diff --git a/.ide/formatter.xml b/.ide/formatter.xml new file mode 100644 index 00000000..55933d98 --- /dev/null +++ b/.ide/formatter.xml @@ -0,0 +1,390 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/luaj-core/src/main/java/org/luaj/vm2/Buffer.java b/luaj-core/src/main/java/org/luaj/vm2/Buffer.java index 0a1117c4..a54d4d89 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/Buffer.java +++ b/luaj-core/src/main/java/org/luaj/vm2/Buffer.java @@ -21,61 +21,64 @@ ******************************************************************************/ package org.luaj.vm2; - /** - * String buffer for use in string library methods, optimized for production - * of StrValue instances. + * String buffer for use in string library methods, optimized for production of + * StrValue instances. *

- * 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,170 @@ 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 ); + 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 */ 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 final 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 final 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 final 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 final 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 final 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. - *
 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * globals.load( new StringReader("print 'hello'"), "main.lua" ).call(); 
- * } 
+ *

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. + * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	globals.load(new StringReader("print 'hello'"), "main.lua").call();
+ * }
+ * 
+ * * The creates a complete global environment with the standard libraries loaded. *

- * For specialized circumstances, the Globals may be constructed directly and loaded - * with only those libraries that are needed, for example. - *

 {@code
- * Globals globals = new Globals();
- * globals.load( new BaseLib() ); 
- * } 
+ * For specialized circumstances, the Globals may be constructed directly and + * loaded with only those libraries that are needed, for example. * - *

Loading and Executing Lua Code

- * Globals contains convenience functions to load and execute lua source code given a Reader. - * A simple example is: - *
 {@code
+ * 
+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new BaseLib());
+ * }
+ * 
+ * + *

Loading and Executing Lua Code

Globals contains convenience + * functions to load and execute lua source code given a Reader. A simple + * example is: + * + *
+ *  {@code
  * globals.load( new StringReader("print 'hello'"), "main.lua" ).call(); 
- * } 
+ * } + *
* - *

Fine-Grained Control of Compiling and Loading Lua

- * Executable LuaFunctions are created from lua code in several steps + *

Fine-Grained Control of Compiling and Loading Lua

Executable + * LuaFunctions are created from lua code in several steps * *

- * 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. *

* - *

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: * * - *

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. * * - *

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 @@ -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,142 @@ 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. + */ 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 +333,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 +363,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 +389,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 +407,27 @@ 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(); } + public void close() throws IOException { i = n; } + public int read() throws IOException { - return i < n ? s.charAt(i++) : -1; + return i < n? s.charAt(i++): -1; } + 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 +436,61 @@ 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; + public int read() throws IOException { int a = avail(); - return (a <= 0 ? -1 : 0xff & b[i++]); + return (a <= 0? -1: 0xff & b[i++]); } + public int read(byte[] b) throws IOException { return read(b, 0, b.length); } + 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; } + 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; - } + } + 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; } + 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 +504,38 @@ public class Globals extends LuaTable { j = LuaString.encodeToUtf8(c, n, b, i = 0); return j; } + 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; } + 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 +548,25 @@ public class Globals extends LuaTable { j += n; return n; } + public void close() throws IOException { s.close(); } + 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; } } + public boolean markSupported() { return true; } + public synchronized void reset() throws IOException { i = 0; } diff --git a/luaj-core/src/main/java/org/luaj/vm2/LoadState.java b/luaj-core/src/main/java/org/luaj/vm2/LoadState.java index 8d71a74a..c8624556 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/LoadState.java +++ b/luaj-core/src/main/java/org/luaj/vm2/LoadState.java @@ -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: -*

 {@code
-* Globals globals = JsePlatform.standardGlobals();
-* LuaValue chunk = globasl.load("print('hello, world')", "main.lua");
-* chunk.call();
-* } 
-* 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: + * + *

+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	LuaValue chunk = globasl.load("print('hello, world')", "main.lua");
+ * 	chunk.call();
+ * }
+ * 
+ * + * 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
 * Prototypep = LoadState.instance.undump(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua");
 * LuaClosure c = new LuaClosure(p, globals);
 * c.call();
-* } 
-* -* -* More commonly, the {@link Globals.Undumper} may be used to undump them: -*
 {@code
-* Prototype p = globals.loadPrototype(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua", "b");
-* LuaClosure c = new LuaClosure(p, globals);
-* c.call();
-* } 
-* -* @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) -*/ +* } + *
+ * + * + * More commonly, the {@link Globals.Undumper} may be used to undump them: + * + *
+ * {
+ * 	@code
+ * 	Prototype p = globals.loadPrototype(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua", "b");
+ * 	LuaClosure c = new LuaClosure(p, globals);
+ * 	c.call();
+ * }
+ * 
+ * + * @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,127 +177,141 @@ 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; @@ -280,7 +319,7 @@ public class LoadState { 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,19 +332,18 @@ 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; f.upvalues[i] = new Upvaldesc(null, instack, idx); @@ -314,28 +352,30 @@ public class LoadState { /** * 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,39 +53,37 @@ 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<<(SIZE_B-1)); /** test whether value is a constant */ public static boolean ISK(int x) { @@ -147,22 +143,20 @@ public class Lua { /** gets the index of the constant */ public static int INDEXK(int r) { - return ((int)(r) & ~BITRK); + return ((int) (r) & ~BITRK); } - public static final int MAXINDEXRK = (BITRK - 1); + public static final int MAXINDEXRK = (BITRK-1); /** code a constant index as a RK value */ public static int RKASK(int x) { return ((x) | BITRK); } - /** - ** invalid register that fits in 8 bits - */ - public static final int NO_REG = MAXARG_A; - + ** invalid register that fits in 8 bits + */ + public static final int NO_REG = MAXARG_A; /* ** R(x) - register @@ -170,7 +164,6 @@ public class Lua { ** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x) */ - /* ** grep "ORDER OP" if you change these enums */ @@ -178,18 +171,18 @@ public class Lua { /*---------------------------------------------------------------------- name args description ------------------------------------------------------------------------*/ - public static final int OP_MOVE = 0;/* A B R(A) := R(B) */ - public static final int OP_LOADK = 1;/* A Bx R(A) := Kst(Bx) */ - public static final int OP_LOADKX = 2;/* A R(A) := Kst(extra arg) */ - public static final int OP_LOADBOOL = 3;/* A B C R(A) := (Bool)B; if (C) pc++ */ - public static final int OP_LOADNIL = 4; /* A B R(A) := ... := R(A+B) := nil */ + public static final int OP_MOVE = 0; /* A B R(A) := R(B) */ + public static final int OP_LOADK = 1; /* A Bx R(A) := Kst(Bx) */ + public static final int OP_LOADKX = 2; /* A R(A) := Kst(extra arg) */ + public static final int OP_LOADBOOL = 3; /* A B C R(A) := (Bool)B; if (C) pc++ */ + public static final int OP_LOADNIL = 4; /* A B R(A) := ... := R(A+B) := nil */ public static final int OP_GETUPVAL = 5; /* A B R(A) := UpValue[B] */ public static final int OP_GETTABUP = 6; /* A B C R(A) := UpValue[B][RK(C)] */ public static final int OP_GETTABLE = 7; /* A B C R(A) := R(B)[RK(C)] */ - public static final int OP_SETTABUP = 8; /* A B C UpValue[A][RK(B)] := RK(C) */ - public static final int OP_SETUPVAL = 9; /* A B UpValue[B] := R(A) */ + public static final int OP_SETTABUP = 8; /* A B C UpValue[A][RK(B)] := RK(C) */ + public static final int OP_SETUPVAL = 9; /* A B UpValue[B] := R(A) */ public static final int OP_SETTABLE = 10; /* A B C R(A)[RK(B)] := RK(C) */ public static final int OP_NEWTABLE = 11; /* A B C R(A) := {} (size = B,C) */ @@ -209,24 +202,24 @@ public class Lua { public static final int OP_CONCAT = 22; /* A B C R(A) := R(B).. ... ..R(C) */ public static final int OP_JMP = 23; /* A sBx pc+=sBx; if (A) close all upvalues >= 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) @@ -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/luaj-core/src/main/java/org/luaj/vm2/LuaBoolean.java b/luaj-core/src/main/java/org/luaj/vm2/LuaBoolean.java index 33103415..e0a40415 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/LuaBoolean.java +++ b/luaj-core/src/main/java/org/luaj/vm2/LuaBoolean.java @@ -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; @@ -70,11 +70,12 @@ public final class LuaBoolean extends LuaValue { } 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() { @@ -86,18 +87,18 @@ public final class LuaBoolean extends LuaValue { } public String tojstring() { - return v ? "true" : "false"; + return v? "true": "false"; } public boolean optboolean(boolean defval) { return this.v; } - + public boolean checkboolean() { return v; } - - public LuaValue getmetatable() { - return s_metatable; + + public LuaValue getmetatable() { + return s_metatable; } } diff --git a/luaj-core/src/main/java/org/luaj/vm2/LuaClosure.java b/luaj-core/src/main/java/org/luaj/vm2/LuaClosure.java index 46a3556f..aa3ac55b 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/LuaClosure.java +++ b/luaj-core/src/main/java/org/luaj/vm2/LuaClosure.java @@ -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}: + * + *
+ * {
+ * 	@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 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: *

    *
  • {@link LuaValue#call()}
  • *
  • {@link LuaValue#call(LuaValue)}
  • @@ -73,8 +85,9 @@ import org.luaj.vm2.lib.DebugLib.CallFrame; *
  • {@link LuaValue#method(String,LuaValue)}
  • *
  • {@link LuaValue#invokemethod(String)}
  • *
  • {@link LuaValue#invokemethod(String,Varargs)}
  • - *
  • ...
  • + *
  • ...
  • *
+ * * @see LuaValue * @see LuaFunction * @see LuaValue#isclosure() @@ -85,16 +98,19 @@ import org.luaj.vm2.lib.DebugLib.CallFrame; */ public class LuaClosure extends LuaFunction { private static final UpValue[] NOUPVALUES = new UpValue[0]; - + 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,21 +118,20 @@ public class LuaClosure extends LuaFunction { this.initupvalue1(env); globals = env instanceof Globals? (Globals) env: null; } - + 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); } } - public boolean isclosure() { return true; } - + public LuaClosure optclosure(LuaClosure defval) { return this; } @@ -124,379 +139,435 @@ public class LuaClosure extends LuaFunction { public LuaClosure checkclosure() { return this; } - + 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; } - + public final LuaValue call() { LuaValue[] stack = getNewStack(); - return execute(stack,NONE).arg1(); + return execute(stack, NONE).arg1(); } 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(); } } - + 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(); } } 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(); } } public final Varargs invoke(Varargs varargs) { return onInvoke(varargs).eval(); } - + 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); - + // 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] = 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) >>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])); + v = stack[a].invoke(varargsOf(stack[a+1], stack[a+2])); c = (i>>14) & 0x1ff; - while (--c >= 0) + 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 +598,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 +628,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.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 +656,13 @@ 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); } public String name() { - return "<"+p.shortsource()+":"+p.linedefined+">"; + return "<" + p.shortsource() + ":" + p.linedefined + ">"; } - - + } diff --git a/luaj-core/src/main/java/org/luaj/vm2/LuaDouble.java b/luaj-core/src/main/java/org/luaj/vm2/LuaDouble.java index 0c5cdd66..0f801031 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/LuaDouble.java +++ b/luaj-core/src/main/java/org/luaj/vm2/LuaDouble.java @@ -26,18 +26,21 @@ import org.luaj.vm2.lib.MathLib; /** * Extension of {@link LuaNumber} which can hold a Java double 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 values which can be represented as int - * are wrapped in {@link LuaInteger} instead of {@link LuaDouble}. + * 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 values which + * can be represented as int are wrapped in {@link LuaInteger} instead of + * {@link LuaDouble}. *

- * Almost all API's implemented in LuaDouble are defined and documented in {@link LuaValue}. + * 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. + * {@link #JSTR_NAN}, {@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 + * LuaDouble also defines functions for handling the unique math rules of lua + * devision and modulo in *

    *
  • {@link #ddiv(double, double)}
  • *
  • {@link #ddiv_d(double, double)}
  • @@ -45,6 +48,7 @@ import org.luaj.vm2.lib.MathLib; *
  • {@link #dmod_d(double, double)}
  • *
*

+ * * @see LuaValue * @see LuaNumber * @see LuaInteger @@ -54,186 +58,260 @@ import org.luaj.vm2.lib.MathLib; public class LuaDouble extends LuaNumber { /** Constant LuaDouble representing NaN (not a number) */ - public static final LuaDouble NAN = new LuaDouble( Double.NaN ); - + public static final LuaDouble NAN = new LuaDouble(Double.NaN); + /** Constant LuaDouble representing positive infinity */ - public static final LuaDouble POSINF = new LuaDouble( Double.POSITIVE_INFINITY ); - + public static final LuaDouble POSINF = new LuaDouble(Double.POSITIVE_INFINITY); + /** Constant LuaDouble representing negative infinity */ - public static final LuaDouble NEGINF = new LuaDouble( Double.NEGATIVE_INFINITY ); - + public static final LuaDouble NEGINF = new LuaDouble(Double.NEGATIVE_INFINITY); + /** Constant String representation for NaN (not a number), "nan" */ - public static final String JSTR_NAN = "nan"; - + public static final String JSTR_NAN = "nan"; + /** Constant String representation for positive infinity, "inf" */ public static final String JSTR_POSINF = "inf"; /** Constant String representation for negative infinity, "-inf" */ public static final String JSTR_NEGINF = "-inf"; - + /** The value being held by this instance. */ final double v; public static LuaNumber valueOf(double d) { int id = (int) d; - return d==id? (LuaNumber) LuaInteger.valueOf(id): (LuaNumber) new LuaDouble(d); + return d == id? (LuaNumber) LuaInteger.valueOf(id): (LuaNumber) new LuaDouble(d); } - - /** Don't allow ints to be boxed by DoubleValues */ + + /** Don't allow ints to be boxed by DoubleValues */ private LuaDouble(double d) { this.v = d; } public int hashCode() { - long l = Double.doubleToLongBits(v + 1); - return ((int)(l>>32)) + (int) l; + long l = Double.doubleToLongBits(v+1); + return ((int) (l>>32))+(int) l; } - + public boolean islong() { return v == (long) v; } - - public byte tobyte() { return (byte) (long) v; } - public char tochar() { return (char) (long) v; } - public double todouble() { return v; } - public float tofloat() { return (float) v; } - public int toint() { return (int) (long) v; } - public long tolong() { return (long) v; } - public short toshort() { return (short) (long) v; } - public double optdouble(double defval) { return v; } - public int optint(int defval) { return (int) (long) v; } - public LuaInteger optinteger(LuaInteger defval) { return LuaInteger.valueOf((int) (long)v); } - public long optlong(long defval) { return (long) v; } - - public LuaInteger checkinteger() { return LuaInteger.valueOf( (int) (long) v ); } - + public byte tobyte() { return (byte) (long) v; } + + public char tochar() { return (char) (long) v; } + + public double todouble() { return v; } + + public float tofloat() { return (float) v; } + + public int toint() { return (int) (long) v; } + + public long tolong() { return (long) v; } + + public short toshort() { return (short) (long) v; } + + public double optdouble(double defval) { return v; } + + public int optint(int defval) { return (int) (long) v; } + + public LuaInteger optinteger(LuaInteger defval) { return LuaInteger.valueOf((int) (long) v); } + + public long optlong(long defval) { return (long) v; } + + public LuaInteger checkinteger() { return LuaInteger.valueOf((int) (long) v); } + // unary operators public LuaValue neg() { return valueOf(-v); } - + // object equality, used for key comparison - public boolean equals(Object o) { return o instanceof LuaDouble? ((LuaDouble)o).v == v: false; } - + public boolean equals(Object o) { return o instanceof LuaDouble? ((LuaDouble) o).v == v: false; } + // equality w/ metatable processing - public LuaValue eq( LuaValue val ) { return val.raweq(v)? TRUE: FALSE; } - public boolean eq_b( LuaValue val ) { return val.raweq(v); } + public LuaValue eq(LuaValue val) { return val.raweq(v)? TRUE: FALSE; } + + public boolean eq_b(LuaValue val) { return val.raweq(v); } // equality w/o metatable processing - public boolean raweq( LuaValue val ) { return val.raweq(v); } - public boolean raweq( double val ) { return v == val; } - public boolean raweq( int val ) { return v == val; } - + public boolean raweq(LuaValue val) { return val.raweq(v); } + + public boolean raweq(double val) { return v == val; } + + public boolean raweq(int val) { return v == val; } + // basic binary arithmetic - public LuaValue add( LuaValue rhs ) { return rhs.add(v); } - public LuaValue add( double lhs ) { return LuaDouble.valueOf(lhs + v); } - public LuaValue sub( LuaValue rhs ) { return rhs.subFrom(v); } - public LuaValue sub( double rhs ) { return LuaDouble.valueOf(v - rhs); } - public LuaValue sub( int rhs ) { return LuaDouble.valueOf(v - rhs); } - public LuaValue subFrom( double lhs ) { return LuaDouble.valueOf(lhs - v); } - public LuaValue mul( LuaValue rhs ) { return rhs.mul(v); } - public LuaValue mul( double lhs ) { return LuaDouble.valueOf(lhs * v); } - public LuaValue mul( int lhs ) { return LuaDouble.valueOf(lhs * v); } - public LuaValue pow( LuaValue rhs ) { return rhs.powWith(v); } - public LuaValue pow( double rhs ) { return MathLib.dpow(v,rhs); } - public LuaValue pow( int rhs ) { return MathLib.dpow(v,rhs); } - public LuaValue powWith( double lhs ) { return MathLib.dpow(lhs,v); } - public LuaValue powWith( int lhs ) { return MathLib.dpow(lhs,v); } - public LuaValue div( LuaValue rhs ) { return rhs.divInto(v); } - public LuaValue div( double rhs ) { return LuaDouble.ddiv(v,rhs); } - public LuaValue div( int rhs ) { return LuaDouble.ddiv(v,rhs); } - public LuaValue divInto( double lhs ) { return LuaDouble.ddiv(lhs,v); } - public LuaValue mod( LuaValue rhs ) { return rhs.modFrom(v); } - public LuaValue mod( double rhs ) { return LuaDouble.dmod(v,rhs); } - public LuaValue mod( int rhs ) { return LuaDouble.dmod(v,rhs); } - public LuaValue modFrom( double lhs ) { return LuaDouble.dmod(lhs,v); } - - - /** Divide two double numbers according to lua math, and return a {@link LuaValue} result. + public LuaValue add(LuaValue rhs) { return rhs.add(v); } + + public LuaValue add(double lhs) { return LuaDouble.valueOf(lhs+v); } + + public LuaValue sub(LuaValue rhs) { return rhs.subFrom(v); } + + public LuaValue sub(double rhs) { return LuaDouble.valueOf(v-rhs); } + + public LuaValue sub(int rhs) { return LuaDouble.valueOf(v-rhs); } + + public LuaValue subFrom(double lhs) { return LuaDouble.valueOf(lhs-v); } + + public LuaValue mul(LuaValue rhs) { return rhs.mul(v); } + + public LuaValue mul(double lhs) { return LuaDouble.valueOf(lhs*v); } + + public LuaValue mul(int lhs) { return LuaDouble.valueOf(lhs*v); } + + public LuaValue pow(LuaValue rhs) { return rhs.powWith(v); } + + public LuaValue pow(double rhs) { return MathLib.dpow(v, rhs); } + + public LuaValue pow(int rhs) { return MathLib.dpow(v, rhs); } + + public LuaValue powWith(double lhs) { return MathLib.dpow(lhs, v); } + + public LuaValue powWith(int lhs) { return MathLib.dpow(lhs, v); } + + public LuaValue div(LuaValue rhs) { return rhs.divInto(v); } + + public LuaValue div(double rhs) { return LuaDouble.ddiv(v, rhs); } + + public LuaValue div(int rhs) { return LuaDouble.ddiv(v, rhs); } + + public LuaValue divInto(double lhs) { return LuaDouble.ddiv(lhs, v); } + + public LuaValue mod(LuaValue rhs) { return rhs.modFrom(v); } + + public LuaValue mod(double rhs) { return LuaDouble.dmod(v, rhs); } + + public LuaValue mod(int rhs) { return LuaDouble.dmod(v, rhs); } + + public LuaValue modFrom(double lhs) { return LuaDouble.dmod(lhs, v); } + + /** + * Divide two double numbers according to lua math, and return a + * {@link LuaValue} result. + * * @param lhs Left-hand-side of the division. * @param rhs Right-hand-side of the division. - * @return {@link LuaValue} for the result of the division, - * taking into account positive and negiative infinity, and Nan + * @return {@link LuaValue} for the result of the division, taking into + * account positive and negiative infinity, and Nan * @see #ddiv_d(double, double) */ public static LuaValue ddiv(double lhs, double rhs) { - return rhs!=0? valueOf( lhs / rhs ): lhs>0? POSINF: lhs==0? NAN: NEGINF; + return rhs != 0? valueOf(lhs/rhs): lhs > 0? POSINF: lhs == 0? NAN: NEGINF; } - - /** Divide two double numbers according to lua math, and return a double result. + + /** + * Divide two double numbers according to lua math, and return a double + * result. + * * @param lhs Left-hand-side of the division. * @param rhs Right-hand-side of the division. - * @return Value of the division, taking into account positive and negative infinity, and Nan + * @return Value of the division, taking into account positive and negative + * infinity, and Nan * @see #ddiv(double, double) */ public static double ddiv_d(double lhs, double rhs) { - return rhs!=0? lhs / rhs: lhs>0? Double.POSITIVE_INFINITY: lhs==0? Double.NaN: Double.NEGATIVE_INFINITY; + return rhs != 0? lhs/rhs: lhs > 0? Double.POSITIVE_INFINITY: lhs == 0? Double.NaN: Double.NEGATIVE_INFINITY; } - - /** Take modulo double numbers according to lua math, and return a {@link LuaValue} result. + + /** + * Take modulo double numbers according to lua math, and return a + * {@link LuaValue} result. + * * @param lhs Left-hand-side of the modulo. * @param rhs Right-hand-side of the modulo. - * @return {@link LuaValue} for the result of the modulo, - * using lua's rules for modulo + * @return {@link LuaValue} for the result of the modulo, using lua's rules + * for modulo * @see #dmod_d(double, double) */ public static LuaValue dmod(double lhs, double rhs) { - if (rhs == 0 || lhs == Double.POSITIVE_INFINITY || lhs == Double.NEGATIVE_INFINITY) return NAN; + if (rhs == 0 || lhs == Double.POSITIVE_INFINITY || lhs == Double.NEGATIVE_INFINITY) + return NAN; if (rhs == Double.POSITIVE_INFINITY) { - return lhs < 0 ? POSINF : valueOf(lhs); + return lhs < 0? POSINF: valueOf(lhs); } if (rhs == Double.NEGATIVE_INFINITY) { - return lhs > 0 ? NEGINF : valueOf(lhs); + return lhs > 0? NEGINF: valueOf(lhs); } - return valueOf( lhs-rhs*Math.floor(lhs/rhs) ); + return valueOf(lhs-rhs*Math.floor(lhs/rhs)); } - /** Take modulo for double numbers according to lua math, and return a double result. + /** + * Take modulo for double numbers according to lua math, and return a double + * result. + * * @param lhs Left-hand-side of the modulo. * @param rhs Right-hand-side of the modulo. - * @return double value for the result of the modulo, - * using lua's rules for modulo + * @return double value for the result of the modulo, using lua's rules for + * modulo * @see #dmod(double, double) */ public static double dmod_d(double lhs, double rhs) { - if (rhs == 0 || lhs == Double.POSITIVE_INFINITY || lhs == Double.NEGATIVE_INFINITY) return Double.NaN; + if (rhs == 0 || lhs == Double.POSITIVE_INFINITY || lhs == Double.NEGATIVE_INFINITY) + return Double.NaN; if (rhs == Double.POSITIVE_INFINITY) { - return lhs < 0 ? Double.POSITIVE_INFINITY : lhs; + return lhs < 0? Double.POSITIVE_INFINITY: lhs; } if (rhs == Double.NEGATIVE_INFINITY) { - return lhs > 0 ? Double.NEGATIVE_INFINITY : lhs; + return lhs > 0? Double.NEGATIVE_INFINITY: lhs; } return lhs-rhs*Math.floor(lhs/rhs); } // relational operators - public LuaValue lt( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.gt_b(v)? TRUE: FALSE) : super.lt(rhs); } - public LuaValue lt( double rhs ) { return v < rhs? TRUE: FALSE; } - public LuaValue lt( int rhs ) { return v < rhs? TRUE: FALSE; } - public boolean lt_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.gt_b(v) : super.lt_b(rhs); } - public boolean lt_b( int rhs ) { return v < rhs; } - public boolean lt_b( double rhs ) { return v < rhs; } - public LuaValue lteq( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.gteq_b(v)? TRUE: FALSE) : super.lteq(rhs); } - public LuaValue lteq( double rhs ) { return v <= rhs? TRUE: FALSE; } - public LuaValue lteq( int rhs ) { return v <= rhs? TRUE: FALSE; } - public boolean lteq_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.gteq_b(v) : super.lteq_b(rhs); } - public boolean lteq_b( int rhs ) { return v <= rhs; } - public boolean lteq_b( double rhs ) { return v <= rhs; } - public LuaValue gt( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.lt_b(v)? TRUE: FALSE) : super.gt(rhs); } - public LuaValue gt( double rhs ) { return v > rhs? TRUE: FALSE; } - public LuaValue gt( int rhs ) { return v > rhs? TRUE: FALSE; } - public boolean gt_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.lt_b(v) : super.gt_b(rhs); } - public boolean gt_b( int rhs ) { return v > rhs; } - public boolean gt_b( double rhs ) { return v > rhs; } - public LuaValue gteq( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.lteq_b(v)? TRUE: FALSE) : super.gteq(rhs); } - public LuaValue gteq( double rhs ) { return v >= rhs? TRUE: FALSE; } - public LuaValue gteq( int rhs ) { return v >= rhs? TRUE: FALSE; } - public boolean gteq_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.lteq_b(v) : super.gteq_b(rhs); } - public boolean gteq_b( int rhs ) { return v >= rhs; } - public boolean gteq_b( double rhs ) { return v >= rhs; } - + public LuaValue lt(LuaValue rhs) { return rhs instanceof LuaNumber? (rhs.gt_b(v)? TRUE: FALSE): super.lt(rhs); } + + public LuaValue lt(double rhs) { return v < rhs? TRUE: FALSE; } + + public LuaValue lt(int rhs) { return v < rhs? TRUE: FALSE; } + + public boolean lt_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.gt_b(v): super.lt_b(rhs); } + + public boolean lt_b(int rhs) { return v < rhs; } + + public boolean lt_b(double rhs) { return v < rhs; } + + public LuaValue lteq(LuaValue rhs) { + return rhs instanceof LuaNumber? (rhs.gteq_b(v)? TRUE: FALSE): super.lteq(rhs); + } + + public LuaValue lteq(double rhs) { return v <= rhs? TRUE: FALSE; } + + public LuaValue lteq(int rhs) { return v <= rhs? TRUE: FALSE; } + + public boolean lteq_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.gteq_b(v): super.lteq_b(rhs); } + + public boolean lteq_b(int rhs) { return v <= rhs; } + + public boolean lteq_b(double rhs) { return v <= rhs; } + + public LuaValue gt(LuaValue rhs) { return rhs instanceof LuaNumber? (rhs.lt_b(v)? TRUE: FALSE): super.gt(rhs); } + + public LuaValue gt(double rhs) { return v > rhs? TRUE: FALSE; } + + public LuaValue gt(int rhs) { return v > rhs? TRUE: FALSE; } + + public boolean gt_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.lt_b(v): super.gt_b(rhs); } + + public boolean gt_b(int rhs) { return v > rhs; } + + public boolean gt_b(double rhs) { return v > rhs; } + + public LuaValue gteq(LuaValue rhs) { + return rhs instanceof LuaNumber? (rhs.lteq_b(v)? TRUE: FALSE): super.gteq(rhs); + } + + public LuaValue gteq(double rhs) { return v >= rhs? TRUE: FALSE; } + + public LuaValue gteq(int rhs) { return v >= rhs? TRUE: FALSE; } + + public boolean gteq_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.lteq_b(v): super.gteq_b(rhs); } + + public boolean gteq_b(int rhs) { return v >= rhs; } + + public boolean gteq_b(double rhs) { return v >= rhs; } + // string comparison - public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; } - + 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 @@ -242,58 +320,63 @@ public class LuaDouble extends LuaNumber { } */ long l = (long) v; - if ( l == v ) + if (l == v) return Long.toString(l); - if ( Double.isNaN(v) ) + if (Double.isNaN(v)) return JSTR_NAN; - if ( Double.isInfinite(v) ) - return (v<0? JSTR_NEGINF: JSTR_POSINF); - return Float.toString((float)v); + if (Double.isInfinite(v)) + return (v < 0? JSTR_NEGINF: JSTR_POSINF); + return Float.toString((float) v); } - + public LuaString strvalue() { return LuaString.valueOf(tojstring()); } - + public LuaString optstring(LuaString defval) { return LuaString.valueOf(tojstring()); } - + public LuaValue tostring() { return LuaString.valueOf(tojstring()); } - + public String optjstring(String defval) { return tojstring(); } - + public LuaNumber optnumber(LuaNumber defval) { return this; } - + public boolean isnumber() { return true; } - + public boolean isstring() { return true; } - + public LuaValue tonumber() { return this; } - public int checkint() { return (int) (long) v; } - public long checklong() { return (long) v; } - public LuaNumber checknumber() { return this; } - public double checkdouble() { return v; } - + + public int checkint() { return (int) (long) v; } + + public long checklong() { return (long) v; } + + public LuaNumber checknumber() { return this; } + + public double checkdouble() { return v; } + public String checkjstring() { return tojstring(); } + public LuaString checkstring() { return LuaString.valueOf(tojstring()); } - + public boolean isvalidkey() { return !Double.isNaN(v); } diff --git a/luaj-core/src/main/java/org/luaj/vm2/LuaError.java b/luaj-core/src/main/java/org/luaj/vm2/LuaError.java index 37a8df8d..dffe6636 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/LuaError.java +++ b/luaj-core/src/main/java/org/luaj/vm2/LuaError.java @@ -21,38 +21,38 @@ ******************************************************************************/ 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. */ public String getMessage() { if (traceback != null) @@ -65,66 +65,70 @@ public class LuaError extends RuntimeException { 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. + */ + public Throwable getCause() { return cause; } } diff --git a/luaj-core/src/main/java/org/luaj/vm2/LuaFunction.java b/luaj-core/src/main/java/org/luaj/vm2/LuaFunction.java index 83bee86d..e1f8e647 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/LuaFunction.java +++ b/luaj-core/src/main/java/org/luaj/vm2/LuaFunction.java @@ -21,41 +21,39 @@ ******************************************************************************/ 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; public int type() { return TFUNCTION; } - + public String typename() { return "function"; } - + public boolean isfunction() { return true; } - public LuaFunction checkfunction() { + public LuaFunction checkfunction() { return this; } - + public LuaFunction optfunction(LuaFunction defval) { return this; } @@ -72,20 +70,29 @@ public class LuaFunction extends LuaValue { 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 index e5e651dc..867cec74 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/LuaInteger.java +++ b/luaj-core/src/main/java/org/luaj/vm2/LuaInteger.java @@ -26,13 +26,13 @@ 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. + * 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}. + * There are no API's specific to LuaInteger that are useful beyond what is + * already exposed in {@link LuaValue}. * * @see LuaValue * @see LuaNumber @@ -44,16 +44,18 @@ public class LuaInteger extends LuaNumber { private static final LuaInteger[] intValues = new LuaInteger[512]; static { - for ( int i=0; i<512; i++ ) + 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); + 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 + + // 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) @@ -61,38 +63,49 @@ public class LuaInteger extends LuaNumber { */ 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); + 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; } - - public boolean isint() { return true; } - public boolean isinttype() { return true; } - public boolean islong() { return true; } - - public byte tobyte() { return (byte) v; } - public char tochar() { return (char) v; } - public double todouble() { return v; } - public float tofloat() { return v; } - public int toint() { return v; } - public long tolong() { return v; } - public short toshort() { return (short) v; } - public double optdouble(double defval) { return v; } - public int optint(int defval) { return v; } - public LuaInteger optinteger(LuaInteger defval) { return this; } - public long optlong(long defval) { return v; } + public boolean isint() { return true; } + + public boolean isinttype() { return true; } + + public boolean islong() { return true; } + + public byte tobyte() { return (byte) v; } + + public char tochar() { return (char) v; } + + public double todouble() { return v; } + + public float tofloat() { return v; } + + public int toint() { return v; } + + public long tolong() { return v; } + + public short toshort() { return (short) v; } + + public double optdouble(double defval) { return v; } + + public int optint(int defval) { return v; } + + public LuaInteger optinteger(LuaInteger defval) { return this; } + + public long optlong(long defval) { return v; } public String tojstring() { return Integer.toString(v); @@ -101,27 +114,27 @@ public class LuaInteger extends LuaNumber { public LuaString strvalue() { return LuaString.valueOf(Integer.toString(v)); } - + public LuaString optstring(LuaString defval) { return LuaString.valueOf(Integer.toString(v)); } - + public LuaValue tostring() { return LuaString.valueOf(Integer.toString(v)); } - + public String optjstring(String defval) { return Integer.toString(v); } - + public LuaInteger checkinteger() { return this; } - + public boolean isstring() { return true; } - + public int hashCode() { return v; } @@ -131,89 +144,146 @@ public class LuaInteger extends LuaNumber { } // unary operators - public LuaValue neg() { return valueOf(-(long)v); } - + public LuaValue neg() { return valueOf(-(long) v); } + // object equality, used for key comparison - public boolean equals(Object o) { return o instanceof LuaInteger? ((LuaInteger)o).v == v: false; } - + public boolean equals(Object o) { return o instanceof LuaInteger? ((LuaInteger) o).v == v: false; } + // equality w/ metatable processing - public LuaValue eq( LuaValue val ) { return val.raweq(v)? TRUE: FALSE; } - public boolean eq_b( LuaValue val ) { return val.raweq(v); } - + public LuaValue eq(LuaValue val) { return val.raweq(v)? TRUE: FALSE; } + + public boolean eq_b(LuaValue val) { return val.raweq(v); } + // equality w/o metatable processing - public boolean raweq( LuaValue val ) { return val.raweq(v); } - public boolean raweq( double val ) { return v == val; } - public boolean raweq( int val ) { return v == val; } - + public boolean raweq(LuaValue val) { return val.raweq(v); } + + public boolean raweq(double val) { return v == val; } + + public boolean raweq(int val) { return v == val; } + // arithmetic operators - public LuaValue add( LuaValue rhs ) { return rhs.add(v); } - public LuaValue add( double lhs ) { return LuaDouble.valueOf(lhs + v); } - public LuaValue add( int lhs ) { return LuaInteger.valueOf(lhs + (long)v); } - public LuaValue sub( LuaValue rhs ) { return rhs.subFrom(v); } - public LuaValue sub( double rhs ) { return LuaDouble.valueOf(v - rhs); } - public LuaValue sub( int rhs ) { return LuaDouble.valueOf(v - rhs); } - public LuaValue subFrom( double lhs ) { return LuaDouble.valueOf(lhs - v); } - public LuaValue subFrom( int lhs ) { return LuaInteger.valueOf(lhs - (long)v); } - public LuaValue mul( LuaValue rhs ) { return rhs.mul(v); } - public LuaValue mul( double lhs ) { return LuaDouble.valueOf(lhs * v); } - public LuaValue mul( int lhs ) { return LuaInteger.valueOf(lhs * (long)v); } - public LuaValue pow( LuaValue rhs ) { return rhs.powWith(v); } - public LuaValue pow( double rhs ) { return MathLib.dpow(v,rhs); } - public LuaValue pow( int rhs ) { return MathLib.dpow(v,rhs); } - public LuaValue powWith( double lhs ) { return MathLib.dpow(lhs,v); } - public LuaValue powWith( int lhs ) { return MathLib.dpow(lhs,v); } - public LuaValue div( LuaValue rhs ) { return rhs.divInto(v); } - public LuaValue div( double rhs ) { return LuaDouble.ddiv(v,rhs); } - public LuaValue div( int rhs ) { return LuaDouble.ddiv(v,rhs); } - public LuaValue divInto( double lhs ) { return LuaDouble.ddiv(lhs,v); } - public LuaValue mod( LuaValue rhs ) { return rhs.modFrom(v); } - public LuaValue mod( double rhs ) { return LuaDouble.dmod(v,rhs); } - public LuaValue mod( int rhs ) { return LuaDouble.dmod(v,rhs); } - public LuaValue modFrom( double lhs ) { return LuaDouble.dmod(lhs,v); } - + public LuaValue add(LuaValue rhs) { return rhs.add(v); } + + public LuaValue add(double lhs) { return LuaDouble.valueOf(lhs+v); } + + public LuaValue add(int lhs) { return LuaInteger.valueOf(lhs+(long) v); } + + public LuaValue sub(LuaValue rhs) { return rhs.subFrom(v); } + + public LuaValue sub(double rhs) { return LuaDouble.valueOf(v-rhs); } + + public LuaValue sub(int rhs) { return LuaDouble.valueOf(v-rhs); } + + public LuaValue subFrom(double lhs) { return LuaDouble.valueOf(lhs-v); } + + public LuaValue subFrom(int lhs) { return LuaInteger.valueOf(lhs-(long) v); } + + public LuaValue mul(LuaValue rhs) { return rhs.mul(v); } + + public LuaValue mul(double lhs) { return LuaDouble.valueOf(lhs*v); } + + public LuaValue mul(int lhs) { return LuaInteger.valueOf(lhs*(long) v); } + + public LuaValue pow(LuaValue rhs) { return rhs.powWith(v); } + + public LuaValue pow(double rhs) { return MathLib.dpow(v, rhs); } + + public LuaValue pow(int rhs) { return MathLib.dpow(v, rhs); } + + public LuaValue powWith(double lhs) { return MathLib.dpow(lhs, v); } + + public LuaValue powWith(int lhs) { return MathLib.dpow(lhs, v); } + + public LuaValue div(LuaValue rhs) { return rhs.divInto(v); } + + public LuaValue div(double rhs) { return LuaDouble.ddiv(v, rhs); } + + public LuaValue div(int rhs) { return LuaDouble.ddiv(v, rhs); } + + public LuaValue divInto(double lhs) { return LuaDouble.ddiv(lhs, v); } + + public LuaValue mod(LuaValue rhs) { return rhs.modFrom(v); } + + public LuaValue mod(double rhs) { return LuaDouble.dmod(v, rhs); } + + public LuaValue mod(int rhs) { return LuaDouble.dmod(v, rhs); } + + public LuaValue modFrom(double lhs) { return LuaDouble.dmod(lhs, v); } + // relational operators - public LuaValue lt( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.gt_b(v)? TRUE: FALSE) : super.lt(rhs); } - public LuaValue lt( double rhs ) { return v < rhs? TRUE: FALSE; } - public LuaValue lt( int rhs ) { return v < rhs? TRUE: FALSE; } - public boolean lt_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.gt_b(v) : super.lt_b(rhs); } - public boolean lt_b( int rhs ) { return v < rhs; } - public boolean lt_b( double rhs ) { return v < rhs; } - public LuaValue lteq( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.gteq_b(v)? TRUE: FALSE) : super.lteq(rhs); } - public LuaValue lteq( double rhs ) { return v <= rhs? TRUE: FALSE; } - public LuaValue lteq( int rhs ) { return v <= rhs? TRUE: FALSE; } - public boolean lteq_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.gteq_b(v) : super.lteq_b(rhs); } - public boolean lteq_b( int rhs ) { return v <= rhs; } - public boolean lteq_b( double rhs ) { return v <= rhs; } - public LuaValue gt( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.lt_b(v)? TRUE: FALSE) : super.gt(rhs); } - public LuaValue gt( double rhs ) { return v > rhs? TRUE: FALSE; } - public LuaValue gt( int rhs ) { return v > rhs? TRUE: FALSE; } - public boolean gt_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.lt_b(v) : super.gt_b(rhs); } - public boolean gt_b( int rhs ) { return v > rhs; } - public boolean gt_b( double rhs ) { return v > rhs; } - public LuaValue gteq( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.lteq_b(v)? TRUE: FALSE) : super.gteq(rhs); } - public LuaValue gteq( double rhs ) { return v >= rhs? TRUE: FALSE; } - public LuaValue gteq( int rhs ) { return v >= rhs? TRUE: FALSE; } - public boolean gteq_b( LuaValue rhs ) { return rhs instanceof LuaNumber ? rhs.lteq_b(v) : super.gteq_b(rhs); } - public boolean gteq_b( int rhs ) { return v >= rhs; } - public boolean gteq_b( double rhs ) { return v >= rhs; } - + public LuaValue lt(LuaValue rhs) { return rhs instanceof LuaNumber? (rhs.gt_b(v)? TRUE: FALSE): super.lt(rhs); } + + public LuaValue lt(double rhs) { return v < rhs? TRUE: FALSE; } + + public LuaValue lt(int rhs) { return v < rhs? TRUE: FALSE; } + + public boolean lt_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.gt_b(v): super.lt_b(rhs); } + + public boolean lt_b(int rhs) { return v < rhs; } + + public boolean lt_b(double rhs) { return v < rhs; } + + public LuaValue lteq(LuaValue rhs) { + return rhs instanceof LuaNumber? (rhs.gteq_b(v)? TRUE: FALSE): super.lteq(rhs); + } + + public LuaValue lteq(double rhs) { return v <= rhs? TRUE: FALSE; } + + public LuaValue lteq(int rhs) { return v <= rhs? TRUE: FALSE; } + + public boolean lteq_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.gteq_b(v): super.lteq_b(rhs); } + + public boolean lteq_b(int rhs) { return v <= rhs; } + + public boolean lteq_b(double rhs) { return v <= rhs; } + + public LuaValue gt(LuaValue rhs) { return rhs instanceof LuaNumber? (rhs.lt_b(v)? TRUE: FALSE): super.gt(rhs); } + + public LuaValue gt(double rhs) { return v > rhs? TRUE: FALSE; } + + public LuaValue gt(int rhs) { return v > rhs? TRUE: FALSE; } + + public boolean gt_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.lt_b(v): super.gt_b(rhs); } + + public boolean gt_b(int rhs) { return v > rhs; } + + public boolean gt_b(double rhs) { return v > rhs; } + + public LuaValue gteq(LuaValue rhs) { + return rhs instanceof LuaNumber? (rhs.lteq_b(v)? TRUE: FALSE): super.gteq(rhs); + } + + public LuaValue gteq(double rhs) { return v >= rhs? TRUE: FALSE; } + + public LuaValue gteq(int rhs) { return v >= rhs? TRUE: FALSE; } + + public boolean gteq_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.lteq_b(v): super.gteq_b(rhs); } + + public boolean gteq_b(int rhs) { return v >= rhs; } + + public boolean gteq_b(double rhs) { return v >= rhs; } + // string comparison - public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; } - + public int strcmp(LuaString rhs) { typerror("attempt to compare number with string"); return 0; } + public int checkint() { return v; } + public long checklong() { return v; } + public double checkdouble() { return v; } + public String checkjstring() { return String.valueOf(v); } + public LuaString checkstring() { - return valueOf( String.valueOf(v) ); + return valueOf(String.valueOf(v)); } } diff --git a/luaj-core/src/main/java/org/luaj/vm2/LuaNil.java b/luaj-core/src/main/java/org/luaj/vm2/LuaNil.java index 1b247cbd..b0ab3822 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/LuaNil.java +++ b/luaj-core/src/main/java/org/luaj/vm2/LuaNil.java @@ -22,27 +22,27 @@ 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() {} public int type() { @@ -50,59 +50,73 @@ public class LuaNil extends LuaValue { } public String toString() { - return "nil"; + return "nil"; } - + public String typename() { return "nil"; } - + public String tojstring() { return "nil"; } - public LuaValue not() { - return LuaValue.TRUE; + public LuaValue not() { + return LuaValue.TRUE; } - - public boolean toboolean() { - return false; + + public boolean toboolean() { + return false; } - + public boolean isnil() { return true; } - - public LuaValue getmetatable() { - return s_metatable; + + public LuaValue getmetatable() { + return s_metatable; } - + public boolean equals(Object o) { return o instanceof LuaNil; } - public LuaValue checknotnil() { + public LuaValue checknotnil() { return argerror("value"); } - + 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; } + 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; } } diff --git a/luaj-core/src/main/java/org/luaj/vm2/LuaNumber.java b/luaj-core/src/main/java/org/luaj/vm2/LuaNumber.java index ef972218..57fa8d27 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/LuaNumber.java +++ b/luaj-core/src/main/java/org/luaj/vm2/LuaNumber.java @@ -21,61 +21,64 @@ ******************************************************************************/ 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; - + public int type() { return TNUMBER; } - + public String typename() { return "number"; } - + public LuaNumber checknumber() { - return this; + return this; } - + public LuaNumber checknumber(String errmsg) { - return this; + return this; } - + public LuaNumber optnumber(LuaNumber defval) { - return this; + return this; } - + public LuaValue tonumber() { return this; } - + public boolean isnumber() { return true; } - + public boolean isstring() { return true; } - - public LuaValue getmetatable() { - return s_metatable; + + 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); } + 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); } } diff --git a/luaj-core/src/main/java/org/luaj/vm2/LuaString.java b/luaj-core/src/main/java/org/luaj/vm2/LuaString.java index 08c1022b..b0a56eb1 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/LuaString.java +++ b/luaj-core/src/main/java/org/luaj/vm2/LuaString.java @@ -21,7 +21,6 @@ ******************************************************************************/ package org.luaj.vm2; - import java.io.ByteArrayInputStream; import java.io.DataOutputStream; import java.io.IOException; @@ -33,27 +32,27 @@ import org.luaj.vm2.lib.MathLib; /** * Subclass of {@link LuaValue} for representing lua strings. *

- * Because lua string values are more nearly sequences of bytes than - * sequences of characters or unicode code points, the {@link LuaString} - * implementation holds the string value in an internal byte array. + * Because lua string values are more nearly sequences of bytes than sequences + * of characters or unicode code points, the {@link LuaString} implementation + * holds the string value in an internal byte array. *

- * {@link LuaString} values are not considered mutable once constructed, - * so multiple {@link LuaString} values can chare a single byte array. + * {@link LuaString} values are not considered mutable once constructed, so + * multiple {@link LuaString} values can chare a single byte array. *

* Currently {@link LuaString}s are pooled via a centrally managed weak table. * To ensure that as many string values as possible take advantage of this, - * Constructors are not exposed directly. As with number, booleans, and nil, - * instance construction should be via {@link LuaValue#valueOf(byte[])} or similar API. + * Constructors are not exposed directly. As with number, booleans, and nil, + * instance construction should be via {@link LuaValue#valueOf(byte[])} or + * similar API. *

* Because of this pooling, users of LuaString must not directly alter the * bytes in a LuaString, or undefined behavior will result. *

- * When Java Strings are used to initialize {@link LuaString} data, the UTF8 encoding is assumed. - * The functions - * {@link #lengthAsUtf8(char[])}, + * When Java Strings are used to initialize {@link LuaString} data, the UTF8 + * encoding is assumed. The functions {@link #lengthAsUtf8(char[])}, * {@link #encodeToUtf8(char[], int, byte[], int)}, and - * {@link #decodeAsUtf8(byte[], int, int)} - * are used to convert back and forth between UTF8 byte arrays and character arrays. + * {@link #decodeAsUtf8(byte[], int, int)} are used to convert back and forth + * between UTF8 byte arrays and character arrays. * * @see LuaValue * @see LuaValue#valueOf(String) @@ -61,54 +60,66 @@ import org.luaj.vm2.lib.MathLib; */ public class LuaString extends LuaValue { - /** The singleton instance for string metatables that forwards to the string functions. - * Typically, this is set to the string metatable as a side effect of loading the string - * library, and is read-write to provide flexible behavior by default. When used in a - * server environment where there may be roge scripts, this should be replaced with a - * read-only table since it is shared across all lua code in this Java VM. + /** + * The singleton instance for string metatables that forwards to the string + * functions. Typically, this is set to the string metatable as a side + * effect of loading the string library, and is read-write to provide + * flexible behavior by default. When used in a server environment where + * there may be roge scripts, this should be replaced with a read-only table + * since it is shared across all lua code in this Java VM. */ public static LuaValue s_metatable; - - /** The bytes for the string. These must not be mutated directly because - * the backing may be shared by multiple LuaStrings, and the hash code is - * computed only at construction time. - * It is exposed only for performance and legacy reasons. */ + + /** + * The bytes for the string. These must not be mutated + * directly because the backing may be shared by multiple + * LuaStrings, and the hash code is computed only at construction time. It + * is exposed only for performance and legacy reasons. + */ public final byte[] m_bytes; - + /** The offset into the byte array, 0 means start at the first byte */ public final int m_offset; - + /** The number of bytes that comprise this string */ public final int m_length; - - /** The hashcode for this string. Computed at construct time. */ + + /** The hashcode for this string. Computed at construct time. */ private final int m_hashcode; - /** Size of cache of recent short strings. This is the maximum number of LuaStrings that - * will be retained in the cache of recent short strings. Exposed to package for testing. */ + /** + * Size of cache of recent short strings. This is the maximum number of + * LuaStrings that will be retained in the cache of recent short strings. + * Exposed to package for testing. + */ static final int RECENT_STRINGS_CACHE_SIZE = 128; - /** Maximum length of a string to be considered for recent short strings caching. - * This effectively limits the total memory that can be spent on the recent strings cache, - * because no LuaString whose backing exceeds this length will be put into the cache. - * Exposed to package for testing. */ + /** + * Maximum length of a string to be considered for recent short strings + * caching. This effectively limits the total memory that can be spent on + * the recent strings cache, because no LuaString whose backing exceeds this + * length will be put into the cache. Exposed to package for testing. + */ static final int RECENT_STRINGS_MAX_LENGTH = 32; - /** Simple cache of recently created strings that are short. - * This is simply a list of strings, indexed by their hash codes modulo the cache size - * that have been recently constructed. If a string is being constructed frequently - * from different contexts, it will generally show up as a cache hit and resolve - * to the same value. */ + /** + * Simple cache of recently created strings that are short. This is simply a + * list of strings, indexed by their hash codes modulo the cache size that + * have been recently constructed. If a string is being constructed + * frequently from different contexts, it will generally show up as a cache + * hit and resolve to the same value. + */ private static final class RecentShortStrings { - private static final LuaString recent_short_strings[] = - new LuaString[RECENT_STRINGS_CACHE_SIZE]; + private static final LuaString recent_short_strings[] = new LuaString[RECENT_STRINGS_CACHE_SIZE]; } /** - * Get a {@link LuaString} instance whose bytes match - * the supplied Java String using the UTF8 encoding. + * Get a {@link LuaString} instance whose bytes match the supplied Java + * String using the UTF8 encoding. + * * @param string Java String containing characters to encode as UTF8 - * @return {@link LuaString} with UTF8 bytes corresponding to the supplied String + * @return {@link LuaString} with UTF8 bytes corresponding to the supplied + * String */ public static LuaString valueOf(String string) { char[] c = string.toCharArray(); @@ -117,25 +128,29 @@ public class LuaString extends LuaValue { return valueUsing(b, 0, b.length); } - /** Construct a {@link LuaString} for a portion of a byte array. + /** + * Construct a {@link LuaString} for a portion of a byte array. *

- * The array is first be used as the backing for this object, so clients must not change contents. - * If the supplied value for 'len' is more than half the length of the container, the - * supplied byte array will be used as the backing, otherwise the bytes will be copied to a - * new byte array, and cache lookup may be performed. + * The array is first be used as the backing for this object, so clients + * must not change contents. If the supplied value for 'len' is more than + * half the length of the container, the supplied byte array will be used as + * the backing, otherwise the bytes will be copied to a new byte array, and + * cache lookup may be performed. *

+ * * @param bytes byte buffer - * @param off offset into the byte buffer - * @param len length of the byte buffer + * @param off offset into the byte buffer + * @param len length of the byte buffer * @return {@link LuaString} wrapping the byte buffer */ public static LuaString valueOf(byte[] bytes, int off, int len) { if (len > RECENT_STRINGS_MAX_LENGTH) return valueFromCopy(bytes, off, len); final int hash = hashCode(bytes, off, len); - final int bucket = hash & (RECENT_STRINGS_CACHE_SIZE - 1); + final int bucket = hash & (RECENT_STRINGS_CACHE_SIZE-1); final LuaString t = RecentShortStrings.recent_short_strings[bucket]; - if (t != null && t.m_hashcode == hash && t.byteseq(bytes, off, len)) return t; + if (t != null && t.m_hashcode == hash && t.byteseq(bytes, off, len)) + return t; final LuaString s = valueFromCopy(bytes, off, len); RecentShortStrings.recent_short_strings[bucket] = s; return s; @@ -148,75 +163,96 @@ public class LuaString extends LuaValue { return new LuaString(copy, 0, len); } - /** Construct a {@link LuaString} around, possibly using the the supplied + /** + * Construct a {@link LuaString} around, possibly using the the supplied * byte array as the backing store. *

* The caller must ensure that the array is not mutated after the call. * However, if the string is short enough the short-string cache is checked * for a match which may be used instead of the supplied byte array. *

+ * * @param bytes byte buffer - * @return {@link LuaString} wrapping the byte buffer, or an equivalent string. + * @return {@link LuaString} wrapping the byte buffer, or an equivalent + * string. */ static public LuaString valueUsing(byte[] bytes, int off, int len) { if (bytes.length > RECENT_STRINGS_MAX_LENGTH) return new LuaString(bytes, off, len); final int hash = hashCode(bytes, off, len); - final int bucket = hash & (RECENT_STRINGS_CACHE_SIZE - 1); + final int bucket = hash & (RECENT_STRINGS_CACHE_SIZE-1); final LuaString t = RecentShortStrings.recent_short_strings[bucket]; - if (t != null && t.m_hashcode == hash && t.byteseq(bytes, off, len)) return t; + if (t != null && t.m_hashcode == hash && t.byteseq(bytes, off, len)) + return t; final LuaString s = new LuaString(bytes, off, len); RecentShortStrings.recent_short_strings[bucket] = s; return s; } - /** Construct a {@link LuaString} using the supplied characters as byte values. + /** + * Construct a {@link LuaString} using the supplied characters as byte + * values. *

- * Only the low-order 8-bits of each character are used, the remainder is ignored. + * Only the low-order 8-bits of each character are used, the remainder is + * ignored. *

- * This is most useful for constructing byte sequences that do not conform to UTF8. - * @param bytes array of char, whose values are truncated at 8-bits each and put into a byte array. + * This is most useful for constructing byte sequences that do not conform + * to UTF8. + * + * @param bytes array of char, whose values are truncated at 8-bits each and + * put into a byte array. * @return {@link LuaString} wrapping a copy of the byte buffer */ public static LuaString valueOf(char[] bytes) { return valueOf(bytes, 0, bytes.length); } - /** Construct a {@link LuaString} using the supplied characters as byte values. + /** + * Construct a {@link LuaString} using the supplied characters as byte + * values. *

- * Only the low-order 8-bits of each character are used, the remainder is ignored. + * Only the low-order 8-bits of each character are used, the remainder is + * ignored. *

- * This is most useful for constructing byte sequences that do not conform to UTF8. - * @param bytes array of char, whose values are truncated at 8-bits each and put into a byte array. + * This is most useful for constructing byte sequences that do not conform + * to UTF8. + * + * @param bytes array of char, whose values are truncated at 8-bits each and + * put into a byte array. * @return {@link LuaString} wrapping a copy of the byte buffer */ public static LuaString valueOf(char[] bytes, int off, int len) { byte[] b = new byte[len]; - for ( int i=0; i * The LuaString returned will either be a new LuaString containing a copy - * of the bytes array, or be an existing LuaString used already having the same value. + * of the bytes array, or be an existing LuaString used already having the + * same value. *

+ * * @param bytes byte buffer * @return {@link LuaString} wrapping the byte buffer */ public static LuaString valueOf(byte[] bytes) { return valueOf(bytes, 0, bytes.length); } - - /** Construct a {@link LuaString} for all the bytes in a byte array, possibly using - * the supplied array as the backing store. + + /** + * Construct a {@link LuaString} for all the bytes in a byte array, possibly + * using the supplied array as the backing store. *

- * The LuaString returned will either be a new LuaString containing the byte array, - * or be an existing LuaString used already having the same value. + * The LuaString returned will either be a new LuaString containing the byte + * array, or be an existing LuaString used already having the same value. *

- * The caller must not mutate the contents of the byte array after this call, as - * it may be used elsewhere due to recent short string caching. + * The caller must not mutate the contents of the byte array after this + * call, as it may be used elsewhere due to recent short string caching. + * * @param bytes byte buffer * @return {@link LuaString} wrapping the byte buffer */ @@ -224,11 +260,15 @@ public class LuaString extends LuaValue { return valueUsing(bytes, 0, bytes.length); } - /** Construct a {@link LuaString} around a byte array without copying the contents. + /** + * Construct a {@link LuaString} around a byte array without copying the + * contents. *

- * The array is used directly after this is called, so clients must not change contents. + * The array is used directly after this is called, so clients must not + * change contents. *

- * @param bytes byte buffer + * + * @param bytes byte buffer * @param offset offset into the byte buffer * @param length length of the byte buffer * @return {@link LuaString} wrapping the byte buffer @@ -243,11 +283,11 @@ public class LuaString extends LuaValue { public boolean isstring() { return true; } - + public LuaValue getmetatable() { return s_metatable; } - + public int type() { return LuaValue.TSTRING; } @@ -255,7 +295,7 @@ public class LuaString extends LuaValue { public String typename() { return "string"; } - + public String tojstring() { return decodeAsUtf8(m_bytes, m_offset, m_length); } @@ -264,53 +304,119 @@ public class LuaString extends LuaValue { public LuaValue neg() { double d = scannumber(); return Double.isNaN(d)? super.neg(): valueOf(-d); } // basic binary arithmetic - public LuaValue add( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(ADD,rhs): rhs.add(d); } - public LuaValue add( double rhs ) { return valueOf( checkarith() + rhs ); } - public LuaValue add( int rhs ) { return valueOf( checkarith() + rhs ); } - public LuaValue sub( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(SUB,rhs): rhs.subFrom(d); } - public LuaValue sub( double rhs ) { return valueOf( checkarith() - rhs ); } - public LuaValue sub( int rhs ) { return valueOf( checkarith() - rhs ); } - public LuaValue subFrom( double lhs ) { return valueOf( lhs - checkarith() ); } - public LuaValue mul( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(MUL,rhs): rhs.mul(d); } - public LuaValue mul( double rhs ) { return valueOf( checkarith() * rhs ); } - public LuaValue mul( int rhs ) { return valueOf( checkarith() * rhs ); } - public LuaValue pow( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(POW,rhs): rhs.powWith(d); } - public LuaValue pow( double rhs ) { return MathLib.dpow(checkarith(),rhs); } - public LuaValue pow( int rhs ) { return MathLib.dpow(checkarith(),rhs); } - public LuaValue powWith( double lhs ) { return MathLib.dpow(lhs, checkarith()); } - public LuaValue powWith( int lhs ) { return MathLib.dpow(lhs, checkarith()); } - public LuaValue div( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(DIV,rhs): rhs.divInto(d); } - public LuaValue div( double rhs ) { return LuaDouble.ddiv(checkarith(),rhs); } - public LuaValue div( int rhs ) { return LuaDouble.ddiv(checkarith(),rhs); } - public LuaValue divInto( double lhs ) { return LuaDouble.ddiv(lhs, checkarith()); } - public LuaValue mod( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(MOD,rhs): rhs.modFrom(d); } - public LuaValue mod( double rhs ) { return LuaDouble.dmod(checkarith(), rhs); } - public LuaValue mod( int rhs ) { return LuaDouble.dmod(checkarith(), rhs); } - public LuaValue modFrom( double lhs ) { return LuaDouble.dmod(lhs, checkarith()); } - + public LuaValue add(LuaValue rhs) { + double d = scannumber(); + return Double.isNaN(d)? arithmt(ADD, rhs): rhs.add(d); + } + + public LuaValue add(double rhs) { return valueOf(checkarith()+rhs); } + + public LuaValue add(int rhs) { return valueOf(checkarith()+rhs); } + + public LuaValue sub(LuaValue rhs) { + double d = scannumber(); + return Double.isNaN(d)? arithmt(SUB, rhs): rhs.subFrom(d); + } + + public LuaValue sub(double rhs) { return valueOf(checkarith()-rhs); } + + public LuaValue sub(int rhs) { return valueOf(checkarith()-rhs); } + + public LuaValue subFrom(double lhs) { return valueOf(lhs-checkarith()); } + + public LuaValue mul(LuaValue rhs) { + double d = scannumber(); + return Double.isNaN(d)? arithmt(MUL, rhs): rhs.mul(d); + } + + public LuaValue mul(double rhs) { return valueOf(checkarith()*rhs); } + + public LuaValue mul(int rhs) { return valueOf(checkarith()*rhs); } + + public LuaValue pow(LuaValue rhs) { + double d = scannumber(); + return Double.isNaN(d)? arithmt(POW, rhs): rhs.powWith(d); + } + + public LuaValue pow(double rhs) { return MathLib.dpow(checkarith(), rhs); } + + public LuaValue pow(int rhs) { return MathLib.dpow(checkarith(), rhs); } + + public LuaValue powWith(double lhs) { return MathLib.dpow(lhs, checkarith()); } + + public LuaValue powWith(int lhs) { return MathLib.dpow(lhs, checkarith()); } + + public LuaValue div(LuaValue rhs) { + double d = scannumber(); + return Double.isNaN(d)? arithmt(DIV, rhs): rhs.divInto(d); + } + + public LuaValue div(double rhs) { return LuaDouble.ddiv(checkarith(), rhs); } + + public LuaValue div(int rhs) { return LuaDouble.ddiv(checkarith(), rhs); } + + public LuaValue divInto(double lhs) { return LuaDouble.ddiv(lhs, checkarith()); } + + public LuaValue mod(LuaValue rhs) { + double d = scannumber(); + return Double.isNaN(d)? arithmt(MOD, rhs): rhs.modFrom(d); + } + + public LuaValue mod(double rhs) { return LuaDouble.dmod(checkarith(), rhs); } + + public LuaValue mod(int rhs) { return LuaDouble.dmod(checkarith(), rhs); } + + public LuaValue modFrom(double lhs) { return LuaDouble.dmod(lhs, checkarith()); } + // relational operators, these only work with other strings - public LuaValue lt( LuaValue rhs ) { return rhs.isstring() ? (rhs.strcmp(this)>0? LuaValue.TRUE: FALSE) : super.lt(rhs); } - public boolean lt_b( LuaValue rhs ) { return rhs.isstring() ? rhs.strcmp(this)>0 : super.lt_b(rhs); } - public boolean lt_b( int rhs ) { typerror("attempt to compare string with number"); return false; } - public boolean lt_b( double rhs ) { typerror("attempt to compare string with number"); return false; } - public LuaValue lteq( LuaValue rhs ) { return rhs.isstring() ? (rhs.strcmp(this)>=0? LuaValue.TRUE: FALSE) : super.lteq(rhs); } - public boolean lteq_b( LuaValue rhs ) { return rhs.isstring() ? rhs.strcmp(this)>=0 : super.lteq_b(rhs); } - public boolean lteq_b( int rhs ) { typerror("attempt to compare string with number"); return false; } - public boolean lteq_b( double rhs ) { typerror("attempt to compare string with number"); return false; } - public LuaValue gt( LuaValue rhs ) { return rhs.isstring() ? (rhs.strcmp(this)<0? LuaValue.TRUE: FALSE) : super.gt(rhs); } - public boolean gt_b( LuaValue rhs ) { return rhs.isstring() ? rhs.strcmp(this)<0 : super.gt_b(rhs); } - public boolean gt_b( int rhs ) { typerror("attempt to compare string with number"); return false; } - public boolean gt_b( double rhs ) { typerror("attempt to compare string with number"); return false; } - public LuaValue gteq( LuaValue rhs ) { return rhs.isstring() ? (rhs.strcmp(this)<=0? LuaValue.TRUE: FALSE) : super.gteq(rhs); } - public boolean gteq_b( LuaValue rhs ) { return rhs.isstring() ? rhs.strcmp(this)<=0 : super.gteq_b(rhs); } - public boolean gteq_b( int rhs ) { typerror("attempt to compare string with number"); return false; } - public boolean gteq_b( double rhs ) { typerror("attempt to compare string with number"); return false; } + public LuaValue lt(LuaValue rhs) { + return rhs.isstring()? (rhs.strcmp(this) > 0? LuaValue.TRUE: FALSE): super.lt(rhs); + } + + public boolean lt_b(LuaValue rhs) { return rhs.isstring()? rhs.strcmp(this) > 0: super.lt_b(rhs); } + + public boolean lt_b(int rhs) { typerror("attempt to compare string with number"); return false; } + + public boolean lt_b(double rhs) { typerror("attempt to compare string with number"); return false; } + + public LuaValue lteq(LuaValue rhs) { + return rhs.isstring()? (rhs.strcmp(this) >= 0? LuaValue.TRUE: FALSE): super.lteq(rhs); + } + + public boolean lteq_b(LuaValue rhs) { return rhs.isstring()? rhs.strcmp(this) >= 0: super.lteq_b(rhs); } + + public boolean lteq_b(int rhs) { typerror("attempt to compare string with number"); return false; } + + public boolean lteq_b(double rhs) { typerror("attempt to compare string with number"); return false; } + + public LuaValue gt(LuaValue rhs) { + return rhs.isstring()? (rhs.strcmp(this) < 0? LuaValue.TRUE: FALSE): super.gt(rhs); + } + + public boolean gt_b(LuaValue rhs) { return rhs.isstring()? rhs.strcmp(this) < 0: super.gt_b(rhs); } + + public boolean gt_b(int rhs) { typerror("attempt to compare string with number"); return false; } + + public boolean gt_b(double rhs) { typerror("attempt to compare string with number"); return false; } + + public LuaValue gteq(LuaValue rhs) { + return rhs.isstring()? (rhs.strcmp(this) <= 0? LuaValue.TRUE: FALSE): super.gteq(rhs); + } + + public boolean gteq_b(LuaValue rhs) { return rhs.isstring()? rhs.strcmp(this) <= 0: super.gteq_b(rhs); } + + public boolean gteq_b(int rhs) { typerror("attempt to compare string with number"); return false; } + + public boolean gteq_b(double rhs) { typerror("attempt to compare string with number"); return false; } // concatenation - public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); } - public Buffer concat(Buffer rhs) { return rhs.concatTo(this); } - public LuaValue concatTo(LuaNumber lhs) { return concatTo(lhs.strvalue()); } - public LuaValue concatTo(LuaString lhs) { + public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); } + + public Buffer concat(Buffer rhs) { return rhs.concatTo(this); } + + public LuaValue concatTo(LuaNumber lhs) { return concatTo(lhs.strvalue()); } + + public LuaValue concatTo(LuaString lhs) { byte[] b = new byte[lhs.m_length+this.m_length]; System.arraycopy(lhs.m_bytes, lhs.m_offset, b, 0, lhs.m_length); System.arraycopy(this.m_bytes, this.m_offset, b, lhs.m_length, this.m_length); @@ -318,57 +424,63 @@ public class LuaString extends LuaValue { } // string comparison - public int strcmp(LuaValue lhs) { return -lhs.strcmp(this); } + public int strcmp(LuaValue lhs) { return -lhs.strcmp(this); } + public int strcmp(LuaString rhs) { - for ( int i=0, j=0; i= m_length / 2? - valueUsing(m_bytes, off, len): - valueOf(m_bytes, off, len); + public LuaString substring(int beginIndex, int endIndex) { + final int off = m_offset+beginIndex; + final int len = endIndex-beginIndex; + return len >= m_length/2? valueUsing(m_bytes, off, len): valueOf(m_bytes, off, len); } - + public int hashCode() { return m_hashcode; } - - /** Compute the hash code of a sequence of bytes within a byte array using - * lua's rules for string hashes. For long strings, not all bytes are hashed. + + /** + * Compute the hash code of a sequence of bytes within a byte array using + * lua's rules for string hashes. For long strings, not all bytes are + * hashed. + * * @param bytes byte array containing the bytes. - * @param offset offset into the hash for the first byte. - * @param length number of bytes starting with offset that are part of the string. + * @param offset offset into the hash for the first byte. + * @param length number of bytes starting with offset that are part of the + * string. * @return hash for the string defined by bytes, offset, and length. */ public static int hashCode(byte[] bytes, int offset, int length) { - int h = length; /* seed */ - int step = (length>>5)+1; /* if string is too long, don't hash all its chars */ - for (int l1=length; l1>=step; l1-=step) /* compute hash */ - h = h ^ ((h<<5)+(h>>2)+(((int) bytes[offset+l1-1] ) & 0x0FF )); + int h = length; /* seed */ + int step = (length>>5)+1; /* if string is too long, don't hash all its chars */ + for (int l1 = length; l1 >= step; l1 -= step) /* compute hash */ + h = h ^ ((h<<5)+(h>>2)+(((int) bytes[offset+l1-1]) & 0x0FF)); return h; } // object comparison, used in key comparison - public boolean equals( Object o ) { - if ( o instanceof LuaString ) { - return raweq( (LuaString) o ); + public boolean equals(Object o) { + if (o instanceof LuaString) { + return raweq((LuaString) o); } return false; } // equality w/ metatable processing - public LuaValue eq( LuaValue val ) { return val.raweq(this)? TRUE: FALSE; } - public boolean eq_b( LuaValue val ) { return val.raweq(this); } - + public LuaValue eq(LuaValue val) { return val.raweq(this)? TRUE: FALSE; } + + public boolean eq_b(LuaValue val) { return val.raweq(this); } + // equality w/o metatable processing - public boolean raweq( LuaValue val ) { + public boolean raweq(LuaValue val) { return val.raweq(this); } - - public boolean raweq( LuaString s ) { - if ( this == s ) + + public boolean raweq(LuaString s) { + if (this == s) return true; - if ( s.m_length != m_length ) + if (s.m_length != m_length) return false; - if ( s.m_bytes == m_bytes && s.m_offset == m_offset ) + if (s.m_bytes == m_bytes && s.m_offset == m_offset) return true; - if ( s.hashCode() != hashCode() ) + if (s.hashCode() != hashCode()) return false; - for ( int i=0; i=0 ) - if ( a[i++]!=b[j++] ) + while ( --n >= 0 ) + if (a[i++] != b[j++]) return false; return true; } public void write(DataOutputStream writer, int i, int len) throws IOException { - writer.write(m_bytes,m_offset+i,len); + writer.write(m_bytes, m_offset+i, len); } - + public LuaValue len() { return LuaInteger.valueOf(m_length); } @@ -526,15 +654,15 @@ public class LuaString extends LuaValue { } public int luaByte(int index) { - return m_bytes[m_offset + index] & 0x0FF; + return m_bytes[m_offset+index] & 0x0FF; } - public int charAt( int index ) { - if ( index < 0 || index >= m_length ) + public int charAt(int index) { + if (index < 0 || index >= m_length) throw new IndexOutOfBoundsException(); - return luaByte( index ); + return luaByte(index); } - + public String checkjstring() { return tojstring(); } @@ -542,120 +670,132 @@ public class LuaString extends LuaValue { public LuaString checkstring() { return this; } - - /** Convert value to an input stream. + + /** + * Convert value to an input stream. * - * @return {@link InputStream} whose data matches the bytes in this {@link LuaString} + * @return {@link InputStream} whose data matches the bytes in this + * {@link LuaString} */ public InputStream toInputStream() { return new ByteArrayInputStream(m_bytes, m_offset, m_length); } - + /** * Copy the bytes of the string into the given byte array. - * @param strOffset offset from which to copy - * @param bytes destination byte array + * + * @param strOffset offset from which to copy + * @param bytes destination byte array * @param arrayOffset offset in destination - * @param len number of bytes to copy + * @param len number of bytes to copy */ - public void copyInto( int strOffset, byte[] bytes, int arrayOffset, int len ) { - System.arraycopy( m_bytes, m_offset+strOffset, bytes, arrayOffset, len ); + public void copyInto(int strOffset, byte[] bytes, int arrayOffset, int len) { + System.arraycopy(m_bytes, m_offset+strOffset, bytes, arrayOffset, len); } - - /** Java version of strpbrk - find index of any byte that in an accept string. + + /** + * Java version of strpbrk - find index of any byte that in an accept + * string. + * * @param accept {@link LuaString} containing characters to look for. - * @return index of first match in the {@code accept} string, or -1 if not found. + * @return index of first match in the {@code accept} string, or -1 if not + * found. */ - public int indexOfAny( LuaString accept ) { - final int ilimit = m_offset + m_length; - final int jlimit = accept.m_offset + accept.m_length; - for ( int i = m_offset; i < ilimit; ++i ) { - for ( int j = accept.m_offset; j < jlimit; ++j ) { - if ( m_bytes[i] == accept.m_bytes[j] ) { - return i - m_offset; + public int indexOfAny(LuaString accept) { + final int ilimit = m_offset+m_length; + final int jlimit = accept.m_offset+accept.m_length; + for (int i = m_offset; i < ilimit; ++i) { + for (int j = accept.m_offset; j < jlimit; ++j) { + if (m_bytes[i] == accept.m_bytes[j]) { + return i-m_offset; } } } return -1; } - + /** * Find the index of a byte starting at a point in this string - * @param b the byte to look for + * + * @param b the byte to look for * @param start the first index in the string * @return index of first match found, or -1 if not found. */ - public int indexOf( byte b, int start ) { - for ( int i=start; i < m_length; ++i ) { - if ( m_bytes[m_offset+i] == b ) - return i; - } - return -1; - } - - /** - * Find the index of a string starting at a point in this string - * @param s the string to search for - * @param start the first index in the string - * @return index of first match found, or -1 if not found. - */ - public int indexOf( LuaString s, int start ) { - final int slen = s.length(); - final int limit = m_length - slen; - for ( int i=start; i <= limit; ++i ) { - if ( equals( m_bytes, m_offset+i, s.m_bytes, s.m_offset, slen ) ) - return i; - } - return -1; - } - - /** - * Find the last index of a string in this string - * @param s the string to search for - * @return index of last match found, or -1 if not found. - */ - public int lastIndexOf( LuaString s ) { - final int slen = s.length(); - final int limit = m_length - slen; - for ( int i=limit; i >= 0; --i ) { - if ( equals( m_bytes, m_offset+i, s.m_bytes, s.m_offset, slen ) ) + public int indexOf(byte b, int start) { + for (int i = start; i < m_length; ++i) { + if (m_bytes[m_offset+i] == b) return i; } return -1; } + /** + * Find the index of a string starting at a point in this string + * + * @param s the string to search for + * @param start the first index in the string + * @return index of first match found, or -1 if not found. + */ + public int indexOf(LuaString s, int start) { + final int slen = s.length(); + final int limit = m_length-slen; + for (int i = start; i <= limit; ++i) { + if (equals(m_bytes, m_offset+i, s.m_bytes, s.m_offset, slen)) + return i; + } + return -1; + } + + /** + * Find the last index of a string in this string + * + * @param s the string to search for + * @return index of last match found, or -1 if not found. + */ + public int lastIndexOf(LuaString s) { + final int slen = s.length(); + final int limit = m_length-slen; + for (int i = limit; i >= 0; --i) { + if (equals(m_bytes, m_offset+i, s.m_bytes, s.m_offset, slen)) + return i; + } + return -1; + } /** * Convert to Java String interpreting as utf8 characters. * - * @param bytes byte array in UTF8 encoding to convert + * @param bytes byte array in UTF8 encoding to convert * @param offset starting index in byte array * @param length number of bytes to convert - * @return Java String corresponding to the value of bytes interpreted using UTF8 + * @return Java String corresponding to the value of bytes interpreted using + * UTF8 * @see #lengthAsUtf8(char[]) * @see #encodeToUtf8(char[], int, byte[], int) * @see #isValidUtf8() */ 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||i>=j)? b: - (b<-32||i+1>=j)? (((b&0x3f) << 6) | (bytes[i++]&0x3f)): - (((b&0xf) << 12) | ((bytes[i++]&0x3f)<<6) | (bytes[i++]&0x3f))); + char[] chars = new char[n]; + for (i = offset, j = offset+length, n = 0; i < j;) { + chars[n++] = (char) (((b = bytes[i++]) >= 0 || i >= j)? b + : (b < -32 || i+1 >= j)? (((b & 0x3f)<<6) | (bytes[i++] & 0x3f)) + : (((b & 0xf)<<12) | ((bytes[i++] & 0x3f)<<6) | (bytes[i++] & 0x3f))); } return new String(chars); } - + /** * Count the number of bytes required to encode the string as UTF-8. + * * @param chars Array of unicode characters to be encoded as UTF-8 * @return count of bytes needed to encode using UTF-8 * @see #encodeToUtf8(char[], int, byte[], int) @@ -663,24 +803,25 @@ public class LuaString extends LuaValue { * @see #isValidUtf8() */ public static int lengthAsUtf8(char[] chars) { - int i,b; + int i, b; char c; - for ( i=b=chars.length; --i>=0; ) - if ( (c=chars[i]) >=0x80 ) - b += (c>=0x800)? 2: 1; + for (i = b = chars.length; --i >= 0;) + if ((c = chars[i]) >= 0x80) + b += (c >= 0x800)? 2: 1; return b; } - + /** * Encode the given Java string as UTF-8 bytes, writing the result to bytes * starting at offset. *

- * The string should be measured first with lengthAsUtf8 - * to make sure the given byte array is large enough. - * @param chars Array of unicode characters to be encoded as UTF-8 + * The string should be measured first with lengthAsUtf8 to make sure the + * given byte array is large enough. + * + * @param chars Array of unicode characters to be encoded as UTF-8 * @param nchars Number of characters in the array to convert. - * @param bytes byte array to hold the result - * @param off offset into the byte array to start writing + * @param bytes byte array to hold the result + * @param off offset into the byte array to start writing * @return number of bytes converted. * @see #lengthAsUtf8(char[]) * @see #decodeAsUtf8(byte[], int, int) @@ -689,158 +830,180 @@ 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) & 0x1f)); + bytes[j++] = (byte) (0x80 | (c & 0x3f)); } else { bytes[j++] = (byte) (0xE0 | ((c>>12) & 0x0f)); - bytes[j++] = (byte) (0x80 | ((c>>6) & 0x3f)); - bytes[j++] = (byte) (0x80 | ( c & 0x3f)); + bytes[j++] = (byte) (0x80 | ((c>>6) & 0x3f)); + bytes[j++] = (byte) (0x80 | (c & 0x3f)); } } - return j - off; + return j-off; } - /** Check that a byte sequence is valid UTF-8 + /** + * Check that a byte sequence is valid UTF-8 + * * @return true if it is valid UTF-8, otherwise false * @see #lengthAsUtf8(char[]) * @see #encodeToUtf8(char[], int, byte[], int) * @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; return false; } return true; } - + // --------------------- number conversion ----------------------- - + /** - * convert to a number using baee 10 or base 16 if it starts with '0x', - * or NIL if it can't be converted - * @return IntValue, DoubleValue, or NIL depending on the content of the string. + * convert to a number using baee 10 or base 16 if it starts with '0x', or + * NIL if it can't be converted + * + * @return IntValue, DoubleValue, or NIL depending on the content of the + * string. * @see LuaValue#tonumber() */ public LuaValue tonumber() { double d = scannumber(); return Double.isNaN(d)? NIL: valueOf(d); } - + /** - * convert to a number using a supplied base, or NIL if it can't be converted + * convert to a number using a supplied base, or NIL if it can't be + * converted + * * @param base the base to use, such as 10 - * @return IntValue, DoubleValue, or NIL depending on the content of the string. + * @return IntValue, DoubleValue, or NIL depending on the content of the + * string. * @see LuaValue#tonumber() */ - public LuaValue tonumber( int base ) { - double d = scannumber( base ); + public LuaValue tonumber(int base) { + 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', - * or return Double.NaN if it cannot be converted to a number. + * 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 && m_bytes[i] == ' ' ) + ++i; + while ( i < j && m_bytes[j-1] == ' ' ) + --j; + if (i >= j) return Double.NaN; - if ( m_bytes[i]=='0' && i+1 36 ) + if (base < 2 || base > 36) return Double.NaN; - int i=m_offset,j=m_offset+m_length; - while ( i=j ) + int i = m_offset, j = m_offset+m_length; + while ( i < j && m_bytes[i] == ' ' ) + ++i; + while ( i < j && m_bytes[j-1] == ' ' ) + --j; + if (i >= j) return Double.NaN; - return scanlong( base, i, j ); + return scanlong(base, i, j); } - + /** * Scan and convert a long value, or return Double.NaN if not found. - * @param base the base to use, such as 10 + * + * @param base the base to use, such as 10 * @param start the index to start searching from - * @param end the first index beyond the search range - * @return double value if conversion is valid, - * or Double.NaN if not + * @param end the first index beyond the search range + * @return double value if conversion is valid, or Double.NaN if not */ - private double scanlong( int base, int start, int end ) { + 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 ) + for (int i = (neg? start+1: start); i < end; i++) { + int digit = m_bytes[i]-(base <= 10 || (m_bytes[i] >= '0' && m_bytes[i] <= '9')? '0' + : m_bytes[i] >= 'A' && m_bytes[i] <= 'Z'? ('A'-10): ('a'-10)); + if (digit < 0 || digit >= base) return Double.NaN; - x = x * base + digit; - if ( x < 0 ) + x = x*base+digit; + if (x < 0) return Double.NaN; // overflow } return neg? -x: x; } - + /** * Scan and convert a double value, or return Double.NaN if not a double. + * * @param start the index to start searching from - * @param end the first index beyond the search range - * @return double value if conversion is valid, - * or Double.NaN if not + * @param end the first index beyond the search range + * @return double value if conversion is valid, or Double.NaN if not */ private double scandouble(int start, int end) { - if ( end>start+64 ) end=start+64; - for ( int i=start; i start+64) + end = start+64; + for (int i = start; i < end; i++) { + switch (m_bytes[i]) { case '-': case '+': case '.': - case 'e': case 'E': - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': + case 'e': + case 'E': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': break; default: return Double.NaN; } } - char [] c = new char[end-start]; - for ( int i=start; i - * 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,47 +110,52 @@ 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) ); + + 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; + public LuaValue get(LuaValue key) { + LuaValue v = rawget(key); + return v.isnil() && m_metatable != null? gettable(this, key): v; + } + + 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() ) { + 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,88 +270,90 @@ 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) ) + 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 ) { + 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 ); + 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 ); + 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 + /** + * Insert an element at a position in a list-table * - * @param pos the position to remove + * @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(); @@ -349,13 +362,14 @@ public class LuaTable extends LuaValue implements Metatable { 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() { + + public LuaValue len() { final LuaValue h = metatag(LEN); if (h.toboolean()) return h.call(this); @@ -364,14 +378,14 @@ public class LuaTable extends LuaValue implements Metatable { 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 +395,162 @@ 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 ) { + 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 +564,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 (int i = 0; i < hash.length; ++i) { + for (Slot slot = hash[i]; slot != null; slot = slot.rest()) { + if (slot.first() != null) keys++; } } @@ -557,7 +574,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 +584,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 +615,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 +688,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 +705,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<<(log-1))) { + newArraySize = 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 +741,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 +794,8 @@ public class LuaTable extends LuaValue implements Metatable { hashEntries -= movingToArray; } - public Slot entry( LuaValue key, LuaValue value ) { - return defaultEntry( key, value ); + public Slot entry(LuaValue key, LuaValue value) { + return defaultEntry(key, value); } protected static boolean isLargeKey(LuaValue key) { @@ -767,12 +811,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 +826,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() >= (long) 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 +853,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 +874,60 @@ 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; + 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; 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 +942,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 +978,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 +999,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,9 +1042,9 @@ 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; } @@ -993,8 +1053,8 @@ public class LuaTable extends LuaValue implements Metatable { return entry.key(); } - public int keyindex( int hashMask ) { - return entry.keyindex( hashMask ); + public int keyindex(int hashMask) { + return entry.keyindex(hashMask); } public LuaValue value() { @@ -1010,7 +1070,7 @@ public class LuaTable extends LuaValue implements Metatable { } public StrongSlot find(LuaValue key) { - return entry.keyeq(key) ? this : null; + return entry.keyeq(key)? this: null; } public boolean keyeq(LuaValue key) { @@ -1021,40 +1081,40 @@ public class LuaTable extends LuaValue implements Metatable { return next; } - public int arraykey( int max ) { - return entry.arraykey( max ); + public int arraykey(int max) { + return entry.arraykey(max); } 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 )); + public Slot add(Slot entry) { + return setnext(next.add(entry)); } - public Slot remove( StrongSlot target ) { - if ( this == target ) { - return new DeadSlot( key(), next ); + 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; } 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 { @@ -1076,19 +1136,25 @@ public class LuaTable extends LuaValue implements Metatable { */ static abstract class Entry extends Varargs implements StrongSlot { 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 ) { + 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) { return 0; } 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; } @@ -1110,8 +1176,10 @@ public class LuaTable extends LuaValue implements Metatable { 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; } @@ -1125,31 +1193,31 @@ public class LuaTable extends LuaValue implements Metatable { } public StrongSlot find(LuaValue key) { - return keyeq(key) ? this : null; + return keyeq(key)? this: null; } public Slot set(StrongSlot target, LuaValue value) { - return set( value ); + return set(value); } - public Slot add( Slot entry ) { - return new LinkSlot( this, entry ); + public Slot add(Slot entry) { + return new LinkSlot(this, entry); } 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; + 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; } @@ -1171,8 +1239,8 @@ public class LuaTable extends LuaValue implements Metatable { return this; } - public int keyindex( int hashMask ) { - return hashSlot( key, hashMask ); + public int keyindex(int hashMask) { + return hashSlot(key, hashMask); } public boolean keyeq(LuaValue key) { @@ -1182,7 +1250,7 @@ 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; @@ -1190,11 +1258,11 @@ public class LuaTable extends LuaValue implements Metatable { } public LuaValue key() { - return valueOf( key ); + return valueOf(key); } public int arraykey(int max) { - return ( key >= 1 && key <= max ) ? key : 0; + return (key >= 1 && key <= max)? key: 0; } public LuaValue value() { @@ -1206,20 +1274,21 @@ public class LuaTable extends LuaValue implements Metatable { return this; } - public int keyindex( int mask ) { - return hashmod( LuaInteger.hashCode( key ), mask ); + public int keyindex(int mask) { + return hashmod(LuaInteger.hashCode(key), mask); } 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) { @@ -1243,11 +1312,11 @@ 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 ); + public int keyindex(int mask) { + return hashSlot(key, mask); } public boolean keyeq(LuaValue key) { @@ -1256,21 +1325,21 @@ public class LuaTable extends LuaValue implements Metatable { } /** - * 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); } public int keyindex(int hashMask) { @@ -1300,8 +1369,8 @@ public class LuaTable extends LuaValue implements Metatable { } 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; @@ -1312,11 +1381,11 @@ public class LuaTable extends LuaValue implements Metatable { } public Slot add(Slot newEntry) { - return ( next != null ) ? next.add(newEntry) : newEntry; + return (next != null)? next.add(newEntry): newEntry; } public Slot remove(StrongSlot target) { - if ( key() != null ) { + if (key() != null) { next = next.remove(target); return this; } else { diff --git a/luaj-core/src/main/java/org/luaj/vm2/LuaThread.java b/luaj-core/src/main/java/org/luaj/vm2/LuaThread.java index a085abee..634fc992 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/LuaThread.java +++ b/luaj-core/src/main/java/org/luaj/vm2/LuaThread.java @@ -21,45 +21,43 @@ ******************************************************************************/ package org.luaj.vm2; - import java.lang.ref.WeakReference; -/** - * Subclass of {@link LuaValue} that implements - * a lua coroutine thread using Java Threads. +/** + * Subclass of {@link LuaValue} that implements a lua coroutine thread using + * Java Threads. *

- * 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,102 @@ 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; } - + public int type() { return LuaValue.TTHREAD; } - + public String typename() { return "thread"; } - + public boolean isthread() { return true; } - + public LuaThread optthread(LuaThread defval) { return this; } - + public LuaThread checkthread() { return this; } - - public LuaValue getmetatable() { - return s_metatable; - } - - public String getStatus() { - return STATUS_NAMES[state.status]; + + 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 +171,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 +183,7 @@ public class LuaThread extends LuaValue { this.lua_thread = new WeakReference(lua_thread); this.function = function; } - + public synchronized void run() { try { Varargs a = this.args; @@ -210,8 +203,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 +212,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 +222,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 +237,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 +248,5 @@ public class LuaThread extends LuaValue { } } } - + } diff --git a/luaj-core/src/main/java/org/luaj/vm2/LuaUserdata.java b/luaj-core/src/main/java/org/luaj/vm2/LuaUserdata.java index b6f58e09..0104502f 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/LuaUserdata.java +++ b/luaj-core/src/main/java/org/luaj/vm2/LuaUserdata.java @@ -21,29 +21,28 @@ ******************************************************************************/ 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; } - + public String tojstring() { return String.valueOf(m_instance); } - + public int type() { return LuaValue.TUSERDATA; } - + public String typename() { return "userdata"; } @@ -51,22 +50,27 @@ public class LuaUserdata extends LuaValue { 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; } + + 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; } + public Object optuserdata(Class c, Object defval) { if (!c.isAssignableFrom(m_instance.getClass())) typerror(c.getName()); return m_instance; } - + public LuaValue getmetatable() { return m_metatable; } @@ -79,48 +83,53 @@ public class LuaUserdata extends LuaValue { public Object checkuserdata() { return m_instance; } - - public Object checkuserdata(Class c) { - if ( c.isAssignableFrom(m_instance.getClass()) ) - return m_instance; + + 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" ); + + public LuaValue get(LuaValue key) { + return m_metatable != null? gettable(this, key): NIL; } - public boolean equals( Object val ) { - if ( this == val ) + public void set(LuaValue key, LuaValue value) { + if (m_metatable == null || !settable(this, key, value)) + error("cannot set " + key + " for userdata"); + } + + 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; + 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; 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)); + 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)); } - + // __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/luaj-core/src/main/java/org/luaj/vm2/LuaValue.java b/luaj-core/src/main/java/org/luaj/vm2/LuaValue.java index 9d3af18d..d4773fd2 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/LuaValue.java +++ b/luaj-core/src/main/java/org/luaj/vm2/LuaValue.java @@ -24,63 +24,86 @@ package org.luaj.vm2; /** * Base class for all concrete lua type values. *

- * Establishes base implementations for all the operations on lua types. - * This allows Java clients to deal essentially with one type for all Java values, namely {@link LuaValue}. + * Establishes base implementations for all the operations on lua types. This + * allows Java clients to deal essentially with one type for all Java values, + * namely {@link LuaValue}. *

* Constructors are provided as static methods for common Java types, such as - * {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(String)} - * to allow for instance pooling. + * {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(String)} to allow + * for instance pooling. *

- * Constants are defined for the lua values - * {@link #NIL}, {@link #TRUE}, and {@link #FALSE}. - * A constant {@link #NONE} is defined which is a {@link Varargs} list having no values. + * Constants are defined for the lua values {@link #NIL}, {@link #TRUE}, and + * {@link #FALSE}. A constant {@link #NONE} is defined which is a + * {@link Varargs} list having no values. *

- * Operations are performed on values directly via their Java methods. - * For example, the following code divides two numbers: - *

 {@code
- * LuaValue a = LuaValue.valueOf( 5 );
- * LuaValue b = LuaValue.valueOf( 4 );
- * LuaValue c = a.div(b);
- * } 
- * Note that in this example, c will be a {@link LuaDouble}, but would be a {@link LuaInteger} - * if the value of a were changed to 8, say. - * In general the value of c in practice will vary depending on both the types and values of a and b - * as well as any metatable/metatag processing that occurs. + * Operations are performed on values directly via their Java methods. For + * example, the following code divides two numbers: + * + *
+ * {
+ * 	@code
+ * 	LuaValue a = LuaValue.valueOf(5);
+ * 	LuaValue b = LuaValue.valueOf(4);
+ * 	LuaValue c = a.div(b);
+ * }
+ * 
+ * + * Note that in this example, c will be a {@link LuaDouble}, but would be a + * {@link LuaInteger} if the value of a were changed to 8, say. In general the + * value of c in practice will vary depending on both the types and values of a + * and b as well as any metatable/metatag processing that occurs. *

- * Field access and function calls are similar, with common overloads to simplify Java usage: - *

 {@code
- * LuaValue globals = JsePlatform.standardGlobals();
- * LuaValue sqrt = globals.get("math").get("sqrt");
- * LuaValue print = globals.get("print");
- * LuaValue d = sqrt.call( a );
- * print.call( LuaValue.valueOf("sqrt(5):"), a );
- * } 
+ * Field access and function calls are similar, with common overloads to + * simplify Java usage: + * + *
+ * {
+ * 	@code
+ * 	LuaValue globals = JsePlatform.standardGlobals();
+ * 	LuaValue sqrt = globals.get("math").get("sqrt");
+ * 	LuaValue print = globals.get("print");
+ * 	LuaValue d = sqrt.call(a);
+ * 	print.call(LuaValue.valueOf("sqrt(5):"), a);
+ * }
+ * 
*

* To supply variable arguments or get multiple return values, use * {@link #invoke(Varargs)} or {@link #invokemethod(LuaValue, Varargs)} methods: - *

 {@code
- * LuaValue modf = globals.get("math").get("modf");
- * Varargs r = modf.invoke( d );
- * print.call( r.arg(1), r.arg(2) );
- * } 
+ * + *
+ * {
+ * 	@code
+ * 	LuaValue modf = globals.get("math").get("modf");
+ * 	Varargs r = modf.invoke(d);
+ * 	print.call(r.arg(1), r.arg(2));
+ * }
+ * 
*

* To load and run a script, {@link LoadState} is used: - *

 {@code
+ * 
+ * 
+ *  {@code
  * LoadState.load( new FileInputStream("main.lua"), "main.lua", globals ).call();
- * } 
+ * } + *
*

* although {@code require} could also be used: - *

 {@code
+ * 
+ * 
+ *  {@code
  * globals.get("require").call(LuaValue.valueOf("main"));
- * } 
- * For this to work the file must be in the current directory, or in the class path, - * dependening on the platform. - * See {@link org.luaj.vm2.lib.jse.JsePlatform} and {@link org.luaj.vm2.lib.jme.JmePlatform} for details. + * } + *
+ * + * For this to work the file must be in the current directory, or in the class + * path, dependening on the platform. See + * {@link org.luaj.vm2.lib.jse.JsePlatform} and + * {@link org.luaj.vm2.lib.jme.JmePlatform} for details. *

- * In general a {@link LuaError} may be thrown on any operation when the - * types supplied to any operation are illegal from a lua perspective. - * Examples could be attempting to concatenate a NIL value, or attempting arithmetic - * on values that are not number. + * In general a {@link LuaError} may be thrown on any operation when the types + * supplied to any operation are illegal from a lua perspective. Examples could + * be attempting to concatenate a NIL value, or attempting arithmetic on values + * that are not number. *

* There are several methods for preinitializing tables, such as: *

    @@ -89,14 +112,14 @@ package org.luaj.vm2; *
  • {@link #tableOf(LuaValue[], LuaValue[], Varargs)} for mixtures
  • *
*

- * Predefined constants exist for the standard lua type constants - * {@link #TNIL}, {@link #TBOOLEAN}, {@link #TLIGHTUSERDATA}, {@link #TNUMBER}, {@link #TSTRING}, - * {@link #TTABLE}, {@link #TFUNCTION}, {@link #TUSERDATA}, {@link #TTHREAD}, - * and extended lua type constants - * {@link #TINT}, {@link #TNONE}, {@link #TVALUE} + * Predefined constants exist for the standard lua type constants {@link #TNIL}, + * {@link #TBOOLEAN}, {@link #TLIGHTUSERDATA}, {@link #TNUMBER}, + * {@link #TSTRING}, {@link #TTABLE}, {@link #TFUNCTION}, {@link #TUSERDATA}, + * {@link #TTHREAD}, and extended lua type constants {@link #TINT}, + * {@link #TNONE}, {@link #TVALUE} *

- * Predefined constants exist for all strings used as metatags: - * {@link #INDEX}, {@link #NEWINDEX}, {@link #CALL}, {@link #MODE}, {@link #METATABLE}, + * Predefined constants exist for all strings used as metatags: {@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}. @@ -106,185 +129,189 @@ package org.luaj.vm2; * @see LoadState * @see Varargs */ -abstract -public class LuaValue extends Varargs { - - /** Type enumeration constant for lua numbers that are ints, for compatibility with lua 5.1 number patch only */ - public static final int TINT = (-2); - - /** Type enumeration constant for lua values that have no type, for example weak table entries */ - public static final int TNONE = (-1); - - /** Type enumeration constant for lua nil */ - public static final int TNIL = 0; - - /** Type enumeration constant for lua booleans */ - public static final int TBOOLEAN = 1; - - /** Type enumeration constant for lua light userdata, for compatibility with C-based lua only */ - public static final int TLIGHTUSERDATA = 2; - - /** Type enumeration constant for lua numbers */ - public static final int TNUMBER = 3; - - /** Type enumeration constant for lua strings */ - public static final int TSTRING = 4; - - /** Type enumeration constant for lua tables */ - public static final int TTABLE = 5; - - /** Type enumeration constant for lua functions */ - public static final int TFUNCTION = 6; - - /** Type enumeration constant for lua userdatas */ - public static final int TUSERDATA = 7; - - /** Type enumeration constant for lua threads */ - public static final int TTHREAD = 8; - - /** Type enumeration constant for unknown values, for compatibility with C-based lua only */ - public static final int TVALUE = 9; +abstract public class LuaValue extends Varargs { - /** String array constant containing names of each of the lua value types + /** + * Type enumeration constant for lua numbers that are ints, for + * compatibility with lua 5.1 number patch only + */ + public static final int TINT = (-2); + + /** + * Type enumeration constant for lua values that have no type, for example + * weak table entries + */ + public static final int TNONE = (-1); + + /** Type enumeration constant for lua nil */ + public static final int TNIL = 0; + + /** Type enumeration constant for lua booleans */ + public static final int TBOOLEAN = 1; + + /** + * Type enumeration constant for lua light userdata, for compatibility with + * C-based lua only + */ + public static final int TLIGHTUSERDATA = 2; + + /** Type enumeration constant for lua numbers */ + public static final int TNUMBER = 3; + + /** Type enumeration constant for lua strings */ + public static final int TSTRING = 4; + + /** Type enumeration constant for lua tables */ + public static final int TTABLE = 5; + + /** Type enumeration constant for lua functions */ + public static final int TFUNCTION = 6; + + /** Type enumeration constant for lua userdatas */ + public static final int TUSERDATA = 7; + + /** Type enumeration constant for lua threads */ + public static final int TTHREAD = 8; + + /** + * Type enumeration constant for unknown values, for compatibility with + * C-based lua only + */ + public static final int TVALUE = 9; + + /** + * String array constant containing names of each of the lua value types + * * @see #type() * @see #typename() */ - public static final String[] TYPE_NAMES = { - "nil", - "boolean", - "lightuserdata", - "number", - "string", - "table", - "function", - "userdata", - "thread", - "value", - }; - + public static final String[] TYPE_NAMES = { "nil", "boolean", "lightuserdata", "number", "string", "table", + "function", "userdata", "thread", "value", }; + /** LuaValue constant corresponding to lua {@code #NIL} */ - public static final LuaValue NIL = LuaNil._NIL; - + public static final LuaValue NIL = LuaNil._NIL; + /** LuaBoolean constant corresponding to lua {@code true} */ - public static final LuaBoolean TRUE = LuaBoolean._TRUE; + public static final LuaBoolean TRUE = LuaBoolean._TRUE; /** LuaBoolean constant corresponding to lua {@code false} */ - public static final LuaBoolean FALSE = LuaBoolean._FALSE; + public static final LuaBoolean FALSE = LuaBoolean._FALSE; + + /** + * LuaValue constant corresponding to a {@link Varargs} list of no values + */ + public static final LuaValue NONE = None._NONE; - /** LuaValue constant corresponding to a {@link Varargs} list of no values */ - public static final LuaValue NONE = None._NONE; - /** LuaValue number constant equal to 0 */ - public static final LuaNumber ZERO = LuaInteger.valueOf(0); - + public static final LuaNumber ZERO = LuaInteger.valueOf(0); + /** LuaValue number constant equal to 1 */ - public static final LuaNumber ONE = LuaInteger.valueOf(1); + public static final LuaNumber ONE = LuaInteger.valueOf(1); /** LuaValue number constant equal to -1 */ - public static final LuaNumber MINUSONE = LuaInteger.valueOf(-1); - + public static final LuaNumber MINUSONE = LuaInteger.valueOf(-1); + /** LuaValue array constant with no values */ - public static final LuaValue[] NOVALS = {}; + public static final LuaValue[] NOVALS = {}; /** The variable name of the environment. */ - public static LuaString ENV = valueOf("_ENV"); + public static LuaString ENV = valueOf("_ENV"); /** LuaString constant with value "__index" for use as metatag */ - public static final LuaString INDEX = valueOf("__index"); + public static final LuaString INDEX = valueOf("__index"); /** LuaString constant with value "__newindex" for use as metatag */ - public static final LuaString NEWINDEX = valueOf("__newindex"); + public static final LuaString NEWINDEX = valueOf("__newindex"); /** LuaString constant with value "__call" for use as metatag */ - public static final LuaString CALL = valueOf("__call"); + public static final LuaString CALL = valueOf("__call"); /** LuaString constant with value "__mode" for use as metatag */ - public static final LuaString MODE = valueOf("__mode"); + public static final LuaString MODE = valueOf("__mode"); /** LuaString constant with value "__metatable" for use as metatag */ - public static final LuaString METATABLE = valueOf("__metatable"); + public static final LuaString METATABLE = valueOf("__metatable"); /** LuaString constant with value "__add" for use as metatag */ - public static final LuaString ADD = valueOf("__add"); + public static final LuaString ADD = valueOf("__add"); /** LuaString constant with value "__sub" for use as metatag */ - public static final LuaString SUB = valueOf("__sub"); + public static final LuaString SUB = valueOf("__sub"); /** LuaString constant with value "__div" for use as metatag */ - public static final LuaString DIV = valueOf("__div"); + public static final LuaString DIV = valueOf("__div"); /** LuaString constant with value "__mul" for use as metatag */ - public static final LuaString MUL = valueOf("__mul"); + public static final LuaString MUL = valueOf("__mul"); /** LuaString constant with value "__pow" for use as metatag */ - public static final LuaString POW = valueOf("__pow"); + public static final LuaString POW = valueOf("__pow"); /** LuaString constant with value "__mod" for use as metatag */ - public static final LuaString MOD = valueOf("__mod"); + public static final LuaString MOD = valueOf("__mod"); /** LuaString constant with value "__unm" for use as metatag */ - public static final LuaString UNM = valueOf("__unm"); + public static final LuaString UNM = valueOf("__unm"); /** LuaString constant with value "__len" for use as metatag */ - public static final LuaString LEN = valueOf("__len"); + public static final LuaString LEN = valueOf("__len"); /** LuaString constant with value "__eq" for use as metatag */ - public static final LuaString EQ = valueOf("__eq"); + public static final LuaString EQ = valueOf("__eq"); /** LuaString constant with value "__lt" for use as metatag */ - public static final LuaString LT = valueOf("__lt"); + public static final LuaString LT = valueOf("__lt"); /** LuaString constant with value "__le" for use as metatag */ - public static final LuaString LE = valueOf("__le"); + public static final LuaString LE = valueOf("__le"); /** LuaString constant with value "__tostring" for use as metatag */ - public static final LuaString TOSTRING = valueOf("__tostring"); + public static final LuaString TOSTRING = valueOf("__tostring"); /** LuaString constant with value "__concat" for use as metatag */ - public static final LuaString CONCAT = valueOf("__concat"); - + public static final LuaString CONCAT = valueOf("__concat"); + /** LuaString constant with value "" */ public static final LuaString EMPTYSTRING = valueOf(""); /** Limit on lua stack size */ private static int MAXSTACK = 250; - - /** Array of {@link #NIL} values to optimize filling stacks using System.arraycopy(). - * Must not be modified. + + /** + * Array of {@link #NIL} values to optimize filling stacks using + * System.arraycopy(). Must not be modified. */ public static final LuaValue[] NILS = new LuaValue[MAXSTACK]; static { - for ( int i=0; i * - * @return name from type name list {@link #TYPE_NAMES} - * corresponding to the type of this value: - * "nil", "boolean", "number", "string", - * "table", "function", "userdata", "thread" + * @return name from type name list {@link #TYPE_NAMES} corresponding to the + * type of this value: "nil", "boolean", "number", "string", + * "table", "function", "userdata", "thread" * @see #type() */ - abstract public String typename(); + abstract public String typename(); - /** Check if {@code this} is a {@code boolean} + /** + * Check if {@code this} is a {@code boolean} + * * @return true if this is a {@code boolean}, otherwise false * @see #isboolean() * @see #toboolean() @@ -292,34 +319,39 @@ public class LuaValue extends Varargs { * @see #optboolean(boolean) * @see #TBOOLEAN */ - public boolean isboolean() { return false; } + public boolean isboolean() { return false; } - /** Check if {@code this} is a {@code function} that is a closure, - * meaning interprets lua bytecode for its execution + /** + * Check if {@code this} is a {@code function} that is a closure, meaning + * interprets lua bytecode for its execution + * * @return true if this is a {@code closure}, otherwise false * @see #isfunction() * @see #checkclosure() * @see #optclosure(LuaClosure) * @see #TFUNCTION */ - public boolean isclosure() { return false; } + public boolean isclosure() { return false; } - /** Check if {@code this} is a {@code function} + /** + * Check if {@code this} is a {@code function} + * * @return true if this is a {@code function}, otherwise false * @see #isclosure() * @see #checkfunction() * @see #optfunction(LuaFunction) * @see #TFUNCTION */ - public boolean isfunction() { return false; } - - /** Check if {@code this} is a {@code number} and is representable by java int - * without rounding or truncation - * @return true if this is a {@code number} - * meaning derives from {@link LuaNumber} - * or derives from {@link LuaString} and is convertible to a number, - * and can be represented by int, - * otherwise false + public boolean isfunction() { return false; } + + /** + * Check if {@code this} is a {@code number} and is representable by java + * int without rounding or truncation + * + * @return true if this is a {@code number} meaning derives from + * {@link LuaNumber} or derives from {@link LuaString} and is + * convertible to a number, and can be represented by int, otherwise + * false * @see #isinttype() * @see #islong() * @see #tonumber() @@ -327,35 +359,39 @@ public class LuaValue extends Varargs { * @see #optint(int) * @see #TNUMBER */ - public boolean isint() { return false; } + public boolean isint() { return false; } - /** Check if {@code this} is a {@link LuaInteger} + /** + * Check if {@code this} is a {@link LuaInteger} *

* No attempt to convert from string will be made by this call. - * @return true if this is a {@code LuaInteger}, - * otherwise false + * + * @return true if this is a {@code LuaInteger}, otherwise false * @see #isint() * @see #isnumber() * @see #tonumber() * @see #TNUMBER */ - public boolean isinttype() { return false; } - - /** Check if {@code this} is a {@code number} and is representable by java long - * without rounding or truncation - * @return true if this is a {@code number} - * meaning derives from {@link LuaNumber} - * or derives from {@link LuaString} and is convertible to a number, - * and can be represented by long, - * otherwise false + public boolean isinttype() { return false; } + + /** + * Check if {@code this} is a {@code number} and is representable by java + * long without rounding or truncation + * + * @return true if this is a {@code number} meaning derives from + * {@link LuaNumber} or derives from {@link LuaString} and is + * convertible to a number, and can be represented by long, + * otherwise false * @see #tonumber() * @see #checklong() * @see #optlong(long) * @see #TNUMBER */ - public boolean islong() { return false; } - - /** Check if {@code this} is {@code #NIL} + public boolean islong() { return false; } + + /** + * Check if {@code this} is {@code #NIL} + * * @return true if this is {@code #NIL}, otherwise false * @see #NIL * @see #NONE @@ -365,48 +401,56 @@ public class LuaValue extends Varargs { * @see #TNIL * @see #TNONE */ - public boolean isnil() { return false; } - - /** Check if {@code this} is a {@code number} - * @return true if this is a {@code number}, - * meaning derives from {@link LuaNumber} - * or derives from {@link LuaString} and is convertible to a number, - * otherwise false + public boolean isnil() { return false; } + + /** + * Check if {@code this} is a {@code number} + * + * @return true if this is a {@code number}, meaning derives from + * {@link LuaNumber} or derives from {@link LuaString} and is + * convertible to a number, otherwise false * @see #tonumber() * @see #checknumber() * @see #optnumber(LuaNumber) * @see #TNUMBER */ - public boolean isnumber() { return false; } // may convert from string - - /** Check if {@code this} is a {@code string} - * @return true if this is a {@code string}, - * meaning derives from {@link LuaString} or {@link LuaNumber}, - * otherwise false + public boolean isnumber() { return false; } // may convert from string + + /** + * Check if {@code this} is a {@code string} + * + * @return true if this is a {@code string}, meaning derives from + * {@link LuaString} or {@link LuaNumber}, otherwise false * @see #tostring() * @see #checkstring() * @see #optstring(LuaString) * @see #TSTRING */ - public boolean isstring() { return false; } - - /** Check if {@code this} is a {@code thread} + public boolean isstring() { return false; } + + /** + * Check if {@code this} is a {@code thread} + * * @return true if this is a {@code thread}, otherwise false * @see #checkthread() * @see #optthread(LuaThread) * @see #TTHREAD */ - public boolean isthread() { return false; } - - /** Check if {@code this} is a {@code table} + public boolean isthread() { return false; } + + /** + * Check if {@code this} is a {@code table} + * * @return true if this is a {@code table}, otherwise false * @see #checktable() * @see #opttable(LuaTable) * @see #TTABLE */ - public boolean istable() { return false; } - - /** Check if {@code this} is a {@code userdata} + public boolean istable() { return false; } + + /** + * Check if {@code this} is a {@code userdata} + * * @return true if this is a {@code userdata}, otherwise false * @see #isuserdata(Class) * @see #touserdata() @@ -414,52 +458,66 @@ public class LuaValue extends Varargs { * @see #optuserdata(Object) * @see #TUSERDATA */ - public boolean isuserdata() { return false; } - - /** Check if {@code this} is a {@code userdata} of type {@code c} + public boolean isuserdata() { return false; } + + /** + * Check if {@code this} is a {@code userdata} of type {@code c} + * * @param c Class to test instance against - * @return true if this is a {@code userdata} - * and the instance is assignable to {@code c}, - * otherwise false + * @return true if this is a {@code userdata} and the instance is assignable + * to {@code c}, otherwise false * @see #isuserdata() * @see #touserdata(Class) * @see #checkuserdata(Class) * @see #optuserdata(Class, Object) * @see #TUSERDATA */ - public boolean isuserdata(Class c) { return false; } - - /** Convert to boolean false if {@link #NIL} or {@link #FALSE}, true if anything else - * @return Value cast to byte if number or string convertible to number, otherwise 0 + public boolean isuserdata(Class c) { return false; } + + /** + * Convert to boolean false if {@link #NIL} or {@link #FALSE}, true if + * anything else + * + * @return Value cast to byte if number or string convertible to number, + * otherwise 0 * @see #optboolean(boolean) * @see #checkboolean() * @see #isboolean() * @see #TBOOLEAN */ - public boolean toboolean() { return true; } - - /** Convert to byte if numeric, or 0 if not. - * @return Value cast to byte if number or string convertible to number, otherwise 0 + public boolean toboolean() { return true; } + + /** + * Convert to byte if numeric, or 0 if not. + * + * @return Value cast to byte if number or string convertible to number, + * otherwise 0 * @see #toint() * @see #todouble() * @see #checknumber() * @see #isnumber() * @see #TNUMBER */ - public byte tobyte() { return 0; } - - /** Convert to char if numeric, or 0 if not. - * @return Value cast to char if number or string convertible to number, otherwise 0 + public byte tobyte() { return 0; } + + /** + * Convert to char if numeric, or 0 if not. + * + * @return Value cast to char if number or string convertible to number, + * otherwise 0 * @see #toint() * @see #todouble() * @see #checknumber() * @see #isnumber() * @see #TNUMBER */ - public char tochar() { return 0; } - - /** Convert to double if numeric, or 0 if not. - * @return Value cast to double if number or string convertible to number, otherwise 0 + public char tochar() { return 0; } + + /** + * Convert to double if numeric, or 0 if not. + * + * @return Value cast to double if number or string convertible to number, + * otherwise 0 * @see #toint() * @see #tobyte() * @see #tochar() @@ -471,20 +529,26 @@ public class LuaValue extends Varargs { * @see #isnumber() * @see #TNUMBER */ - public double todouble() { return 0; } - - /** Convert to float if numeric, or 0 if not. - * @return Value cast to float if number or string convertible to number, otherwise 0 + public double todouble() { return 0; } + + /** + * Convert to float if numeric, or 0 if not. + * + * @return Value cast to float if number or string convertible to number, + * otherwise 0 * @see #toint() * @see #todouble() * @see #checknumber() * @see #isnumber() * @see #TNUMBER */ - public float tofloat() { return 0; } - - /** Convert to int if numeric, or 0 if not. - * @return Value cast to int if number or string convertible to number, otherwise 0 + public float tofloat() { return 0; } + + /** + * Convert to int if numeric, or 0 if not. + * + * @return Value cast to int if number or string convertible to number, + * otherwise 0 * @see #tobyte() * @see #tochar() * @see #toshort() @@ -496,10 +560,13 @@ public class LuaValue extends Varargs { * @see #isnumber() * @see #TNUMBER */ - public int toint() { return 0; } - - /** Convert to long if numeric, or 0 if not. - * @return Value cast to long if number or string convertible to number, otherwise 0 + public int toint() { return 0; } + + /** + * Convert to long if numeric, or 0 if not. + * + * @return Value cast to long if number or string convertible to number, + * otherwise 0 * @see #isint() * @see #isinttype() * @see #toint() @@ -509,19 +576,24 @@ public class LuaValue extends Varargs { * @see #isnumber() * @see #TNUMBER */ - public long tolong() { return 0; } - - /** Convert to short if numeric, or 0 if not. - * @return Value cast to short if number or string convertible to number, otherwise 0 + public long tolong() { return 0; } + + /** + * Convert to short if numeric, or 0 if not. + * + * @return Value cast to short if number or string convertible to number, + * otherwise 0 * @see #toint() * @see #todouble() * @see #checknumber() * @see #isnumber() * @see #TNUMBER */ - public short toshort() { return 0; } - - /** Convert to human readable String for any type. + public short toshort() { return 0; } + + /** + * Convert to human readable String for any type. + * * @return String for use by human readers based on type. * @see #tostring() * @see #optjstring(String) @@ -529,29 +601,34 @@ public class LuaValue extends Varargs { * @see #isstring() * @see #TSTRING */ - public String tojstring() { return typename() + ": " + Integer.toHexString(hashCode()); } - - /** Convert to userdata instance, or null. + public String tojstring() { return typename() + ": " + Integer.toHexString(hashCode()); } + + /** + * Convert to userdata instance, or null. + * * @return userdata instance if userdata, or null if not {@link LuaUserdata} * @see #optuserdata(Object) * @see #checkuserdata() * @see #isuserdata() * @see #TUSERDATA */ - public Object touserdata() { return null; } - - /** Convert to userdata instance if specific type, or null. - * @return userdata instance if is a userdata whose instance derives from {@code c}, - * or null if not {@link LuaUserdata} + public Object touserdata() { return null; } + + /** + * Convert to userdata instance if specific type, or null. + * + * @return userdata instance if is a userdata whose instance derives from + * {@code c}, or null if not {@link LuaUserdata} * @see #optuserdata(Class,Object) * @see #checkuserdata(Class) * @see #isuserdata(Class) * @see #TUSERDATA */ - public Object touserdata(Class c) { return null; } + public Object touserdata(Class c) { return null; } /** * Convert the value to a human readable string using {@link #tojstring()} + * * @return String value intended to be human readible. * @see #tostring() * @see #tojstring() @@ -560,78 +637,86 @@ public class LuaValue extends Varargs { * @see #toString() */ public String toString() { return tojstring(); } - - /** Conditionally convert to lua number without throwing errors. + + /** + * Conditionally convert to lua number without throwing errors. *

- * In lua all numbers are strings, but not all strings are numbers. - * This function will return - * the {@link LuaValue} {@code this} if it is a number - * or a string convertible to a number, - * and {@link #NIL} for all other cases. + * In lua all numbers are strings, but not all strings are numbers. This + * function will return the {@link LuaValue} {@code this} if it is a number + * or a string convertible to a number, and {@link #NIL} for all other + * cases. *

- * This allows values to be tested for their "numeric-ness" without - * the penalty of throwing exceptions, - * nor the cost of converting the type and creating storage for it. - * @return {@code this} if it is a {@link LuaNumber} - * or {@link LuaString} that can be converted to a number, - * otherwise {@link #NIL} + * This allows values to be tested for their "numeric-ness" without the + * penalty of throwing exceptions, nor the cost of converting the type and + * creating storage for it. + * + * @return {@code this} if it is a {@link LuaNumber} or {@link LuaString} + * that can be converted to a number, otherwise {@link #NIL} * @see #tostring() * @see #optnumber(LuaNumber) * @see #checknumber() * @see #toint() * @see #todouble() */ - public LuaValue tonumber() { return NIL; } - - /** Conditionally convert to lua string without throwing errors. + public LuaValue tonumber() { return NIL; } + + /** + * Conditionally convert to lua string without throwing errors. *

- * In lua all numbers are strings, so this function will return - * the {@link LuaValue} {@code this} if it is a string or number, - * and {@link #NIL} for all other cases. + * In lua all numbers are strings, so this function will return the + * {@link LuaValue} {@code this} if it is a string or number, and + * {@link #NIL} for all other cases. *

- * This allows values to be tested for their "string-ness" without - * the penalty of throwing exceptions. + * This allows values to be tested for their "string-ness" without the + * penalty of throwing exceptions. + * * @return {@code this} if it is a {@link LuaString} or {@link LuaNumber}, - * otherwise {@link #NIL} + * otherwise {@link #NIL} * @see #tonumber() * @see #tojstring() * @see #optstring(LuaString) * @see #checkstring() * @see #toString() */ - public LuaValue tostring() { return NIL; } + public LuaValue tostring() { return NIL; } - /** Check that optional argument is a boolean and return its boolean value + /** + * Check that optional argument is a boolean and return its boolean value + * * @param defval boolean value to return if {@code this} is nil or none * @return {@code this} cast to boolean if a {@link LuaBoolean}, - * {@code defval} if nil or none, - * throws {@link LuaError} otherwise + * {@code defval} if nil or none, throws {@link LuaError} otherwise * @throws LuaError if was not a boolean or nil or none. * @see #checkboolean() * @see #isboolean() * @see #TBOOLEAN */ - public boolean optboolean(boolean defval) { argerror("boolean"); return false; } + public boolean optboolean(boolean defval) { argerror("boolean"); return false; } - /** Check that optional argument is a closure and return as {@link LuaClosure} + /** + * Check that optional argument is a closure and return as + * {@link LuaClosure} *

- * A {@link LuaClosure} is a {@link LuaFunction} that executes lua byteccode. + * A {@link LuaClosure} is a {@link LuaFunction} that executes lua + * byteccode. + * * @param defval {@link LuaClosure} to return if {@code this} is nil or none * @return {@code this} cast to {@link LuaClosure} if a function, - * {@code defval} if nil or none, - * throws {@link LuaError} otherwise + * {@code defval} if nil or none, throws {@link LuaError} otherwise * @throws LuaError if was not a closure or nil or none. * @see #checkclosure() * @see #isclosure() * @see #TFUNCTION */ - public LuaClosure optclosure(LuaClosure defval) { argerror("closure"); return null; } + public LuaClosure optclosure(LuaClosure defval) { argerror("closure"); return null; } - /** Check that optional argument is a number or string convertible to number and return as double + /** + * 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 - * @return {@code this} cast to double if numeric, - * {@code defval} if nil or none, - * throws {@link LuaError} otherwise + * @return {@code this} cast to double if numeric, {@code defval} if nil or + * none, throws {@link LuaError} otherwise * @throws LuaError if was not numeric or nil or none. * @see #optint(int) * @see #optinteger(LuaInteger) @@ -641,29 +726,34 @@ public class LuaValue extends Varargs { * @see #isnumber() * @see #TNUMBER */ - public double optdouble(double defval) { argerror("number"); return 0; } + public double optdouble(double defval) { argerror("number"); return 0; } - /** Check that optional argument is a function and return as {@link LuaFunction} + /** + * Check that optional argument is a function and return as + * {@link LuaFunction} *

* A {@link LuaFunction} may either be a Java function that implements - * functionality directly in Java, or a {@link LuaClosure} - * which is a {@link LuaFunction} that executes lua bytecode. - * @param defval {@link LuaFunction} to return if {@code this} is nil or none + * functionality directly in Java, or a {@link LuaClosure} which is a + * {@link LuaFunction} that executes lua bytecode. + * + * @param defval {@link LuaFunction} to return if {@code this} is nil or + * none * @return {@code this} cast to {@link LuaFunction} if a function, - * {@code defval} if nil or none, - * throws {@link LuaError} otherwise + * {@code defval} if nil or none, throws {@link LuaError} otherwise * @throws LuaError if was not a function or nil or none. * @see #checkfunction() * @see #isfunction() * @see #TFUNCTION */ - public LuaFunction optfunction(LuaFunction defval) { argerror("function"); return null; } + public LuaFunction optfunction(LuaFunction defval) { argerror("function"); return null; } - /** Check that optional argument is a number or string convertible to number and return as int + /** + * Check that optional argument is a number or string convertible to number + * and return as int + * * @param defval int to return if {@code this} is nil or none - * @return {@code this} cast to int if numeric, - * {@code defval} if nil or none, - * throws {@link LuaError} otherwise + * @return {@code this} cast to int if numeric, {@code defval} if nil or + * none, throws {@link LuaError} otherwise * @throws LuaError if was not numeric or nil or none. * @see #optdouble(double) * @see #optlong(long) @@ -674,13 +764,16 @@ public class LuaValue extends Varargs { * @see #isnumber() * @see #TNUMBER */ - public int optint(int defval) { argerror("int"); return 0; } + public int optint(int defval) { argerror("int"); return 0; } - /** Check that optional argument is a number or string convertible to number and return as {@link LuaInteger} + /** + * Check that optional argument is a number or string convertible to number + * and return as {@link LuaInteger} + * * @param defval {@link LuaInteger} to return if {@code this} is nil or none - * @return {@code this} converted and wrapped in {@link LuaInteger} if numeric, - * {@code defval} if nil or none, - * throws {@link LuaError} otherwise + * @return {@code this} converted and wrapped in {@link LuaInteger} if + * numeric, {@code defval} if nil or none, throws {@link LuaError} + * otherwise * @throws LuaError if was not numeric or nil or none. * @see #optdouble(double) * @see #optint(int) @@ -690,13 +783,15 @@ public class LuaValue extends Varargs { * @see #isnumber() * @see #TNUMBER */ - public LuaInteger optinteger(LuaInteger defval) { argerror("integer"); return null; } + public LuaInteger optinteger(LuaInteger defval) { argerror("integer"); return null; } - /** Check that optional argument is a number or string convertible to number and return as long + /** + * Check that optional argument is a number or string convertible to number + * and return as long + * * @param defval long to return if {@code this} is nil or none - * @return {@code this} cast to long if numeric, - * {@code defval} if nil or none, - * throws {@link LuaError} otherwise + * @return {@code this} cast to long if numeric, {@code defval} if nil or + * none, throws {@link LuaError} otherwise * @throws LuaError if was not numeric or nil or none. * @see #optdouble(double) * @see #optint(int) @@ -706,13 +801,15 @@ public class LuaValue extends Varargs { * @see #isnumber() * @see #TNUMBER */ - public long optlong(long defval) { argerror("long"); return 0; } + public long optlong(long defval) { argerror("long"); return 0; } - /** Check that optional argument is a number or string convertible to number and return as {@link LuaNumber} + /** + * Check that optional argument is a number or string convertible to number + * and return as {@link LuaNumber} + * * @param defval {@link LuaNumber} to return if {@code this} is nil or none - * @return {@code this} cast to {@link LuaNumber} if numeric, - * {@code defval} if nil or none, - * throws {@link LuaError} otherwise + * @return {@code this} cast to {@link LuaNumber} if numeric, {@code defval} + * if nil or none, throws {@link LuaError} otherwise * @throws LuaError if was not numeric or nil or none. * @see #optdouble(double) * @see #optlong(long) @@ -723,13 +820,16 @@ public class LuaValue extends Varargs { * @see #isnumber() * @see #TNUMBER */ - public LuaNumber optnumber(LuaNumber defval) { argerror("number"); return null; } + public LuaNumber optnumber(LuaNumber defval) { argerror("number"); return null; } - /** Check that optional argument is a string or number and return as Java String + /** + * Check that optional argument is a string or number and return as Java + * String + * * @param defval {@link LuaString} to return if {@code this} is nil or none * @return {@code this} converted to String if a string or number, - * {@code defval} if nil or none, - * throws {@link LuaError} if some other type + * {@code defval} if nil or none, throws {@link LuaError} if some + * other type * @throws LuaError if was not a string or number or nil or none. * @see #tojstring() * @see #optstring(LuaString) @@ -737,13 +837,16 @@ 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} + /** + * 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 - * @return {@code this} converted to {@link LuaString} if a string or number, - * {@code defval} if nil or none, - * throws {@link LuaError} if some other type + * @return {@code this} converted to {@link LuaString} if a string or + * number, {@code defval} if nil or none, throws {@link LuaError} if + * some other type * @throws LuaError if was not a string or number or nil or none. * @see #tojstring() * @see #optjstring(String) @@ -751,61 +854,70 @@ public class LuaValue extends Varargs { * @see #toString() * @see #TSTRING */ - public LuaString optstring(LuaString defval) { argerror("string"); return null; } + public LuaString optstring(LuaString defval) { argerror("string"); return null; } - /** Check that optional argument is a table and return as {@link LuaTable} + /** + * Check that optional argument is a table and return as {@link LuaTable} + * * @param defval {@link LuaTable} to return if {@code this} is nil or none - * @return {@code this} cast to {@link LuaTable} if a table, - * {@code defval} if nil or none, - * throws {@link LuaError} if some other type + * @return {@code this} cast to {@link LuaTable} if a table, {@code defval} + * if nil or none, throws {@link LuaError} if some other type * @throws LuaError if was not a table or nil or none. * @see #checktable() * @see #istable() * @see #TTABLE */ - public LuaTable opttable(LuaTable defval) { argerror("table"); return null; } + public LuaTable opttable(LuaTable defval) { argerror("table"); return null; } - /** Check that optional argument is a thread and return as {@link LuaThread} + /** + * Check that optional argument is a thread and return as {@link LuaThread} + * * @param defval {@link LuaThread} to return if {@code this} is nil or none - * @return {@code this} cast to {@link LuaTable} if a thread, - * {@code defval} if nil or none, - * throws {@link LuaError} if some other type + * @return {@code this} cast to {@link LuaTable} if a thread, {@code defval} + * if nil or none, throws {@link LuaError} if some other type * @throws LuaError if was not a thread or nil or none. * @see #checkthread() * @see #isthread() * @see #TTHREAD */ - public LuaThread optthread(LuaThread defval) { argerror("thread"); return null; } + public LuaThread optthread(LuaThread defval) { argerror("thread"); return null; } - /** Check that optional argument is a userdata and return the Object instance + /** + * Check that optional argument is a userdata and return the Object instance + * * @param defval Object to return if {@code this} is nil or none * @return Object instance of the userdata if a {@link LuaUserdata}, - * {@code defval} if nil or none, - * throws {@link LuaError} if some other type + * {@code defval} if nil or none, throws {@link LuaError} if some + * other type * @throws LuaError if was not a userdata or nil or none. * @see #checkuserdata() * @see #isuserdata() * @see #optuserdata(Class, Object) * @see #TUSERDATA */ - public Object optuserdata(Object defval) { argerror("object"); return null; } + public Object optuserdata(Object defval) { argerror("object"); return null; } - /** Check that optional argument is a userdata whose instance is of a type + /** + * Check that optional argument is a userdata whose instance is of a type * and return the Object instance - * @param c Class to test userdata instance against + * + * @param c Class to test userdata instance against * @param defval Object to return if {@code this} is nil or none - * @return Object instance of the userdata if a {@link LuaUserdata} and instance is assignable to {@code c}, - * {@code defval} if nil or none, - * throws {@link LuaError} if some other type - * @throws LuaError if was not a userdata whose instance is assignable to {@code c} or nil or none. + * @return Object instance of the userdata if a {@link LuaUserdata} and + * instance is assignable to {@code c}, {@code defval} if nil or + * none, throws {@link LuaError} if some other type + * @throws LuaError if was not a userdata whose instance is assignable to + * {@code c} or nil or none. * @see #checkuserdata(Class) * @see #isuserdata(Class) * @see #optuserdata(Object) * @see #TUSERDATA */ - public Object optuserdata(Class c, Object defval) { argerror(c.getName()); return null; } + public Object optuserdata(Class c, Object defval) { argerror(c.getName()); return null; } - /** Perform argument check that this is not nil or none. + /** + * Perform argument check that this is not nil or none. + * * @param defval {@link LuaValue} to return if {@code this} is nil or none * @return {@code this} if not nil or none, else {@code defval} * @see #NIL @@ -815,22 +927,26 @@ public class LuaValue extends Varargs { * @see #TNIL * @see #TNONE */ - public LuaValue optvalue(LuaValue defval) { return this; } + public LuaValue optvalue(LuaValue defval) { return this; } - - /** Check that the value is a {@link LuaBoolean}, - * or throw {@link LuaError} if not + /** + * Check that the value is a {@link LuaBoolean}, or throw {@link LuaError} + * if not + * * @return boolean value for {@code this} if it is a {@link LuaBoolean} * @throws LuaError if not a {@link LuaBoolean} * @see #optboolean(boolean) * @see #TBOOLEAN */ - public boolean checkboolean() { argerror("boolean"); return false; } - - /** Check that the value is a {@link LuaClosure} , - * or throw {@link LuaError} if not + public boolean checkboolean() { argerror("boolean"); return false; } + + /** + * Check that the value is a {@link LuaClosure} , or throw {@link LuaError} + * if not *

- * {@link LuaClosure} is a subclass of {@link LuaFunction} that interprets lua bytecode. + * {@link LuaClosure} is a subclass of {@link LuaFunction} that interprets + * lua bytecode. + * * @return {@code this} cast as {@link LuaClosure} * @throws LuaError if not a {@link LuaClosure} * @see #checkfunction() @@ -838,93 +954,118 @@ public class LuaValue extends Varargs { * @see #isclosure() * @see #TFUNCTION */ - public LuaClosure checkclosure() { argerror("closure"); return null; } - - /** Check that the value is numeric and return the value as a double, - * or throw {@link LuaError} if not numeric + public LuaClosure checkclosure() { argerror("closure"); return null; } + + /** + * Check that the value is numeric and return the value as a double, or + * throw {@link LuaError} if not numeric *

* Values that are {@link LuaNumber} and values that are {@link LuaString} * that can be converted to a number will be converted to double. + * * @return value cast to a double if numeric - * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number + * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} + * that can't be converted to number * @see #checkint() * @see #checkinteger() * @see #checklong() * @see #optdouble(double) * @see #TNUMBER */ - public double checkdouble() { argerror("number"); return 0; } - - /** Check that the value is a function , or throw {@link LuaError} if not + public double checkdouble() { argerror("number"); return 0; } + + /** + * Check that the value is a function , or throw {@link LuaError} if not *

* A {@link LuaFunction} may either be a Java function that implements - * functionality directly in Java, or a {@link LuaClosure} - * which is a {@link LuaFunction} that executes lua bytecode. + * functionality directly in Java, or a {@link LuaClosure} which is a + * {@link LuaFunction} that executes lua bytecode. + * * @return {@code this} if it is a lua function or closure * @throws LuaError if not a function * @see #checkclosure() */ - public LuaFunction checkfunction() { argerror("function"); return null; } + public LuaFunction checkfunction() { argerror("function"); return null; } - - /** Check that the value is a Globals instance, or throw {@link LuaError} if not + /** + * Check that the value is a Globals instance, or throw {@link LuaError} if + * not *

- * {@link Globals} are a special {@link LuaTable} that establish the default global environment. + * {@link Globals} are a special {@link LuaTable} that establish the default + * global environment. + * * @return {@code this} if if an instance fof {@link Globals} * @throws LuaError if not a {@link Globals} instance. */ - public Globals checkglobals() { argerror("globals"); return null; } + public Globals checkglobals() { argerror("globals"); return null; } - /** Check that the value is numeric, and convert and cast value to int, or throw {@link LuaError} if not numeric + /** + * Check that the value is numeric, and convert and cast value to int, or + * throw {@link LuaError} if not numeric *

- * Values that are {@link LuaNumber} will be cast to int and may lose precision. - * Values that are {@link LuaString} that can be converted to a number will be converted, - * then cast to int, so may also lose precision. + * Values that are {@link LuaNumber} will be cast to int and may lose + * precision. Values that are {@link LuaString} that can be converted to a + * number will be converted, then cast to int, so may also lose precision. + * * @return value cast to a int if numeric - * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number + * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} + * that can't be converted to number * @see #checkinteger() * @see #checklong() * @see #checkdouble() * @see #optint(int) * @see #TNUMBER */ - public int checkint() { argerror("int"); return 0; } + public int checkint() { argerror("int"); return 0; } - /** Check that the value is numeric, and convert and cast value to int, or throw {@link LuaError} if not numeric + /** + * Check that the value is numeric, and convert and cast value to int, or + * throw {@link LuaError} if not numeric *

- * Values that are {@link LuaNumber} will be cast to int and may lose precision. - * Values that are {@link LuaString} that can be converted to a number will be converted, - * then cast to int, so may also lose precision. + * Values that are {@link LuaNumber} will be cast to int and may lose + * precision. Values that are {@link LuaString} that can be converted to a + * number will be converted, then cast to int, so may also lose precision. + * * @return value cast to a int and wrapped in {@link LuaInteger} if numeric - * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number + * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} + * that can't be converted to number * @see #checkint() * @see #checklong() * @see #checkdouble() * @see #optinteger(LuaInteger) * @see #TNUMBER */ - public LuaInteger checkinteger() { argerror("integer"); return null; } - - /** Check that the value is numeric, and convert and cast value to long, or throw {@link LuaError} if not numeric + public LuaInteger checkinteger() { argerror("integer"); return null; } + + /** + * Check that the value is numeric, and convert and cast value to long, or + * throw {@link LuaError} if not numeric *

- * Values that are {@link LuaNumber} will be cast to long and may lose precision. - * Values that are {@link LuaString} that can be converted to a number will be converted, - * then cast to long, so may also lose precision. + * Values that are {@link LuaNumber} will be cast to long and may lose + * precision. Values that are {@link LuaString} that can be converted to a + * number will be converted, then cast to long, so may also lose precision. + * * @return value cast to a long if numeric - * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number + * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} + * that can't be converted to number * @see #checkint() * @see #checkinteger() * @see #checkdouble() * @see #optlong(long) * @see #TNUMBER */ - public long checklong() { argerror("long"); return 0; } - - /** Check that the value is numeric, and return as a LuaNumber if so, or throw {@link LuaError} + public long checklong() { argerror("long"); return 0; } + + /** + * Check that the value is numeric, and return as a LuaNumber if so, or + * throw {@link LuaError} *

- * Values that are {@link LuaString} that can be converted to a number will be converted and returned. + * Values that are {@link LuaString} that can be converted to a number will + * be converted and returned. + * * @return value as a {@link LuaNumber} if numeric - * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number + * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} + * that can't be converted to number * @see #checkint() * @see #checkinteger() * @see #checkdouble() @@ -932,14 +1073,19 @@ public class LuaValue extends Varargs { * @see #optnumber(LuaNumber) * @see #TNUMBER */ - public LuaNumber checknumber() { argerror("number"); return null; } - - /** Check that the value is numeric, and return as a LuaNumber if so, or throw {@link LuaError} + public LuaNumber checknumber() { argerror("number"); return null; } + + /** + * Check that the value is numeric, and return as a LuaNumber if so, or + * throw {@link LuaError} *

- * Values that are {@link LuaString} that can be converted to a number will be converted and returned. + * Values that are {@link LuaString} that can be converted to a number will + * be converted and returned. + * * @param msg String message to supply if conversion fails * @return value as a {@link LuaNumber} if numeric - * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} that can't be converted to number + * @throws LuaError if not a {@link LuaNumber} or is a {@link LuaString} + * that can't be converted to number * @see #checkint() * @see #checkinteger() * @see #checkdouble() @@ -947,13 +1093,15 @@ public class LuaValue extends Varargs { * @see #optnumber(LuaNumber) * @see #TNUMBER */ - public LuaNumber checknumber(String msg) { throw new LuaError(msg); } - - /** Convert this value to a Java String. + public LuaNumber checknumber(String msg) { throw new LuaError(msg); } + + /** + * Convert this value to a Java String. *

- * The string representations here will roughly match what is produced by the - * C lua distribution, however hash codes have no relationship, - * and there may be differences in number formatting. + * The string representations here will roughly match what is produced by + * the C lua distribution, however hash codes have no relationship, and + * there may be differences in number formatting. + * * @return String representation of the value * @see #checkstring() * @see #optjstring(String) @@ -961,15 +1109,17 @@ public class LuaValue extends Varargs { * @see #isstring * @see #TSTRING */ - public String checkjstring() { argerror("string"); return null; } - - /** Check that this is a lua string, or throw {@link LuaError} if it is not. + public String checkjstring() { argerror("string"); return null; } + + /** + * Check that this is a lua string, or throw {@link LuaError} if it is not. *

- * In lua all numbers are strings, so this will succeed for - * anything that derives from {@link LuaString} or {@link LuaNumber}. - * Numbers will be converted to {@link LuaString}. + * In lua all numbers are strings, so this will succeed for anything that + * derives from {@link LuaString} or {@link LuaNumber}. Numbers will be + * converted to {@link LuaString}. * - * @return {@link LuaString} representation of the value if it is a {@link LuaString} or {@link LuaNumber} + * @return {@link LuaString} representation of the value if it is a + * {@link LuaString} or {@link LuaNumber} * @throws LuaError if {@code this} is not a {@link LuaTable} * @see #checkjstring() * @see #optstring(LuaString) @@ -977,27 +1127,36 @@ public class LuaValue extends Varargs { * @see #isstring() * @see #TSTRING */ - public LuaString checkstring() { argerror("string"); return null; } - - /** Check that this is a {@link LuaTable}, or throw {@link LuaError} if it is not + public LuaString checkstring() { argerror("string"); return null; } + + /** + * Check that this is a {@link LuaTable}, or throw {@link LuaError} if it is + * not + * * @return {@code this} if it is a {@link LuaTable} * @throws LuaError if {@code this} is not a {@link LuaTable} * @see #istable() * @see #opttable(LuaTable) * @see #TTABLE */ - public LuaTable checktable() { argerror("table"); return null; } - - /** Check that this is a {@link LuaThread}, or throw {@link LuaError} if it is not + public LuaTable checktable() { argerror("table"); return null; } + + /** + * Check that this is a {@link LuaThread}, or throw {@link LuaError} if it + * is not + * * @return {@code this} if it is a {@link LuaThread} * @throws LuaError if {@code this} is not a {@link LuaThread} * @see #isthread() * @see #optthread(LuaThread) * @see #TTHREAD */ - public LuaThread checkthread() { argerror("thread"); return null; } - - /** Check that this is a {@link LuaUserdata}, or throw {@link LuaError} if it is not + public LuaThread checkthread() { argerror("thread"); return null; } + + /** + * Check that this is a {@link LuaUserdata}, or throw {@link LuaError} if it + * is not + * * @return {@code this} if it is a {@link LuaUserdata} * @throws LuaError if {@code this} is not a {@link LuaUserdata} * @see #isuserdata() @@ -1005,9 +1164,12 @@ public class LuaValue extends Varargs { * @see #checkuserdata(Class) * @see #TUSERDATA */ - public Object checkuserdata() { argerror("userdata"); return null; } - - /** Check that this is a {@link LuaUserdata}, or throw {@link LuaError} if it is not + public Object checkuserdata() { argerror("userdata"); return null; } + + /** + * Check that this is a {@link LuaUserdata}, or throw {@link LuaError} if it + * is not + * * @return {@code this} if it is a {@link LuaUserdata} * @throws LuaError if {@code this} is not a {@link LuaUserdata} * @see #isuserdata(Class) @@ -1015,293 +1177,388 @@ public class LuaValue extends Varargs { * @see #checkuserdata() * @see #TUSERDATA */ - public Object checkuserdata(Class c) { argerror("userdata"); return null; } - - /** Check that this is not the value {@link #NIL}, or throw {@link LuaError} if it is + public Object checkuserdata(Class c) { argerror("userdata"); return null; } + + /** + * Check that this is not the value {@link #NIL}, or throw {@link LuaError} + * if it is + * * @return {@code this} if it is not {@link #NIL} * @throws LuaError if {@code this} is {@link #NIL} * @see #optvalue(LuaValue) */ - public LuaValue checknotnil() { return this; } - - /** Return true if this is a valid key in a table index operation. + public LuaValue checknotnil() { return this; } + + /** + * Return true if this is a valid key in a table index operation. + * * @return true if valid as a table key, otherwise false * @see #isnil() * @see #isinttype() */ - public boolean isvalidkey() { return true; } - + public boolean isvalidkey() { return true; } + /** * Throw a {@link LuaError} with a particular message + * * @param message String providing message details * @throws LuaError in all cases */ public static LuaValue error(String message) { throw new LuaError(message); } /** - * Assert a condition is true, or throw a {@link LuaError} if not - * Returns no value when b is true, throws {@link #error(String)} with {@code msg} as argument - * and does not return if b is false. - * @param b condition to test + * Assert a condition is true, or throw a {@link LuaError} if not Returns no + * value when b is true, throws {@link #error(String)} with {@code msg} as + * argument and does not return if b is false. + * + * @param b condition to test * @param msg String message to produce on failure * @throws LuaError if b is not true */ - public static void assert_(boolean b,String msg) { if(!b) throw new LuaError(msg); } - + public static void assert_(boolean b, String msg) { + if (!b) + throw new LuaError(msg); + } + /** - * Throw a {@link LuaError} indicating an invalid argument was supplied to a function + * Throw a {@link LuaError} indicating an invalid argument was supplied to a + * function + * * @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 + * Throw a {@link LuaError} indicating an invalid argument was supplied to a + * function + * * @param iarg index of the argument that was invalid, first index is 1 - * @param msg String providing information about the invalid argument + * @param msg String providing information about the invalid argument * @throws LuaError in all cases */ - public static LuaValue argerror(int iarg,String msg) { throw new LuaError("bad argument #"+iarg+": "+msg); } - + public static LuaValue argerror(int iarg, String msg) { + throw new LuaError("bad argument #" + iarg + ": " + msg); + } + /** - * Throw a {@link LuaError} indicating an invalid type was supplied to a function + * Throw a {@link LuaError} indicating an invalid type was supplied to a + * function + * * @param expected String naming the type that was expected * @throws LuaError in all cases */ - protected LuaValue typerror(String expected) { throw new LuaError(expected+" expected, got "+typename()); } - + protected LuaValue typerror(String expected) { throw new LuaError(expected + " expected, got " + typename()); } + /** * Throw a {@link LuaError} indicating an operation is not implemented + * * @throws LuaError in all cases */ - protected LuaValue unimplemented(String fun) { throw new LuaError("'"+fun+"' not implemented for "+typename()); } - + protected LuaValue unimplemented(String fun) { + throw new LuaError("'" + fun + "' not implemented for " + typename()); + } + /** * Throw a {@link LuaError} indicating an illegal operation occurred, * typically involved in managing weak references + * * @throws LuaError in all cases */ - protected LuaValue illegal(String op,String typename) { throw new LuaError("illegal operation '"+op+"' for "+typename); } - + protected LuaValue illegal(String op, String typename) { + throw new LuaError("illegal operation '" + op + "' for " + typename); + } + /** - * Throw a {@link LuaError} based on the len operator, - * typically due to an invalid operand type + * Throw a {@link LuaError} based on the len operator, typically due to an + * invalid operand type + * * @throws LuaError in all cases */ - protected LuaValue lenerror() { throw new LuaError("attempt to get length of "+typename()); } - + protected LuaValue lenerror() { throw new LuaError("attempt to get length of " + typename()); } + /** - * Throw a {@link LuaError} based on an arithmetic error such as add, or pow, - * typically due to an invalid operand type + * Throw a {@link LuaError} based on an arithmetic error such as add, or + * pow, typically due to an invalid operand type + * * @throws LuaError in all cases */ - protected LuaValue aritherror() { throw new LuaError("attempt to perform arithmetic on "+typename()); } - + protected LuaValue aritherror() { throw new LuaError("attempt to perform arithmetic on " + typename()); } + /** - * Throw a {@link LuaError} based on an arithmetic error such as add, or pow, - * typically due to an invalid operand type + * Throw a {@link LuaError} based on an arithmetic error such as add, or + * pow, typically due to an invalid operand type + * * @param fun String description of the function that was attempted * @throws LuaError in all cases */ - protected LuaValue aritherror(String fun) { throw new LuaError("attempt to perform arithmetic '"+fun+"' on "+typename()); } - + protected LuaValue aritherror(String fun) { + throw new LuaError("attempt to perform arithmetic '" + fun + "' on " + typename()); + } + /** - * Throw a {@link LuaError} based on a comparison error such as greater-than or less-than, - * typically due to an invalid operand type - * @param rhs String description of what was on the right-hand-side of the comparison that resulted in the error. + * Throw a {@link LuaError} based on a comparison error such as greater-than + * or less-than, typically due to an invalid operand type + * + * @param rhs String description of what was on the right-hand-side of the + * comparison that resulted in the error. * @throws LuaError in all cases */ - protected LuaValue compareerror(String rhs) { throw new LuaError("attempt to compare "+typename()+" with "+rhs); } - + protected LuaValue compareerror(String rhs) { + throw new LuaError("attempt to compare " + typename() + " with " + rhs); + } + /** - * Throw a {@link LuaError} based on a comparison error such as greater-than or less-than, - * typically due to an invalid operand type + * Throw a {@link LuaError} based on a comparison error such as greater-than + * or less-than, typically due to an invalid operand type + * * @param rhs Right-hand-side of the comparison that resulted in the error. * @throws LuaError in all cases */ - protected LuaValue compareerror(LuaValue rhs) { throw new LuaError("attempt to compare "+typename()+" with "+rhs.typename()); } - - /** Get a value in a table including metatag processing using {@link #INDEX}. + protected LuaValue compareerror(LuaValue rhs) { + throw new LuaError("attempt to compare " + typename() + " with " + rhs.typename()); + } + + /** + * Get a value in a table including metatag processing using {@link #INDEX}. + * * @param key the key to look up, must not be {@link #NIL} or null - * @return {@link LuaValue} for that key, or {@link #NIL} if not found and no metatag - * @throws LuaError if {@code this} is not a table, - * or there is no {@link #INDEX} metatag, - * or key is {@link #NIL} + * @return {@link LuaValue} for that key, or {@link #NIL} if not found and + * no metatag + * @throws LuaError if {@code this} is not a table, or there is no + * {@link #INDEX} metatag, or key is {@link #NIL} * @see #get(int) * @see #get(String) * @see #rawget(LuaValue) */ - public LuaValue get( LuaValue key ) { return gettable(this,key); } - - /** Get a value in a table including metatag processing using {@link #INDEX}. + public LuaValue get(LuaValue key) { return gettable(this, key); } + + /** + * Get a value in a table including metatag processing using {@link #INDEX}. + * * @param key the key to look up * @return {@link LuaValue} for that key, or {@link #NIL} if not found - * @throws LuaError if {@code this} is not a table, - * or there is no {@link #INDEX} metatag + * @throws LuaError if {@code this} is not a table, or there is no + * {@link #INDEX} metatag * @see #get(LuaValue) * @see #rawget(int) */ - public LuaValue get( int key ) { return get(LuaInteger.valueOf(key)); } + public LuaValue get(int key) { return get(LuaInteger.valueOf(key)); } - /** Get a value in a table including metatag processing using {@link #INDEX}. + /** + * Get a value in a table including metatag processing using {@link #INDEX}. + * * @param key the key to look up, must not be null * @return {@link LuaValue} for that key, or {@link #NIL} if not found - * @throws LuaError if {@code this} is not a table, - * or there is no {@link #INDEX} metatag + * @throws LuaError if {@code this} is not a table, or there is no + * {@link #INDEX} metatag * @see #get(LuaValue) * @see #rawget(String) */ - public LuaValue get( String key ) { return get(valueOf(key)); } - - /** Set a value in a table without metatag processing using {@link #NEWINDEX}. - * @param key the key to use, must not be {@link #NIL} or null - * @param value the value to use, can be {@link #NIL}, must not be null - * @throws LuaError if {@code this} is not a table, - * or key is {@link #NIL}, - * or there is no {@link #NEWINDEX} metatag - */ - public void set( LuaValue key, LuaValue value ) { settable(this, key, value); } - - /** Set a value in a table without metatag processing using {@link #NEWINDEX}. - * @param key the key to use - * @param value the value to use, can be {@link #NIL}, must not be null - * @throws LuaError if {@code this} is not a table, - * or there is no {@link #NEWINDEX} metatag - */ - public void set( int key, LuaValue value ) { set(LuaInteger.valueOf(key), value ); } - - /** Set a value in a table without metatag processing using {@link #NEWINDEX}. - * @param key the key to use - * @param value the value to use, must not be null - * @throws LuaError if {@code this} is not a table, - * or there is no {@link #NEWINDEX} metatag - */ - public void set( int key, String value ) { set(key, valueOf(value) ); } - - /** Set a value in a table without metatag processing using {@link #NEWINDEX}. - * @param key the key to use, must not be {@link #NIL} or null - * @param value the value to use, can be {@link #NIL}, must not be null - * @throws LuaError if {@code this} is not a table, - * or there is no {@link #NEWINDEX} metatag - */ - public void set( String key, LuaValue value ) { set(valueOf(key), value ); } - - /** Set a value in a table without metatag processing using {@link #NEWINDEX}. - * @param key the key to use, must not be null - * @param value the value to use - * @throws LuaError if {@code this} is not a table, - * or there is no {@link #NEWINDEX} metatag - */ - public void set( String key, double value ) { set(valueOf(key), valueOf(value) ); } - - /** Set a value in a table without metatag processing using {@link #NEWINDEX}. - * @param key the key to use, must not be null - * @param value the value to use - * @throws LuaError if {@code this} is not a table, - * or there is no {@link #NEWINDEX} metatag - */ - public void set( String key, int value ) { set(valueOf(key), valueOf(value) ); } - - /** Set a value in a table without metatag processing using {@link #NEWINDEX}. - * @param key the key to use, must not be null - * @param value the value to use, must not be null - * @throws LuaError if {@code this} is not a table, - * or there is no {@link #NEWINDEX} metatag - */ - public void set( String key, String value ) { set(valueOf(key), valueOf(value) ); } + public LuaValue get(String key) { return get(valueOf(key)); } - /** Get a value in a table without metatag processing. + /** + * Set a value in a table without metatag processing using + * {@link #NEWINDEX}. + * + * @param key the key to use, must not be {@link #NIL} or null + * @param value the value to use, can be {@link #NIL}, must not be null + * @throws LuaError if {@code this} is not a table, or key is {@link #NIL}, + * or there is no {@link #NEWINDEX} metatag + */ + public void set(LuaValue key, LuaValue value) { settable(this, key, value); } + + /** + * Set a value in a table without metatag processing using + * {@link #NEWINDEX}. + * + * @param key the key to use + * @param value the value to use, can be {@link #NIL}, must not be null + * @throws LuaError if {@code this} is not a table, or there is no + * {@link #NEWINDEX} metatag + */ + public void set(int key, LuaValue value) { set(LuaInteger.valueOf(key), value); } + + /** + * Set a value in a table without metatag processing using + * {@link #NEWINDEX}. + * + * @param key the key to use + * @param value the value to use, must not be null + * @throws LuaError if {@code this} is not a table, or there is no + * {@link #NEWINDEX} metatag + */ + public void set(int key, String value) { set(key, valueOf(value)); } + + /** + * Set a value in a table without metatag processing using + * {@link #NEWINDEX}. + * + * @param key the key to use, must not be {@link #NIL} or null + * @param value the value to use, can be {@link #NIL}, must not be null + * @throws LuaError if {@code this} is not a table, or there is no + * {@link #NEWINDEX} metatag + */ + public void set(String key, LuaValue value) { set(valueOf(key), value); } + + /** + * Set a value in a table without metatag processing using + * {@link #NEWINDEX}. + * + * @param key the key to use, must not be null + * @param value the value to use + * @throws LuaError if {@code this} is not a table, or there is no + * {@link #NEWINDEX} metatag + */ + public void set(String key, double value) { set(valueOf(key), valueOf(value)); } + + /** + * Set a value in a table without metatag processing using + * {@link #NEWINDEX}. + * + * @param key the key to use, must not be null + * @param value the value to use + * @throws LuaError if {@code this} is not a table, or there is no + * {@link #NEWINDEX} metatag + */ + public void set(String key, int value) { set(valueOf(key), valueOf(value)); } + + /** + * Set a value in a table without metatag processing using + * {@link #NEWINDEX}. + * + * @param key the key to use, must not be null + * @param value the value to use, must not be null + * @throws LuaError if {@code this} is not a table, or there is no + * {@link #NEWINDEX} metatag + */ + public void set(String key, String value) { set(valueOf(key), valueOf(value)); } + + /** + * Get a value in a table without metatag processing. + * * @param key the key to look up, must not be {@link #NIL} or null * @return {@link LuaValue} for that key, or {@link #NIL} if not found * @throws LuaError if {@code this} is not a table, or key is {@link #NIL} */ - public LuaValue rawget( LuaValue key ) { return unimplemented("rawget"); } + public LuaValue rawget(LuaValue key) { return unimplemented("rawget"); } - /** Get a value in a table without metatag processing. + /** + * Get a value in a table without metatag processing. + * * @param key the key to look up * @return {@link LuaValue} for that key, or {@link #NIL} if not found * @throws LuaError if {@code this} is not a table */ - public LuaValue rawget( int key ) { return rawget(valueOf(key)); } + public LuaValue rawget(int key) { return rawget(valueOf(key)); } - /** Get a value in a table without metatag processing. + /** + * Get a value in a table without metatag processing. + * * @param key the key to look up, must not be null * @return {@link LuaValue} for that key, or {@link #NIL} if not found * @throws LuaError if {@code this} is not a table */ - public LuaValue rawget( String key ) { return rawget(valueOf(key)); } - - /** Set a value in a table without metatag processing. - * @param key the key to use, must not be {@link #NIL} or null + public LuaValue rawget(String key) { return rawget(valueOf(key)); } + + /** + * Set a value in a table without metatag processing. + * + * @param key the key to use, must not be {@link #NIL} or null * @param value the value to use, can be {@link #NIL}, must not be null * @throws LuaError if {@code this} is not a table, or key is {@link #NIL} */ - public void rawset( LuaValue key, LuaValue value ) { unimplemented("rawset"); } - - /** Set a value in a table without metatag processing. - * @param key the key to use + public void rawset(LuaValue key, LuaValue value) { unimplemented("rawset"); } + + /** + * Set a value in a table without metatag processing. + * + * @param key the key to use * @param value the value to use, can be {@link #NIL}, must not be null * @throws LuaError if {@code this} is not a table */ - public void rawset( int key, LuaValue value ) { rawset(valueOf(key),value); } - - /** Set a value in a table without metatag processing. - * @param key the key to use + public void rawset(int key, LuaValue value) { rawset(valueOf(key), value); } + + /** + * Set a value in a table without metatag processing. + * + * @param key the key to use * @param value the value to use, can be {@link #NIL}, must not be null * @throws LuaError if {@code this} is not a table */ - public void rawset( int key, String value ) { rawset(key,valueOf(value)); } - - /** Set a value in a table without metatag processing. - * @param key the key to use, must not be null + public void rawset(int key, String value) { rawset(key, valueOf(value)); } + + /** + * Set a value in a table without metatag processing. + * + * @param key the key to use, must not be null * @param value the value to use, can be {@link #NIL}, must not be null * @throws LuaError if {@code this} is not a table */ - public void rawset( String key, LuaValue value ) { rawset(valueOf(key),value); } - - /** Set a value in a table without metatag processing. - * @param key the key to use, must not be null + public void rawset(String key, LuaValue value) { rawset(valueOf(key), value); } + + /** + * Set a value in a table without metatag processing. + * + * @param key the key to use, must not be null * @param value the value to use * @throws LuaError if {@code this} is not a table */ - public void rawset( String key, double value ) { rawset(valueOf(key),valueOf(value)); } - - /** Set a value in a table without metatag processing. - * @param key the key to use, must not be null + public void rawset(String key, double value) { rawset(valueOf(key), valueOf(value)); } + + /** + * Set a value in a table without metatag processing. + * + * @param key the key to use, must not be null * @param value the value to use * @throws LuaError if {@code this} is not a table */ - public void rawset( String key, int value ) { rawset(valueOf(key),valueOf(value)); } - - /** Set a value in a table without metatag processing. - * @param key the key to use, must not be null + public void rawset(String key, int value) { rawset(valueOf(key), valueOf(value)); } + + /** + * Set a value in a table without metatag processing. + * + * @param key the key to use, must not be null * @param value the value to use, must not be null * @throws LuaError if {@code this} is not a table */ - public void rawset( String key, String value ) { rawset(valueOf(key),valueOf(value)); } + public void rawset(String key, String value) { rawset(valueOf(key), valueOf(value)); } - /** Set list values in a table without invoking metatag processing + /** + * Set list values in a table without invoking metatag processing *

* Primarily used internally in response to a SETLIST bytecode. - * @param key0 the first key to set in the table + * + * @param key0 the first key to set in the table * @param values the list of values to set * @throws LuaError if this is not a table. */ - public void rawsetlist( int key0, Varargs values ) { for ( int i=0, n=values.narg(); i * Primarily used internally in response to a SETLIST bytecode. + * * @param i the number of array slots to preallocate in the table. * @throws LuaError if this is not a table. */ - public void presize( int i) { typerror("table"); } - - /** Find the next key,value pair if {@code this} is a table, - * return {@link #NIL} if there are no more, or throw a {@link LuaError} if not a table. + public void presize(int i) { typerror("table"); } + + /** + * Find the next key,value pair if {@code this} is a table, return + * {@link #NIL} if there are no more, or throw a {@link LuaError} if not a + * table. *

* To iterate over all key-value pairs in a table you can use - *

 {@code
+	 * 
+	 * 
+	 *  {@code
 	 * LuaValue k = LuaValue.NIL;
 	 * while ( true ) {
 	 *    Varargs n = table.next(k);
@@ -1309,12 +1566,15 @@ public class LuaValue extends Varargs {
 	 *       break;
 	 *    LuaValue v = n.arg(2)
 	 *    process( k, v )
-	 * }}
- * @param index {@link LuaInteger} value identifying a key to start from, - * or {@link #NIL} to start at the beginning - * @return {@link Varargs} containing {key,value} for the next entry, - * or {@link #NIL} if there are no more. - * @throws LuaError if {@code this} is not a table, or the supplied key is invalid. + * }} + *
+ * + * @param index {@link LuaInteger} value identifying a key to start from, or + * {@link #NIL} to start at the beginning + * @return {@link Varargs} containing {key,value} for the next entry, or + * {@link #NIL} if there are no more. + * @throws LuaError if {@code this} is not a table, or the supplied key is + * invalid. * @see LuaTable * @see #inext(LuaValue) * @see #valueOf(int) @@ -1323,12 +1583,16 @@ public class LuaValue extends Varargs { * @see #isnil() */ public Varargs next(LuaValue index) { return typerror("table"); } - - /** Find the next integer-key,value pair if {@code this} is a table, - * return {@link #NIL} if there are no more, or throw a {@link LuaError} if not a table. + + /** + * Find the next integer-key,value pair if {@code this} is a table, return + * {@link #NIL} if there are no more, or throw a {@link LuaError} if not a + * table. *

* To iterate over integer keys in a table you can use - *

 {@code
+	 * 
+	 * 
+	 *  {@code
 	 *   LuaValue k = LuaValue.NIL;
 	 *   while ( true ) {
 	 *      Varargs n = table.inext(k);
@@ -1337,12 +1601,15 @@ public class LuaValue extends Varargs {
 	 *      LuaValue v = n.arg(2)
 	 *      process( k, v )
 	 *   }
-	 * } 
- * @param index {@link LuaInteger} value identifying a key to start from, - * or {@link #NIL} to start at the beginning - * @return {@link Varargs} containing {@code (key,value)} for the next entry, - * or {@link #NONE} if there are no more. - * @throws LuaError if {@code this} is not a table, or the supplied key is invalid. + * } + *
+ * + * @param index {@link LuaInteger} value identifying a key to start from, or + * {@link #NIL} to start at the beginning + * @return {@link Varargs} containing {@code (key,value)} for the next + * entry, or {@link #NONE} if there are no more. + * @throws LuaError if {@code this} is not a table, or the supplied key is + * invalid. * @see LuaTable * @see #next(LuaValue) * @see #valueOf(int) @@ -1351,27 +1618,32 @@ public class LuaValue extends Varargs { * @see #isnil() */ public Varargs inext(LuaValue index) { return typerror("table"); } - + /** - * Load a library instance by calling it with and empty string as the modname, - * and this Globals as the environment. This is normally used to iniitalize the - * library instance and which may install itself into these globals. + * Load a library instance by calling it with and empty string as the + * modname, and this Globals as the environment. This is normally used to + * iniitalize the library instance and which may install itself into these + * globals. + * * @param library The callable {@link LuaValue} to load into {@code this} * @return {@link LuaValue} returned by the initialization call. */ public LuaValue load(LuaValue library) { return library.call(EMPTYSTRING, this); } // varargs references - public LuaValue arg(int index) { return index==1? this: NIL; } + public LuaValue arg(int index) { return index == 1? this: NIL; } + public int narg() { return 1; }; + public LuaValue arg1() { return this; } - + /** * Get the metatable for this {@link LuaValue} *

- * For {@link LuaTable} and {@link LuaUserdata} instances, - * the metatable returned is this instance metatable. - * For all other types, the class metatable value will be returned. + * For {@link LuaTable} and {@link LuaUserdata} instances, the metatable + * returned is this instance metatable. For all other types, the class + * metatable value will be returned. + * * @return metatable, or null if it there is none * @see LuaBoolean#s_metatable * @see LuaNumber#s_metatable @@ -1380,13 +1652,16 @@ public class LuaValue extends Varargs { * @see LuaThread#s_metatable */ public LuaValue getmetatable() { return null; } - + /** * Set the metatable for this {@link LuaValue} *

- * For {@link LuaTable} and {@link LuaUserdata} instances, the metatable is per instance. - * For all other types, there is one metatable per type that can be set directly from java - * @param metatable {@link LuaValue} instance to serve as the metatable, or null to reset it. + * For {@link LuaTable} and {@link LuaUserdata} instances, the metatable is + * per instance. For all other types, there is one metatable per type that + * can be set directly from java + * + * @param metatable {@link LuaValue} instance to serve as the metatable, or + * null to reset it. * @return {@code this} to allow chaining of Java function calls * @see LuaBoolean#s_metatable * @see LuaNumber#s_metatable @@ -1395,23 +1670,26 @@ public class LuaValue extends Varargs { * @see LuaThread#s_metatable */ public LuaValue setmetatable(LuaValue metatable) { return argerror("table"); } - - /** Call {@code this} with 0 arguments, including metatag processing, - * and return only the first return value. + + /** + * Call {@code this} with 0 arguments, including metatag processing, and + * return only the first return value. *

- * If {@code this} is a {@link LuaFunction}, call it, - * and return only its first return value, dropping any others. - * Otherwise, look for the {@link #CALL} metatag and call that. + * If {@code this} is a {@link LuaFunction}, call it, and return only its + * first return value, dropping any others. Otherwise, look for the + * {@link #CALL} metatag and call that. *

- * If the return value is a {@link Varargs}, only the 1st value will be returned. - * To get multiple values, use {@link #invoke()} instead. + * If the return value is a {@link Varargs}, only the 1st value will be + * returned. To get multiple values, use {@link #invoke()} instead. *

- * To call {@code this} as a method call, use {@link #method(LuaValue)} instead. + * To call {@code this} as a method call, use {@link #method(LuaValue)} + * instead. * - * @return First return value {@code (this())}, or {@link #NIL} if there were none. - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @return First return value {@code (this())}, or {@link #NIL} if there + * were none. + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call(LuaValue) * @see #call(LuaValue,LuaValue) * @see #call(LuaValue, LuaValue, LuaValue) @@ -1421,23 +1699,26 @@ public class LuaValue extends Varargs { */ public LuaValue call() { return callmt().call(this); } - /** Call {@code this} with 1 argument, including metatag processing, - * and return only the first return value. + /** + * Call {@code this} with 1 argument, including metatag processing, and + * return only the first return value. *

- * If {@code this} is a {@link LuaFunction}, call it, - * and return only its first return value, dropping any others. - * Otherwise, look for the {@link #CALL} metatag and call that. + * If {@code this} is a {@link LuaFunction}, call it, and return only its + * first return value, dropping any others. Otherwise, look for the + * {@link #CALL} metatag and call that. *

- * If the return value is a {@link Varargs}, only the 1st value will be returned. - * To get multiple values, use {@link #invoke()} instead. + * If the return value is a {@link Varargs}, only the 1st value will be + * returned. To get multiple values, use {@link #invoke()} instead. *

- * To call {@code this} as a method call, use {@link #method(LuaValue)} instead. + * To call {@code this} as a method call, use {@link #method(LuaValue)} + * instead. * * @param arg First argument to supply to the called function - * @return First return value {@code (this(arg))}, or {@link #NIL} if there were none. - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @return First return value {@code (this(arg))}, or {@link #NIL} if there + * were none. + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call() * @see #call(LuaValue,LuaValue) * @see #call(LuaValue, LuaValue, LuaValue) @@ -1445,33 +1726,40 @@ public class LuaValue extends Varargs { * @see #method(String,LuaValue) * @see #method(LuaValue,LuaValue) */ - public LuaValue call(LuaValue arg) { return callmt().call(this,arg); } + public LuaValue call(LuaValue arg) { return callmt().call(this, arg); } - /** Convenience function which calls a luavalue with a single, string argument. - * @param arg String argument to the function. This will be converted to a LuaString. + /** + * Convenience function which calls a luavalue with a single, string + * argument. + * + * @param arg String argument to the function. This will be converted to a + * LuaString. * @return return value of the invocation. * @see #call(LuaValue) */ public LuaValue call(String arg) { return call(valueOf(arg)); } - - /** Call {@code this} with 2 arguments, including metatag processing, - * and return only the first return value. + + /** + * Call {@code this} with 2 arguments, including metatag processing, and + * return only the first return value. *

- * If {@code this} is a {@link LuaFunction}, call it, - * and return only its first return value, dropping any others. - * Otherwise, look for the {@link #CALL} metatag and call that. + * If {@code this} is a {@link LuaFunction}, call it, and return only its + * first return value, dropping any others. Otherwise, look for the + * {@link #CALL} metatag and call that. *

- * If the return value is a {@link Varargs}, only the 1st value will be returned. - * To get multiple values, use {@link #invoke()} instead. + * If the return value is a {@link Varargs}, only the 1st value will be + * returned. To get multiple values, use {@link #invoke()} instead. *

- * To call {@code this} as a method call, use {@link #method(LuaValue)} instead. + * To call {@code this} as a method call, use {@link #method(LuaValue)} + * instead. * * @param arg1 First argument to supply to the called function * @param arg2 Second argument to supply to the called function - * @return First return value {@code (this(arg1,arg2))}, or {@link #NIL} if there were none. - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @return First return value {@code (this(arg1,arg2))}, or {@link #NIL} if + * there were none. + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call() * @see #call(LuaValue) * @see #call(LuaValue, LuaValue, LuaValue) @@ -1479,27 +1767,30 @@ public class LuaValue extends Varargs { * @see #method(String,LuaValue,LuaValue) * @see #method(LuaValue,LuaValue,LuaValue) */ - public LuaValue call(LuaValue arg1, LuaValue arg2) { return callmt().call(this,arg1,arg2); } + public LuaValue call(LuaValue arg1, LuaValue arg2) { return callmt().call(this, arg1, arg2); } - /** Call {@code this} with 3 arguments, including metatag processing, - * and return only the first return value. + /** + * Call {@code this} with 3 arguments, including metatag processing, and + * return only the first return value. *

- * If {@code this} is a {@link LuaFunction}, call it, - * and return only its first return value, dropping any others. - * Otherwise, look for the {@link #CALL} metatag and call that. + * If {@code this} is a {@link LuaFunction}, call it, and return only its + * first return value, dropping any others. Otherwise, look for the + * {@link #CALL} metatag and call that. *

- * If the return value is a {@link Varargs}, only the 1st value will be returned. - * To get multiple values, use {@link #invoke()} instead. + * If the return value is a {@link Varargs}, only the 1st value will be + * returned. To get multiple values, use {@link #invoke()} instead. *

- * To call {@code this} as a method call, use {@link #method(LuaValue)} instead. + * To call {@code this} as a method call, use {@link #method(LuaValue)} + * instead. * * @param arg1 First argument to supply to the called function * @param arg2 Second argument to supply to the called function * @param arg3 Second argument to supply to the called function - * @return First return value {@code (this(arg1,arg2,arg3))}, or {@link #NIL} if there were none. - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @return First return value {@code (this(arg1,arg2,arg3))}, or + * {@link #NIL} if there were none. + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call() * @see #call(LuaValue) * @see #call(LuaValue, LuaValue) @@ -1507,26 +1798,30 @@ public class LuaValue extends Varargs { * @see #invokemethod(String,Varargs) * @see #invokemethod(LuaValue,Varargs) */ - public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { return callmt().invoke(new LuaValue[]{this,arg1,arg2,arg3}).arg1(); } - - /** Call named method on {@code this} with 0 arguments, including metatag processing, - * and return only the first return value. + public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { + return callmt().invoke(new LuaValue[] { this, arg1, arg2, arg3 }).arg1(); + } + + /** + * Call named method on {@code this} with 0 arguments, including metatag + * processing, and return only the first return value. *

- * Look up {@code this[name]} and if it is a {@link LuaFunction}, - * call it inserting {@code this} as an additional first argument. - * and return only its first return value, dropping any others. - * Otherwise, look for the {@link #CALL} metatag and call that. + * Look up {@code this[name]} and if it is a {@link LuaFunction}, call it + * inserting {@code this} as an additional first argument. and return only + * its first return value, dropping any others. Otherwise, look for the + * {@link #CALL} metatag and call that. *

- * If the return value is a {@link Varargs}, only the 1st value will be returned. - * To get multiple values, use {@link #invoke()} instead. + * If the return value is a {@link Varargs}, only the 1st value will be + * returned. To get multiple values, use {@link #invoke()} instead. *

* To call {@code this} as a plain call, use {@link #call()} instead. * * @param name Name of the method to look up for invocation - * @return All values returned from {@code this:name()} as a {@link Varargs} instance - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @return All values returned from {@code this:name()} as a {@link Varargs} + * instance + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call() * @see #invoke() * @see #method(LuaValue) @@ -1535,24 +1830,26 @@ public class LuaValue extends Varargs { */ public LuaValue method(String name) { return this.get(name).call(this); } - /** Call named method on {@code this} with 0 arguments, including metatag processing, - * and return only the first return value. + /** + * Call named method on {@code this} with 0 arguments, including metatag + * processing, and return only the first return value. *

- * Look up {@code this[name]} and if it is a {@link LuaFunction}, - * call it inserting {@code this} as an additional first argument, - * and return only its first return value, dropping any others. - * Otherwise, look for the {@link #CALL} metatag and call that. + * Look up {@code this[name]} and if it is a {@link LuaFunction}, call it + * inserting {@code this} as an additional first argument, and return only + * its first return value, dropping any others. Otherwise, look for the + * {@link #CALL} metatag and call that. *

- * If the return value is a {@link Varargs}, only the 1st value will be returned. - * To get multiple values, use {@link #invoke()} instead. + * If the return value is a {@link Varargs}, only the 1st value will be + * returned. To get multiple values, use {@link #invoke()} instead. *

* To call {@code this} as a plain call, use {@link #call()} instead. * * @param name Name of the method to look up for invocation - * @return All values returned from {@code this:name()} as a {@link Varargs} instance - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @return All values returned from {@code this:name()} as a {@link Varargs} + * instance + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call() * @see #invoke() * @see #method(String) @@ -1560,129 +1857,147 @@ public class LuaValue extends Varargs { * @see #method(LuaValue,LuaValue,LuaValue) */ public LuaValue method(LuaValue name) { return this.get(name).call(this); } - - /** Call named method on {@code this} with 1 argument, including metatag processing, - * and return only the first return value. + + /** + * Call named method on {@code this} with 1 argument, including metatag + * processing, and return only the first return value. *

- * Look up {@code this[name]} and if it is a {@link LuaFunction}, - * call it inserting {@code this} as an additional first argument, - * and return only its first return value, dropping any others. - * Otherwise, look for the {@link #CALL} metatag and call that. + * Look up {@code this[name]} and if it is a {@link LuaFunction}, call it + * inserting {@code this} as an additional first argument, and return only + * its first return value, dropping any others. Otherwise, look for the + * {@link #CALL} metatag and call that. *

- * If the return value is a {@link Varargs}, only the 1st value will be returned. - * To get multiple values, use {@link #invoke()} instead. + * If the return value is a {@link Varargs}, only the 1st value will be + * returned. To get multiple values, use {@link #invoke()} instead. *

- * To call {@code this} as a plain call, use {@link #call(LuaValue)} instead. + * To call {@code this} as a plain call, use {@link #call(LuaValue)} + * instead. * * @param name Name of the method to look up for invocation - * @param arg Argument to supply to the method - * @return All values returned from {@code this:name(arg)} as a {@link Varargs} instance - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @param arg Argument to supply to the method + * @return All values returned from {@code this:name(arg)} as a + * {@link Varargs} instance + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call(LuaValue) * @see #invoke(Varargs) * @see #method(String) * @see #method(LuaValue) * @see #method(String,LuaValue,LuaValue) */ - public LuaValue method(String name, LuaValue arg) { return this.get(name).call(this,arg); } - - /** Call named method on {@code this} with 1 argument, including metatag processing, - * and return only the first return value. + public LuaValue method(String name, LuaValue arg) { return this.get(name).call(this, arg); } + + /** + * Call named method on {@code this} with 1 argument, including metatag + * processing, and return only the first return value. *

- * Look up {@code this[name]} and if it is a {@link LuaFunction}, - * call it inserting {@code this} as an additional first argument, - * and return only its first return value, dropping any others. - * Otherwise, look for the {@link #CALL} metatag and call that. + * Look up {@code this[name]} and if it is a {@link LuaFunction}, call it + * inserting {@code this} as an additional first argument, and return only + * its first return value, dropping any others. Otherwise, look for the + * {@link #CALL} metatag and call that. *

- * If the return value is a {@link Varargs}, only the 1st value will be returned. - * To get multiple values, use {@link #invoke()} instead. + * If the return value is a {@link Varargs}, only the 1st value will be + * returned. To get multiple values, use {@link #invoke()} instead. *

- * To call {@code this} as a plain call, use {@link #call(LuaValue)} instead. + * To call {@code this} as a plain call, use {@link #call(LuaValue)} + * instead. * * @param name Name of the method to look up for invocation - * @param arg Argument to supply to the method - * @return All values returned from {@code this:name(arg)} as a {@link Varargs} instance - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @param arg Argument to supply to the method + * @return All values returned from {@code this:name(arg)} as a + * {@link Varargs} instance + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call(LuaValue) * @see #invoke(Varargs) * @see #method(String,LuaValue) * @see #method(LuaValue) * @see #method(LuaValue,LuaValue,LuaValue) */ - public LuaValue method(LuaValue name, LuaValue arg) { return this.get(name).call(this,arg); } + public LuaValue method(LuaValue name, LuaValue arg) { return this.get(name).call(this, arg); } - /** Call named method on {@code this} with 2 arguments, including metatag processing, - * and return only the first return value. + /** + * Call named method on {@code this} with 2 arguments, including metatag + * processing, and return only the first return value. *

- * Look up {@code this[name]} and if it is a {@link LuaFunction}, - * call it inserting {@code this} as an additional first argument, - * and return only its first return value, dropping any others. - * Otherwise, look for the {@link #CALL} metatag and call that. + * Look up {@code this[name]} and if it is a {@link LuaFunction}, call it + * inserting {@code this} as an additional first argument, and return only + * its first return value, dropping any others. Otherwise, look for the + * {@link #CALL} metatag and call that. *

- * If the return value is a {@link Varargs}, only the 1st value will be returned. - * To get multiple values, use {@link #invoke()} instead. + * If the return value is a {@link Varargs}, only the 1st value will be + * returned. To get multiple values, use {@link #invoke()} instead. *

- * To call {@code this} as a plain call, use {@link #call(LuaValue,LuaValue)} instead. + * To call {@code this} as a plain call, use + * {@link #call(LuaValue,LuaValue)} instead. * * @param name Name of the method to look up for invocation * @param arg1 First argument to supply to the method * @param arg2 Second argument to supply to the method - * @return All values returned from {@code this:name(arg1,arg2)} as a {@link Varargs} instance - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @return All values returned from {@code this:name(arg1,arg2)} as a + * {@link Varargs} instance + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call(LuaValue,LuaValue) * @see #invoke(LuaValue,Varargs) * @see #method(String,LuaValue) * @see #method(LuaValue,LuaValue,LuaValue) */ - public LuaValue method(String name, LuaValue arg1, LuaValue arg2) { return this.get(name).call(this,arg1,arg2); } + public LuaValue method(String name, LuaValue arg1, LuaValue arg2) { + return this.get(name).call(this, arg1, arg2); + } - /** Call named method on {@code this} with 2 arguments, including metatag processing, - * and return only the first return value. + /** + * Call named method on {@code this} with 2 arguments, including metatag + * processing, and return only the first return value. *

- * Look up {@code this[name]} and if it is a {@link LuaFunction}, - * call it inserting {@code this} as an additional first argument, - * and return only its first return value, dropping any others. - * Otherwise, look for the {@link #CALL} metatag and call that. + * Look up {@code this[name]} and if it is a {@link LuaFunction}, call it + * inserting {@code this} as an additional first argument, and return only + * its first return value, dropping any others. Otherwise, look for the + * {@link #CALL} metatag and call that. *

- * If the return value is a {@link Varargs}, only the 1st value will be returned. - * To get multiple values, use {@link #invoke()} instead. + * If the return value is a {@link Varargs}, only the 1st value will be + * returned. To get multiple values, use {@link #invoke()} instead. *

- * To call {@code this} as a plain call, use {@link #call(LuaValue,LuaValue)} instead. + * To call {@code this} as a plain call, use + * {@link #call(LuaValue,LuaValue)} instead. * * @param name Name of the method to look up for invocation * @param arg1 First argument to supply to the method * @param arg2 Second argument to supply to the method - * @return All values returned from {@code this:name(arg1,arg2)} as a {@link Varargs} instance - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @return All values returned from {@code this:name(arg1,arg2)} as a + * {@link Varargs} instance + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call(LuaValue,LuaValue) * @see #invoke(LuaValue,Varargs) * @see #method(LuaValue,LuaValue) * @see #method(String,LuaValue,LuaValue) */ - public LuaValue method(LuaValue name, LuaValue arg1, LuaValue arg2) { return this.get(name).call(this,arg1,arg2); } - - /** Call {@code this} with 0 arguments, including metatag processing, - * and retain all return values in a {@link Varargs}. + public LuaValue method(LuaValue name, LuaValue arg1, LuaValue arg2) { + return this.get(name).call(this, arg1, arg2); + } + + /** + * Call {@code this} with 0 arguments, including metatag processing, and + * retain all return values in a {@link Varargs}. *

* If {@code this} is a {@link LuaFunction}, call it, and return all values. * Otherwise, look for the {@link #CALL} metatag and call that. *

* To get a particular return value, us {@link Varargs#arg(int)} *

- * To call {@code this} as a method call, use {@link #invokemethod(LuaValue)} instead. + * To call {@code this} as a method call, use + * {@link #invokemethod(LuaValue)} instead. * * @return All return values as a {@link Varargs} instance. - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call() * @see #invoke(Varargs) * @see #invokemethod(String) @@ -1690,7 +2005,8 @@ public class LuaValue extends Varargs { */ public Varargs invoke() { return invoke(NONE); } - /** Call {@code this} with variable arguments, including metatag processing, + /** + * Call {@code this} with variable arguments, including metatag processing, * and retain all return values in a {@link Varargs}. *

* If {@code this} is a {@link LuaFunction}, call it, and return all values. @@ -1698,13 +2014,15 @@ public class LuaValue extends Varargs { *

* To get a particular return value, us {@link Varargs#arg(int)} *

- * To call {@code this} as a method call, use {@link #invokemethod(LuaValue)} instead. + * To call {@code this} as a method call, use + * {@link #invokemethod(LuaValue)} instead. * - * @param args Varargs containing the arguments to supply to the called function + * @param args Varargs containing the arguments to supply to the called + * function * @return All return values as a {@link Varargs} instance. - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #varargsOf(LuaValue[]) * @see #call(LuaValue) * @see #invoke() @@ -1712,9 +2030,10 @@ public class LuaValue extends Varargs { * @see #invokemethod(String,Varargs) * @see #invokemethod(LuaValue,Varargs) */ - public Varargs invoke(Varargs args) { return callmt().invoke(this,args); } + public Varargs invoke(Varargs args) { return callmt().invoke(this, args); } - /** Call {@code this} with variable arguments, including metatag processing, + /** + * Call {@code this} with variable arguments, including metatag processing, * and retain all return values in a {@link Varargs}. *

* If {@code this} is a {@link LuaFunction}, call it, and return all values. @@ -1722,23 +2041,26 @@ public class LuaValue extends Varargs { *

* To get a particular return value, us {@link Varargs#arg(int)} *

- * To call {@code this} as a method call, use {@link #invokemethod(LuaValue,Varargs)} instead. + * To call {@code this} as a method call, use + * {@link #invokemethod(LuaValue,Varargs)} instead. * - * @param arg The first argument to supply to the called function - * @param varargs Varargs containing the remaining arguments to supply to the called function + * @param arg The first argument to supply to the called function + * @param varargs Varargs containing the remaining arguments to supply to + * the called function * @return All return values as a {@link Varargs} instance. - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #varargsOf(LuaValue[]) * @see #call(LuaValue,LuaValue) * @see #invoke(LuaValue,Varargs) * @see #invokemethod(String,Varargs) * @see #invokemethod(LuaValue,Varargs) */ - public Varargs invoke(LuaValue arg,Varargs varargs) { return invoke(varargsOf(arg,varargs)); } + public Varargs invoke(LuaValue arg, Varargs varargs) { return invoke(varargsOf(arg, varargs)); } - /** Call {@code this} with variable arguments, including metatag processing, + /** + * Call {@code this} with variable arguments, including metatag processing, * and retain all return values in a {@link Varargs}. *

* If {@code this} is a {@link LuaFunction}, call it, and return all values. @@ -1746,24 +2068,29 @@ public class LuaValue extends Varargs { *

* To get a particular return value, us {@link Varargs#arg(int)} *

- * To call {@code this} as a method call, use {@link #invokemethod(LuaValue,Varargs)} instead. + * To call {@code this} as a method call, use + * {@link #invokemethod(LuaValue,Varargs)} instead. * - * @param arg1 The first argument to supply to the called function - * @param arg2 The second argument to supply to the called function - * @param varargs Varargs containing the remaining arguments to supply to the called function + * @param arg1 The first argument to supply to the called function + * @param arg2 The second argument to supply to the called function + * @param varargs Varargs containing the remaining arguments to supply to + * the called function * @return All return values as a {@link Varargs} instance. - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #varargsOf(LuaValue[]) * @see #call(LuaValue,LuaValue,LuaValue) * @see #invoke(LuaValue,LuaValue,Varargs) * @see #invokemethod(String,Varargs) * @see #invokemethod(LuaValue,Varargs) */ - public Varargs invoke(LuaValue arg1,LuaValue arg2,Varargs varargs) { return invoke(varargsOf(arg1,arg2,varargs)); } + public Varargs invoke(LuaValue arg1, LuaValue arg2, Varargs varargs) { + return invoke(varargsOf(arg1, arg2, varargs)); + } - /** Call {@code this} with variable arguments, including metatag processing, + /** + * Call {@code this} with variable arguments, including metatag processing, * and retain all return values in a {@link Varargs}. *

* If {@code this} is a {@link LuaFunction}, call it, and return all values. @@ -1771,13 +2098,14 @@ public class LuaValue extends Varargs { *

* To get a particular return value, us {@link Varargs#arg(int)} *

- * To call {@code this} as a method call, use {@link #invokemethod(LuaValue,Varargs)} instead. + * To call {@code this} as a method call, use + * {@link #invokemethod(LuaValue,Varargs)} instead. * * @param args Array of arguments to supply to the called function * @return All return values as a {@link Varargs} instance. - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #varargsOf(LuaValue[]) * @see #call(LuaValue,LuaValue,LuaValue) * @see #invoke(LuaValue,LuaValue,Varargs) @@ -1786,7 +2114,8 @@ public class LuaValue extends Varargs { */ public Varargs invoke(LuaValue[] args) { return invoke(varargsOf(args)); } - /** Call {@code this} with variable arguments, including metatag processing, + /** + * Call {@code this} with variable arguments, including metatag processing, * and retain all return values in a {@link Varargs}. *

* If {@code this} is a {@link LuaFunction}, call it, and return all values. @@ -1794,14 +2123,16 @@ public class LuaValue extends Varargs { *

* To get a particular return value, us {@link Varargs#arg(int)} *

- * To call {@code this} as a method call, use {@link #invokemethod(LuaValue,Varargs)} instead. + * To call {@code this} as a method call, use + * {@link #invokemethod(LuaValue,Varargs)} instead. * - * @param args Array of arguments to supply to the called function - * @param varargs Varargs containing additional arguments to supply to the called function + * @param args Array of arguments to supply to the called function + * @param varargs Varargs containing additional arguments to supply to the + * called function * @return All return values as a {@link Varargs} instance. - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #varargsOf(LuaValue[]) * @see #call(LuaValue,LuaValue,LuaValue) * @see #invoke(LuaValue,LuaValue,Varargs) @@ -1810,25 +2141,27 @@ public class LuaValue extends Varargs { * @see #invokemethod(String,Varargs) * @see #invokemethod(LuaValue,Varargs) */ - public Varargs invoke(LuaValue[] args,Varargs varargs) { return invoke(varargsOf(args,varargs)); } - - /** Call named method on {@code this} with 0 arguments, including metatag processing, - * and retain all return values in a {@link Varargs}. + public Varargs invoke(LuaValue[] args, Varargs varargs) { return invoke(varargsOf(args, varargs)); } + + /** + * Call named method on {@code this} with 0 arguments, including metatag + * processing, and retain all return values in a {@link Varargs}. *

- * Look up {@code this[name]} and if it is a {@link LuaFunction}, - * call it inserting {@code this} as an additional first argument, - * and return all return values as a {@link Varargs} instance. - * Otherwise, look for the {@link #CALL} metatag and call that. + * Look up {@code this[name]} and if it is a {@link LuaFunction}, call it + * inserting {@code this} as an additional first argument, and return all + * return values as a {@link Varargs} instance. Otherwise, look for the + * {@link #CALL} metatag and call that. *

* To get a particular return value, us {@link Varargs#arg(int)} *

* To call {@code this} as a plain call, use {@link #invoke()} instead. * * @param name Name of the method to look up for invocation - * @return All values returned from {@code this:name()} as a {@link Varargs} instance - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @return All values returned from {@code this:name()} as a {@link Varargs} + * instance + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call() * @see #invoke() * @see #method(String) @@ -1839,24 +2172,26 @@ public class LuaValue extends Varargs { * @see #invokemethod(LuaValue, Varargs) */ public Varargs invokemethod(String name) { return get(name).invoke(this); } - - /** Call named method on {@code this} with 0 arguments, including metatag processing, - * and retain all return values in a {@link Varargs}. + + /** + * Call named method on {@code this} with 0 arguments, including metatag + * processing, and retain all return values in a {@link Varargs}. *

- * Look up {@code this[name]} and if it is a {@link LuaFunction}, - * call it inserting {@code this} as an additional first argument, - * and return all return values as a {@link Varargs} instance. - * Otherwise, look for the {@link #CALL} metatag and call that. + * Look up {@code this[name]} and if it is a {@link LuaFunction}, call it + * inserting {@code this} as an additional first argument, and return all + * return values as a {@link Varargs} instance. Otherwise, look for the + * {@link #CALL} metatag and call that. *

* To get a particular return value, us {@link Varargs#arg(int)} *

* To call {@code this} as a plain call, use {@link #invoke()} instead. * * @param name Name of the method to look up for invocation - * @return All values returned from {@code this:name()} as a {@link Varargs} instance - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @return All values returned from {@code this:name()} as a {@link Varargs} + * instance + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call() * @see #invoke() * @see #method(LuaValue) @@ -1867,25 +2202,29 @@ public class LuaValue extends Varargs { * @see #invokemethod(LuaValue, Varargs) */ public Varargs invokemethod(LuaValue name) { return get(name).invoke(this); } - - /** Call named method on {@code this} with 1 argument, including metatag processing, - * and retain all return values in a {@link Varargs}. + + /** + * Call named method on {@code this} with 1 argument, including metatag + * processing, and retain all return values in a {@link Varargs}. *

- * Look up {@code this[name]} and if it is a {@link LuaFunction}, - * call it inserting {@code this} as an additional first argument, - * and return all return values as a {@link Varargs} instance. - * Otherwise, look for the {@link #CALL} metatag and call that. + * Look up {@code this[name]} and if it is a {@link LuaFunction}, call it + * inserting {@code this} as an additional first argument, and return all + * return values as a {@link Varargs} instance. Otherwise, look for the + * {@link #CALL} metatag and call that. *

* To get a particular return value, us {@link Varargs#arg(int)} *

- * To call {@code this} as a plain call, use {@link #invoke(Varargs)} instead. + * To call {@code this} as a plain call, use {@link #invoke(Varargs)} + * instead. * * @param name Name of the method to look up for invocation - * @param args {@link Varargs} containing arguments to supply to the called function after {@code this} - * @return All values returned from {@code this:name(args)} as a {@link Varargs} instance - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @param args {@link Varargs} containing arguments to supply to the called + * function after {@code this} + * @return All values returned from {@code this:name(args)} as a + * {@link Varargs} instance + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call() * @see #invoke(Varargs) * @see #method(String) @@ -1895,26 +2234,30 @@ public class LuaValue extends Varargs { * @see #invokemethod(LuaValue, LuaValue[]) * @see #invokemethod(LuaValue, Varargs) */ - public Varargs invokemethod(String name, Varargs args) { return get(name).invoke(varargsOf(this,args)); } - - /** Call named method on {@code this} with variable arguments, including metatag processing, - * and retain all return values in a {@link Varargs}. + public Varargs invokemethod(String name, Varargs args) { return get(name).invoke(varargsOf(this, args)); } + + /** + * Call named method on {@code this} with variable arguments, including + * metatag processing, and retain all return values in a {@link Varargs}. *

- * Look up {@code this[name]} and if it is a {@link LuaFunction}, - * call it inserting {@code this} as an additional first argument, - * and return all return values as a {@link Varargs} instance. - * Otherwise, look for the {@link #CALL} metatag and call that. + * Look up {@code this[name]} and if it is a {@link LuaFunction}, call it + * inserting {@code this} as an additional first argument, and return all + * return values as a {@link Varargs} instance. Otherwise, look for the + * {@link #CALL} metatag and call that. *

* To get a particular return value, us {@link Varargs#arg(int)} *

- * To call {@code this} as a plain call, use {@link #invoke(Varargs)} instead. + * To call {@code this} as a plain call, use {@link #invoke(Varargs)} + * instead. * * @param name Name of the method to look up for invocation - * @param args {@link Varargs} containing arguments to supply to the called function after {@code this} - * @return All values returned from {@code this:name(args)} as a {@link Varargs} instance - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @param args {@link Varargs} containing arguments to supply to the called + * function after {@code this} + * @return All values returned from {@code this:name(args)} as a + * {@link Varargs} instance + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call() * @see #invoke(Varargs) * @see #method(String) @@ -1924,26 +2267,30 @@ public class LuaValue extends Varargs { * @see #invokemethod(String, Varargs) * @see #invokemethod(LuaValue, LuaValue[]) */ - public Varargs invokemethod(LuaValue name, Varargs args) { return get(name).invoke(varargsOf(this,args)); } - - /** Call named method on {@code this} with 1 argument, including metatag processing, - * and retain all return values in a {@link Varargs}. + public Varargs invokemethod(LuaValue name, Varargs args) { return get(name).invoke(varargsOf(this, args)); } + + /** + * Call named method on {@code this} with 1 argument, including metatag + * processing, and retain all return values in a {@link Varargs}. *

- * Look up {@code this[name]} and if it is a {@link LuaFunction}, - * call it inserting {@code this} as an additional first argument, - * and return all return values as a {@link Varargs} instance. - * Otherwise, look for the {@link #CALL} metatag and call that. + * Look up {@code this[name]} and if it is a {@link LuaFunction}, call it + * inserting {@code this} as an additional first argument, and return all + * return values as a {@link Varargs} instance. Otherwise, look for the + * {@link #CALL} metatag and call that. *

* To get a particular return value, us {@link Varargs#arg(int)} *

- * To call {@code this} as a plain call, use {@link #invoke(Varargs)} instead. + * To call {@code this} as a plain call, use {@link #invoke(Varargs)} + * instead. * * @param name Name of the method to look up for invocation - * @param args Array of {@link LuaValue} containing arguments to supply to the called function after {@code this} - * @return All values returned from {@code this:name(args)} as a {@link Varargs} instance - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @param args Array of {@link LuaValue} containing arguments to supply to + * the called function after {@code this} + * @return All values returned from {@code this:name(args)} as a + * {@link Varargs} instance + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call() * @see #invoke(Varargs) * @see #method(String) @@ -1954,26 +2301,32 @@ public class LuaValue extends Varargs { * @see #invokemethod(LuaValue, Varargs) * @see LuaValue#varargsOf(LuaValue[]) */ - public Varargs invokemethod(String name, LuaValue[] args) { return get(name).invoke(varargsOf(this,varargsOf(args))); } - - /** Call named method on {@code this} with variable arguments, including metatag processing, - * and retain all return values in a {@link Varargs}. + public Varargs invokemethod(String name, LuaValue[] args) { + return get(name).invoke(varargsOf(this, varargsOf(args))); + } + + /** + * Call named method on {@code this} with variable arguments, including + * metatag processing, and retain all return values in a {@link Varargs}. *

- * Look up {@code this[name]} and if it is a {@link LuaFunction}, - * call it inserting {@code this} as an additional first argument, - * and return all return values as a {@link Varargs} instance. - * Otherwise, look for the {@link #CALL} metatag and call that. + * Look up {@code this[name]} and if it is a {@link LuaFunction}, call it + * inserting {@code this} as an additional first argument, and return all + * return values as a {@link Varargs} instance. Otherwise, look for the + * {@link #CALL} metatag and call that. *

* To get a particular return value, us {@link Varargs#arg(int)} *

- * To call {@code this} as a plain call, use {@link #invoke(Varargs)} instead. + * To call {@code this} as a plain call, use {@link #invoke(Varargs)} + * instead. * * @param name Name of the method to look up for invocation - * @param args Array of {@link LuaValue} containing arguments to supply to the called function after {@code this} - * @return All values returned from {@code this:name(args)} as a {@link Varargs} instance - * @throws LuaError if not a function and {@link #CALL} is not defined, - * or the invoked function throws a {@link LuaError} - * or the invoked closure throw a lua {@code error} + * @param args Array of {@link LuaValue} containing arguments to supply to + * the called function after {@code this} + * @return All values returned from {@code this:name(args)} as a + * {@link Varargs} instance + * @throws LuaError if not a function and {@link #CALL} is not defined, or + * the invoked function throws a {@link LuaError} or the + * invoked closure throw a lua {@code error} * @see #call() * @see #invoke(Varargs) * @see #method(String) @@ -1984,112 +2337,143 @@ public class LuaValue extends Varargs { * @see #invokemethod(LuaValue, Varargs) * @see LuaValue#varargsOf(LuaValue[]) */ - public Varargs invokemethod(LuaValue name, LuaValue[] args) { return get(name).invoke(varargsOf(this,varargsOf(args))); } - + public Varargs invokemethod(LuaValue name, LuaValue[] args) { + return get(name).invoke(varargsOf(this, varargsOf(args))); + } + /** * Get the metatag value for the {@link #CALL} metatag, if it exists. + * * @return {@link LuaValue} value if metatag is defined * @throws LuaError if {@link #CALL} metatag is not defined. */ protected LuaValue callmt() { return checkmetatag(CALL, "attempt to call "); } - - /** Unary not: return inverse boolean value {@code (~this)} as defined by lua not operator - * @return {@link #TRUE} if {@link #NIL} or {@link #FALSE}, otherwise {@link #FALSE} - */ - public LuaValue not() { return FALSE; } - - /** Unary minus: return negative value {@code (-this)} as defined by lua unary minus operator - * @return boolean inverse as {@link LuaBoolean} if boolean or nil, - * numeric inverse as {@link LuaNumber} if numeric, - * or metatag processing result if {@link #UNM} metatag is defined - * @throws LuaError if {@code this} is not a table or string, and has no {@link #UNM} metatag - */ - public LuaValue neg() { return checkmetatag(UNM, "attempt to perform arithmetic on ").call(this); } - - /** Length operator: return lua length of object {@code (#this)} including metatag processing as java int - * @return length as defined by the lua # operator - * or metatag processing result - * @throws LuaError if {@code this} is not a table or string, and has no {@link #LEN} metatag - */ - public LuaValue len() { return checkmetatag(LEN, "attempt to get length of ").call(this); } - /** Length operator: return lua length of object {@code (#this)} including metatag processing as java int - * @return length as defined by the lua # operator - * or metatag processing result converted to java int using {@link #toint()} - * @throws LuaError if {@code this} is not a table or string, and has no {@link #LEN} metatag + /** + * Unary not: return inverse boolean value {@code (~this)} as defined by lua + * not operator + * + * @return {@link #TRUE} if {@link #NIL} or {@link #FALSE}, otherwise + * {@link #FALSE} */ - public int length() { return len().toint(); } - - /** Get raw length of table or string without metatag processing. + public LuaValue not() { return FALSE; } + + /** + * Unary minus: return negative value {@code (-this)} as defined by lua + * unary minus operator + * + * @return boolean inverse as {@link LuaBoolean} if boolean or nil, numeric + * inverse as {@link LuaNumber} if numeric, or metatag processing + * result if {@link #UNM} metatag is defined + * @throws LuaError if {@code this} is not a table or string, and has no + * {@link #UNM} metatag + */ + public LuaValue neg() { return checkmetatag(UNM, "attempt to perform arithmetic on ").call(this); } + + /** + * Length operator: return lua length of object {@code (#this)} including + * metatag processing as java int + * + * @return length as defined by the lua # operator or metatag processing + * result + * @throws LuaError if {@code this} is not a table or string, and has no + * {@link #LEN} metatag + */ + public LuaValue len() { return checkmetatag(LEN, "attempt to get length of ").call(this); } + + /** + * Length operator: return lua length of object {@code (#this)} including + * metatag processing as java int + * + * @return length as defined by the lua # operator or metatag processing + * result converted to java int using {@link #toint()} + * @throws LuaError if {@code this} is not a table or string, and has no + * {@link #LEN} metatag + */ + public int length() { return len().toint(); } + + /** + * Get raw length of table or string without metatag processing. + * * @return the length of the table or string. * @throws LuaError if {@code this} is not a table or string. */ public int rawlen() { typerror("table or string"); return 0; } - + // object equality, used for key comparison - public boolean equals(Object obj) { return this == obj; } - - /** Equals: Perform equality comparison with another value - * including metatag processing using {@link #EQ}. + public boolean equals(Object obj) { return this == obj; } + + /** + * Equals: Perform equality comparison with another value including metatag + * processing using {@link #EQ}. + * * @param val The value to compare with. - * @return {@link #TRUE} if values are comparable and {@code (this == rhs)}, - * {@link #FALSE} if comparable but not equal, - * {@link LuaValue} if metatag processing occurs. + * @return {@link #TRUE} if values are comparable and {@code (this == rhs)}, + * {@link #FALSE} if comparable but not equal, {@link LuaValue} if + * metatag processing occurs. * @see #eq_b(LuaValue) * @see #raweq(LuaValue) * @see #neq(LuaValue) * @see #eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue) * @see #EQ */ - public LuaValue eq( LuaValue val ) { return eq_b(val)? TRUE: FALSE; } - - /** Equals: Perform equality comparison with another value - * including metatag processing using {@link #EQ}, - * and return java boolean + public LuaValue eq(LuaValue val) { return eq_b(val)? TRUE: FALSE; } + + /** + * Equals: Perform equality comparison with another value including metatag + * processing using {@link #EQ}, and return java boolean + * * @param val The value to compare with. - * @return true if values are comparable and {@code (this == rhs)}, - * false if comparable but not equal, - * result converted to java boolean if metatag processing occurs. + * @return true if values are comparable and {@code (this == rhs)}, false if + * comparable but not equal, result converted to java boolean if + * metatag processing occurs. * @see #eq(LuaValue) * @see #raweq(LuaValue) * @see #neq_b(LuaValue) * @see #eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue) * @see #EQ */ - public boolean eq_b( LuaValue val ) { return this == val; } + public boolean eq_b(LuaValue val) { return this == val; } - /** Notquals: Perform inequality comparison with another value - * including metatag processing using {@link #EQ}. + /** + * Notquals: Perform inequality comparison with another value including + * metatag processing using {@link #EQ}. + * * @param val The value to compare with. - * @return {@link #TRUE} if values are comparable and {@code (this != rhs)}, - * {@link #FALSE} if comparable but equal, - * inverse of {@link LuaValue} converted to {@link LuaBoolean} if metatag processing occurs. + * @return {@link #TRUE} if values are comparable and {@code (this != rhs)}, + * {@link #FALSE} if comparable but equal, inverse of + * {@link LuaValue} converted to {@link LuaBoolean} if metatag + * processing occurs. * @see #eq(LuaValue) * @see #raweq(LuaValue) * @see #eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue) * @see #EQ */ - public LuaValue neq( LuaValue val ) { return eq_b(val)? FALSE: TRUE; } + public LuaValue neq(LuaValue val) { return eq_b(val)? FALSE: TRUE; } - /** Notquals: Perform inequality comparison with another value - * including metatag processing using {@link #EQ}. + /** + * Notquals: Perform inequality comparison with another value including + * metatag processing using {@link #EQ}. + * * @param val The value to compare with. - * @return true if values are comparable and {@code (this != rhs)}, - * false if comparable but equal, - * inverse of result converted to boolean if metatag processing occurs. + * @return true if values are comparable and {@code (this != rhs)}, false if + * comparable but equal, inverse of result converted to boolean if + * metatag processing occurs. * @see #eq_b(LuaValue) * @see #raweq(LuaValue) * @see #eqmtcall(LuaValue, LuaValue, LuaValue, LuaValue) * @see #EQ */ - public boolean neq_b( LuaValue val ) { return !eq_b(val); } + public boolean neq_b(LuaValue val) { return !eq_b(val); } - /** Equals: Perform direct equality comparison with another value - * without metatag processing. + /** + * Equals: Perform direct equality comparison with another value without + * metatag processing. + * * @param val The value to compare with. - * @return true if {@code (this == rhs)}, false otherwise + * @return true if {@code (this == rhs)}, false otherwise * @see #eq(LuaValue) * @see #raweq(LuaUserdata) * @see #raweq(LuaString) @@ -2097,53 +2481,60 @@ public class LuaValue extends Varargs { * @see #raweq(int) * @see #EQ */ - public boolean raweq( LuaValue val ) { return this == val; } - - /** Equals: Perform direct equality comparison with a {@link LuaUserdata} value - * without metatag processing. + public boolean raweq(LuaValue val) { return this == val; } + + /** + * Equals: Perform direct equality comparison with a {@link LuaUserdata} + * value without metatag processing. + * * @param val The {@link LuaUserdata} to compare with. - * @return true if {@code this} is userdata - * and their metatables are the same using == - * and their instances are equal using {@link #equals(Object)}, - * otherwise false + * @return true if {@code this} is userdata and their metatables are the + * same using == and their instances are equal using + * {@link #equals(Object)}, otherwise false * @see #eq(LuaValue) * @see #raweq(LuaValue) */ - public boolean raweq( LuaUserdata val ) { return false; } + public boolean raweq(LuaUserdata val) { return false; } - /** Equals: Perform direct equality comparison with a {@link LuaString} value + /** + * Equals: Perform direct equality comparison with a {@link LuaString} value * without metatag processing. + * * @param val The {@link LuaString} to compare with. - * @return true if {@code this} is a {@link LuaString} - * and their byte sequences match, - * otherwise false + * @return true if {@code this} is a {@link LuaString} and their byte + * sequences match, otherwise false */ - public boolean raweq( LuaString val ) { return false; } + public boolean raweq(LuaString val) { return false; } - /** Equals: Perform direct equality comparison with a double value - * without metatag processing. + /** + * Equals: Perform direct equality comparison with a double value without + * metatag processing. + * * @param val The double value to compare with. - * @return true if {@code this} is a {@link LuaNumber} - * whose value equals val, - * otherwise false + * @return true if {@code this} is a {@link LuaNumber} whose value equals + * val, otherwise false */ - public boolean raweq( double val ) { return false; } + public boolean raweq(double val) { return false; } - /** Equals: Perform direct equality comparison with a int value - * without metatag processing. + /** + * Equals: Perform direct equality comparison with a int value without + * metatag processing. + * * @param val The double value to compare with. - * @return true if {@code this} is a {@link LuaNumber} - * whose value equals val, - * otherwise false + * @return true if {@code this} is a {@link LuaNumber} whose value equals + * val, otherwise false */ - public boolean raweq( int val ) { return false; } + public boolean raweq(int val) { return false; } - /** Perform equality testing metatag processing - * @param lhs left-hand-side of equality expression + /** + * Perform equality testing metatag processing + * + * @param lhs left-hand-side of equality expression * @param lhsmt metatag value for left-hand-side - * @param rhs right-hand-side of equality expression + * @param rhs right-hand-side of equality expression * @param rhsmt metatag value for right-hand-side - * @return true if metatag processing result is not {@link #NIL} or {@link #FALSE} + * @return true if metatag processing result is not {@link #NIL} or + * {@link #FALSE} * @throws LuaError if metatag was not defined for either operand * @see #equals(Object) * @see #eq(LuaValue) @@ -2152,363 +2543,408 @@ public class LuaValue extends Varargs { */ public static final boolean eqmtcall(LuaValue lhs, LuaValue lhsmt, LuaValue rhs, LuaValue rhsmt) { LuaValue h = lhsmt.rawget(EQ); - return h.isnil() || h!=rhsmt.rawget(EQ)? false: h.call(lhs,rhs).toboolean(); + return h.isnil() || h != rhsmt.rawget(EQ)? false: h.call(lhs, rhs).toboolean(); } - - /** Add: Perform numeric add operation with another value - * including metatag processing. + + /** + * Add: Perform numeric add operation with another value including metatag + * processing. *

- * Each operand must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * Each operand must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param rhs The right-hand-side value to perform the add with - * @return value of {@code (this + rhs)} if both are numeric, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if either operand is not a number or string convertible to number, - * and neither has the {@link #ADD} metatag defined + * @return value of {@code (this + rhs)} if both are numeric, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if either operand is not a number or string convertible + * to number, and neither has the {@link #ADD} metatag + * defined * @see #arithmt(LuaValue, LuaValue) */ - public LuaValue add( LuaValue rhs ) { return arithmt(ADD,rhs); } - - /** Add: Perform numeric add operation with another value - * of double type with metatag processing + public LuaValue add(LuaValue rhs) { return arithmt(ADD, rhs); } + + /** + * Add: Perform numeric add operation with another value of double type with + * metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param rhs The right-hand-side value to perform the add with - * @return value of {@code (this + rhs)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (this + rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #add(LuaValue) */ - public LuaValue add(double rhs) { return arithmtwith(ADD,rhs); } - - /** Add: Perform numeric add operation with another value - * of int type with metatag processing + public LuaValue add(double rhs) { return arithmtwith(ADD, rhs); } + + /** + * Add: Perform numeric add operation with another value of int type with + * metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param rhs The right-hand-side value to perform the add with - * @return value of {@code (this + rhs)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (this + rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #add(LuaValue) */ - public LuaValue add(int rhs) { return add((double)rhs); } - - /** Subtract: Perform numeric subtract operation with another value - * of unknown type, - * including metatag processing. + public LuaValue add(int rhs) { return add((double) rhs); } + + /** + * Subtract: Perform numeric subtract operation with another value of + * unknown type, including metatag processing. *

- * Each operand must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * Each operand must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param rhs The right-hand-side value to perform the subtract with - * @return value of {@code (this - rhs)} if both are numeric, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if either operand is not a number or string convertible to number, - * and neither has the {@link #SUB} metatag defined + * @return value of {@code (this - rhs)} if both are numeric, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if either operand is not a number or string convertible + * to number, and neither has the {@link #SUB} metatag + * defined * @see #arithmt(LuaValue, LuaValue) */ - public LuaValue sub( LuaValue rhs ) { return arithmt(SUB,rhs); } - - /** Subtract: Perform numeric subtract operation with another value - * of double type with metatag processing + public LuaValue sub(LuaValue rhs) { return arithmt(SUB, rhs); } + + /** + * Subtract: Perform numeric subtract operation with another value of double + * type with metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param rhs The right-hand-side value to perform the subtract with - * @return value of {@code (this - rhs)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (this - rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #sub(LuaValue) */ - public LuaValue sub( double rhs ) { return aritherror("sub"); } - - /** Subtract: Perform numeric subtract operation with another value - * of int type with metatag processing + public LuaValue sub(double rhs) { return aritherror("sub"); } + + /** + * Subtract: Perform numeric subtract operation with another value of int + * type with metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param rhs The right-hand-side value to perform the subtract with - * @return value of {@code (this - rhs)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (this - rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #sub(LuaValue) */ - public LuaValue sub( int rhs ) { return aritherror("sub"); } - - /** Reverse-subtract: Perform numeric subtract operation from an int value + public LuaValue sub(int rhs) { return aritherror("sub"); } + + /** + * Reverse-subtract: Perform numeric subtract operation from an int value * with metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param lhs The left-hand-side value from which to perform the subtraction - * @return value of {@code (lhs - this)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (lhs - this)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #sub(LuaValue) * @see #sub(double) * @see #sub(int) */ - public LuaValue subFrom(double lhs) { return arithmtwith(SUB,lhs); } - - /** Reverse-subtract: Perform numeric subtract operation from a double value + public LuaValue subFrom(double lhs) { return arithmtwith(SUB, lhs); } + + /** + * Reverse-subtract: Perform numeric subtract operation from a double value * without metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number *

* For metatag processing {@link #sub(LuaValue)} must be used * * @param lhs The left-hand-side value from which to perform the subtraction - * @return value of {@code (lhs - this)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (lhs - this)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #sub(LuaValue) * @see #sub(double) * @see #sub(int) */ - public LuaValue subFrom(int lhs) { return subFrom((double)lhs); } - - /** Multiply: Perform numeric multiply operation with another value - * of unknown type, - * including metatag processing. + public LuaValue subFrom(int lhs) { return subFrom((double) lhs); } + + /** + * Multiply: Perform numeric multiply operation with another value of + * unknown type, including metatag processing. *

- * Each operand must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * Each operand must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param rhs The right-hand-side value to perform the multiply with - * @return value of {@code (this * rhs)} if both are numeric, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if either operand is not a number or string convertible to number, - * and neither has the {@link #MUL} metatag defined + * @return value of {@code (this * rhs)} if both are numeric, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if either operand is not a number or string convertible + * to number, and neither has the {@link #MUL} metatag + * defined * @see #arithmt(LuaValue, LuaValue) */ - public LuaValue mul( LuaValue rhs ) { return arithmt(MUL,rhs); } - - /** Multiply: Perform numeric multiply operation with another value - * of double type with metatag processing + public LuaValue mul(LuaValue rhs) { return arithmt(MUL, rhs); } + + /** + * Multiply: Perform numeric multiply operation with another value of double + * type with metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param rhs The right-hand-side value to perform the multiply with - * @return value of {@code (this * rhs)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (this * rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #mul(LuaValue) */ - public LuaValue mul(double rhs) { return arithmtwith(MUL,rhs); } - - /** Multiply: Perform numeric multiply operation with another value - * of int type with metatag processing + public LuaValue mul(double rhs) { return arithmtwith(MUL, rhs); } + + /** + * Multiply: Perform numeric multiply operation with another value of int + * type with metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param rhs The right-hand-side value to perform the multiply with - * @return value of {@code (this * rhs)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (this * rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #mul(LuaValue) */ - public LuaValue mul(int rhs) { return mul((double)rhs); } - - /** Raise to power: Raise this value to a power - * including metatag processing. + public LuaValue mul(int rhs) { return mul((double) rhs); } + + /** + * Raise to power: Raise this value to a power including metatag processing. *

- * Each operand must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * Each operand must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param rhs The power to raise this value to - * @return value of {@code (this ^ rhs)} if both are numeric, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if either operand is not a number or string convertible to number, - * and neither has the {@link #POW} metatag defined + * @return value of {@code (this ^ rhs)} if both are numeric, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if either operand is not a number or string convertible + * to number, and neither has the {@link #POW} metatag + * defined * @see #arithmt(LuaValue, LuaValue) */ - public LuaValue pow( LuaValue rhs ) { return arithmt(POW,rhs); } - - /** Raise to power: Raise this value to a power - * of double type with metatag processing + public LuaValue pow(LuaValue rhs) { return arithmt(POW, rhs); } + + /** + * Raise to power: Raise this value to a power of double type with metatag + * processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param rhs The power to raise this value to - * @return value of {@code (this ^ rhs)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (this ^ rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #pow(LuaValue) */ - public LuaValue pow( double rhs ) { return aritherror("pow"); } - - /** Raise to power: Raise this value to a power - * of int type with metatag processing + public LuaValue pow(double rhs) { return aritherror("pow"); } + + /** + * Raise to power: Raise this value to a power of int type with metatag + * processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param rhs The power to raise this value to - * @return value of {@code (this ^ rhs)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (this ^ rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #pow(LuaValue) */ - public LuaValue pow( int rhs ) { return aritherror("pow"); } - - /** Reverse-raise to power: Raise another value of double type to this power + public LuaValue pow(int rhs) { return aritherror("pow"); } + + /** + * Reverse-raise to power: Raise another value of double type to this power * with metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param lhs The left-hand-side value which will be raised to this power - * @return value of {@code (lhs ^ this)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (lhs ^ this)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #pow(LuaValue) * @see #pow(double) * @see #pow(int) */ - public LuaValue powWith(double lhs) { return arithmtwith(POW,lhs); } - - /** Reverse-raise to power: Raise another value of double type to this power + public LuaValue powWith(double lhs) { return arithmtwith(POW, lhs); } + + /** + * Reverse-raise to power: Raise another value of double type to this power * with metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param lhs The left-hand-side value which will be raised to this power - * @return value of {@code (lhs ^ this)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (lhs ^ this)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #pow(LuaValue) * @see #pow(double) * @see #pow(int) */ - public LuaValue powWith(int lhs) { return powWith((double)lhs); } - - /** Divide: Perform numeric divide operation by another value - * of unknown type, - * including metatag processing. + public LuaValue powWith(int lhs) { return powWith((double) lhs); } + + /** + * Divide: Perform numeric divide operation by another value of unknown + * type, including metatag processing. *

- * Each operand must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * Each operand must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param rhs The right-hand-side value to perform the divulo with - * @return value of {@code (this / rhs)} if both are numeric, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if either operand is not a number or string convertible to number, - * and neither has the {@link #DIV} metatag defined + * @return value of {@code (this / rhs)} if both are numeric, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if either operand is not a number or string convertible + * to number, and neither has the {@link #DIV} metatag + * defined * @see #arithmt(LuaValue, LuaValue) */ - public LuaValue div( LuaValue rhs ) { return arithmt(DIV,rhs); } - - /** Divide: Perform numeric divide operation by another value - * of double type without metatag processing + public LuaValue div(LuaValue rhs) { return arithmt(DIV, rhs); } + + /** + * Divide: Perform numeric divide operation by another value of double type + * without metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number *

* For metatag processing {@link #div(LuaValue)} must be used * * @param rhs The right-hand-side value to perform the divulo with - * @return value of {@code (this / rhs)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (this / rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #div(LuaValue) */ - public LuaValue div( double rhs ) { return aritherror("div"); } - - /** Divide: Perform numeric divide operation by another value - * of int type without metatag processing + public LuaValue div(double rhs) { return aritherror("div"); } + + /** + * Divide: Perform numeric divide operation by another value of int type + * without metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number *

* For metatag processing {@link #div(LuaValue)} must be used * * @param rhs The right-hand-side value to perform the divulo with - * @return value of {@code (this / rhs)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (this / rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #div(LuaValue) */ - public LuaValue div( int rhs ) { return aritherror("div"); } - - /** Reverse-divide: Perform numeric divide operation into another value - * with metatag processing + public LuaValue div(int rhs) { return aritherror("div"); } + + /** + * Reverse-divide: Perform numeric divide operation into another value with + * metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param lhs The left-hand-side value which will be divided by this - * @return value of {@code (lhs / this)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (lhs / this)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #div(LuaValue) * @see #div(double) * @see #div(int) */ - public LuaValue divInto(double lhs) { return arithmtwith(DIV,lhs); } - - /** Modulo: Perform numeric modulo operation with another value - * of unknown type, - * including metatag processing. + public LuaValue divInto(double lhs) { return arithmtwith(DIV, lhs); } + + /** + * Modulo: Perform numeric modulo operation with another value of unknown + * type, including metatag processing. *

- * Each operand must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * Each operand must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param rhs The right-hand-side value to perform the modulo with - * @return value of {@code (this % rhs)} if both are numeric, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if either operand is not a number or string convertible to number, - * and neither has the {@link #MOD} metatag defined + * @return value of {@code (this % rhs)} if both are numeric, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if either operand is not a number or string convertible + * to number, and neither has the {@link #MOD} metatag + * defined * @see #arithmt(LuaValue, LuaValue) */ - public LuaValue mod( LuaValue rhs ) { return arithmt(MOD,rhs); } - - /** Modulo: Perform numeric modulo operation with another value - * of double type without metatag processing + public LuaValue mod(LuaValue rhs) { return arithmt(MOD, rhs); } + + /** + * Modulo: Perform numeric modulo operation with another value of double + * type without metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number *

* For metatag processing {@link #mod(LuaValue)} must be used * * @param rhs The right-hand-side value to perform the modulo with - * @return value of {@code (this % rhs)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (this % rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #mod(LuaValue) */ - public LuaValue mod( double rhs ) { return aritherror("mod"); } - - /** Modulo: Perform numeric modulo operation with another value - * of int type without metatag processing + public LuaValue mod(double rhs) { return aritherror("mod"); } + + /** + * Modulo: Perform numeric modulo operation with another value of int type + * without metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number *

* For metatag processing {@link #mod(LuaValue)} must be used * * @param rhs The right-hand-side value to perform the modulo with - * @return value of {@code (this % rhs)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (this % rhs)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #mod(LuaValue) */ - public LuaValue mod( int rhs ) { return aritherror("mod"); } - - /** Reverse-modulo: Perform numeric modulo operation from another value - * with metatag processing + public LuaValue mod(int rhs) { return aritherror("mod"); } + + /** + * Reverse-modulo: Perform numeric modulo operation from another value with + * metatag processing *

- * {@code this} must derive from {@link LuaNumber} - * or derive from {@link LuaString} and be convertible to a number + * {@code this} must derive from {@link LuaNumber} or derive from + * {@link LuaString} and be convertible to a number * * @param lhs The left-hand-side value which will be modulo'ed by this - * @return value of {@code (lhs % this)} if this is numeric - * @throws LuaError if {@code this} is not a number or string convertible to number + * @return value of {@code (lhs % this)} if this is numeric + * @throws LuaError if {@code this} is not a number or string convertible to + * number * @see #mod(LuaValue) * @see #mod(double) * @see #mod(int) */ - public LuaValue modFrom(double lhs) { return arithmtwith(MOD,lhs); } - - /** Perform metatag processing for arithmetic operations. + public LuaValue modFrom(double lhs) { return arithmtwith(MOD, lhs); } + + /** + * Perform metatag processing for arithmetic operations. *

- * Finds the supplied metatag value for {@code this} or {@code op2} and invokes it, - * or throws {@link LuaError} if neither is defined. + * Finds the supplied metatag value for {@code this} or {@code op2} and + * invokes it, or throws {@link LuaError} if neither is defined. + * * @param tag The metatag to look up * @param op2 The other operand value to perform the operation with * @return {@link LuaValue} resulting from metatag processing @@ -2528,18 +2964,21 @@ public class LuaValue extends Varargs { */ protected LuaValue arithmt(LuaValue tag, LuaValue op2) { LuaValue h = this.metatag(tag); - if ( h.isnil() ) { + if (h.isnil()) { h = op2.metatag(tag); - if ( h.isnil() ) - error( "attempt to perform arithmetic "+tag+" on "+typename()+" and "+op2.typename() ); + if (h.isnil()) + error("attempt to perform arithmetic " + tag + " on " + typename() + " and " + op2.typename()); } - return h.call( this, op2 ); + return h.call(this, op2); } - - /** Perform metatag processing for arithmetic operations when the left-hand-side is a number. + + /** + * Perform metatag processing for arithmetic operations when the + * left-hand-side is a number. *

- * Finds the supplied metatag value for {@code this} and invokes it, - * or throws {@link LuaError} if neither is defined. + * Finds the supplied metatag value for {@code this} and invokes it, or + * throws {@link LuaError} if neither is defined. + * * @param tag The metatag to look up * @param op1 The value of the left-hand-side to perform the operation with * @return {@link LuaValue} resulting from metatag processing @@ -2559,734 +2998,827 @@ public class LuaValue extends Varargs { */ protected LuaValue arithmtwith(LuaValue tag, double op1) { LuaValue h = metatag(tag); - if ( h.isnil() ) - error( "attempt to perform arithmetic "+tag+" on number and "+typename() ); - return h.call( LuaValue.valueOf(op1), this ); + if (h.isnil()) + error("attempt to perform arithmetic " + tag + " on number and " + typename()); + return h.call(LuaValue.valueOf(op1), this); } - - /** Less than: Perform numeric or string comparison with another value - * of unknown type, - * including metatag processing, and returning {@link LuaValue}. + + /** + * Less than: Perform numeric or string comparison with another value of + * unknown type, including metatag processing, and returning + * {@link LuaValue}. *

- * To be comparable, both operands must derive from {@link LuaString} - * or both must derive from {@link LuaNumber}. + * To be comparable, both operands must derive from {@link LuaString} or + * both must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return {@link #TRUE} if {@code (this < rhs)}, {@link #FALSE} if not, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if either both operands are not a strings or both are not numbers - * and no {@link #LT} metatag is defined. + * @return {@link #TRUE} if {@code (this < rhs)}, {@link #FALSE} if not, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if either both operands are not a strings or both are + * not numbers and no {@link #LT} metatag is defined. * @see #gteq_b(LuaValue) * @see #comparemt(LuaValue, LuaValue) */ - public LuaValue lt( LuaValue rhs ) { return comparemt(LT,rhs); } + public LuaValue lt(LuaValue rhs) { return comparemt(LT, rhs); } - /** Less than: Perform numeric comparison with another value - * of double type, + /** + * Less than: Perform numeric comparison with another value of double type, * including metatag processing, and returning {@link LuaValue}. *

* To be comparable, this must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return {@link #TRUE} if {@code (this < rhs)}, {@link #FALSE} if not, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if this is not a number - * and no {@link #LT} metatag is defined. + * @return {@link #TRUE} if {@code (this < rhs)}, {@link #FALSE} if not, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number and no {@link #LT} metatag is + * defined. * @see #gteq_b(double) * @see #comparemt(LuaValue, LuaValue) */ - public LuaValue lt( double rhs ) { return compareerror("number"); } + public LuaValue lt(double rhs) { return compareerror("number"); } - /** Less than: Perform numeric comparison with another value - * of int type, + /** + * Less than: Perform numeric comparison with another value of int type, * including metatag processing, and returning {@link LuaValue}. *

* To be comparable, this must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return {@link #TRUE} if {@code (this < rhs)}, {@link #FALSE} if not, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if this is not a number - * and no {@link #LT} metatag is defined. + * @return {@link #TRUE} if {@code (this < rhs)}, {@link #FALSE} if not, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number and no {@link #LT} metatag is + * defined. * @see #gteq_b(int) * @see #comparemt(LuaValue, LuaValue) */ - public LuaValue lt( int rhs ) { return compareerror("number"); } + public LuaValue lt(int rhs) { return compareerror("number"); } - /** Less than: Perform numeric or string comparison with another value - * of unknown type, including metatag processing, - * and returning java boolean. + /** + * Less than: Perform numeric or string comparison with another value of + * unknown type, including metatag processing, and returning java boolean. *

- * To be comparable, both operands must derive from {@link LuaString} - * or both must derive from {@link LuaNumber}. + * To be comparable, both operands must derive from {@link LuaString} or + * both must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return true if {@code (this < rhs)}, false if not, - * and boolean interpreation of result if metatag processing occurs. - * @throws LuaError if either both operands are not a strings or both are not numbers - * and no {@link #LT} metatag is defined. + * @return true if {@code (this < rhs)}, false if not, and boolean + * interpreation of result if metatag processing occurs. + * @throws LuaError if either both operands are not a strings or both are + * not numbers and no {@link #LT} metatag is defined. * @see #gteq(LuaValue) * @see #comparemt(LuaValue, LuaValue) */ - public boolean lt_b( LuaValue rhs ) { return comparemt(LT,rhs).toboolean(); } + public boolean lt_b(LuaValue rhs) { return comparemt(LT, rhs).toboolean(); } - /** Less than: Perform numeric comparison with another value - * of int type, - * including metatag processing, - * and returning java boolean. + /** + * Less than: Perform numeric comparison with another value of int type, + * including metatag processing, and returning java boolean. *

* To be comparable, this must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return true if {@code (this < rhs)}, false if not, - * and boolean interpreation of result if metatag processing occurs. - * @throws LuaError if this is not a number - * and no {@link #LT} metatag is defined. + * @return true if {@code (this < rhs)}, false if not, and boolean + * interpreation of result if metatag processing occurs. + * @throws LuaError if this is not a number and no {@link #LT} metatag is + * defined. * @see #gteq(int) * @see #comparemt(LuaValue, LuaValue) */ - public boolean lt_b( int rhs ) { compareerror("number"); return false; } + public boolean lt_b(int rhs) { compareerror("number"); return false; } - /** Less than: Perform numeric or string comparison with another value - * of unknown type, including metatag processing, - * and returning java boolean. + /** + * Less than: Perform numeric or string comparison with another value of + * unknown type, including metatag processing, and returning java boolean. *

- * To be comparable, both operands must derive from {@link LuaString} - * or both must derive from {@link LuaNumber}. + * To be comparable, both operands must derive from {@link LuaString} or + * both must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return true if {@code (this < rhs)}, false if not, - * and boolean interpreation of result if metatag processing occurs. - * @throws LuaError if either both operands are not a strings or both are not numbers - * and no {@link #LT} metatag is defined. + * @return true if {@code (this < rhs)}, false if not, and boolean + * interpreation of result if metatag processing occurs. + * @throws LuaError if either both operands are not a strings or both are + * not numbers and no {@link #LT} metatag is defined. * @see #gteq(LuaValue) * @see #comparemt(LuaValue, LuaValue) */ - public boolean lt_b( double rhs ) { compareerror("number"); return false; } + public boolean lt_b(double rhs) { compareerror("number"); return false; } - /** Less than or equals: Perform numeric or string comparison with another value - * of unknown type, - * including metatag processing, and returning {@link LuaValue}. + /** + * Less than or equals: Perform numeric or string comparison with another + * value of unknown type, including metatag processing, and returning + * {@link LuaValue}. *

- * To be comparable, both operands must derive from {@link LuaString} - * or both must derive from {@link LuaNumber}. + * To be comparable, both operands must derive from {@link LuaString} or + * both must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return {@link #TRUE} if {@code (this <= rhs)}, {@link #FALSE} if not, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if either both operands are not a strings or both are not numbers - * and no {@link #LE} metatag is defined. + * @return {@link #TRUE} if {@code (this <= rhs)}, {@link #FALSE} if not, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if either both operands are not a strings or both are + * not numbers and no {@link #LE} metatag is defined. * @see #gteq_b(LuaValue) * @see #comparemt(LuaValue, LuaValue) */ - public LuaValue lteq( LuaValue rhs ) { return comparemt(LE,rhs); } + public LuaValue lteq(LuaValue rhs) { return comparemt(LE, rhs); } - /** Less than or equals: Perform numeric comparison with another value - * of double type, - * including metatag processing, and returning {@link LuaValue}. + /** + * Less than or equals: Perform numeric comparison with another value of + * double type, including metatag processing, and returning + * {@link LuaValue}. *

* To be comparable, this must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return {@link #TRUE} if {@code (this <= rhs)}, {@link #FALSE} if not, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if this is not a number - * and no {@link #LE} metatag is defined. + * @return {@link #TRUE} if {@code (this <= rhs)}, {@link #FALSE} if not, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number and no {@link #LE} metatag is + * defined. * @see #gteq_b(double) * @see #comparemt(LuaValue, LuaValue) */ - public LuaValue lteq( double rhs ) { return compareerror("number"); } + public LuaValue lteq(double rhs) { return compareerror("number"); } - /** Less than or equals: Perform numeric comparison with another value - * of int type, - * including metatag processing, and returning {@link LuaValue}. + /** + * Less than or equals: Perform numeric comparison with another value of int + * type, including metatag processing, and returning {@link LuaValue}. *

* To be comparable, this must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return {@link #TRUE} if {@code (this <= rhs)}, {@link #FALSE} if not, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if this is not a number - * and no {@link #LE} metatag is defined. + * @return {@link #TRUE} if {@code (this <= rhs)}, {@link #FALSE} if not, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number and no {@link #LE} metatag is + * defined. * @see #gteq_b(int) * @see #comparemt(LuaValue, LuaValue) */ - public LuaValue lteq( int rhs ) { return compareerror("number"); } + public LuaValue lteq(int rhs) { return compareerror("number"); } - /** Less than or equals: Perform numeric or string comparison with another value - * of unknown type, including metatag processing, - * and returning java boolean. + /** + * Less than or equals: Perform numeric or string comparison with another + * value of unknown type, including metatag processing, and returning java + * boolean. *

- * To be comparable, both operands must derive from {@link LuaString} - * or both must derive from {@link LuaNumber}. + * To be comparable, both operands must derive from {@link LuaString} or + * both must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return true if {@code (this <= rhs)}, false if not, - * and boolean interpreation of result if metatag processing occurs. - * @throws LuaError if either both operands are not a strings or both are not numbers - * and no {@link #LE} metatag is defined. + * @return true if {@code (this <= rhs)}, false if not, and boolean + * interpreation of result if metatag processing occurs. + * @throws LuaError if either both operands are not a strings or both are + * not numbers and no {@link #LE} metatag is defined. * @see #gteq(LuaValue) * @see #comparemt(LuaValue, LuaValue) */ - public boolean lteq_b( LuaValue rhs ) { return comparemt(LE,rhs).toboolean(); } + public boolean lteq_b(LuaValue rhs) { return comparemt(LE, rhs).toboolean(); } - /** Less than or equals: Perform numeric comparison with another value - * of int type, - * including metatag processing, - * and returning java boolean. + /** + * Less than or equals: Perform numeric comparison with another value of int + * type, including metatag processing, and returning java boolean. *

* To be comparable, this must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return true if {@code (this <= rhs)}, false if not, - * and boolean interpreation of result if metatag processing occurs. - * @throws LuaError if this is not a number - * and no {@link #LE} metatag is defined. + * @return true if {@code (this <= rhs)}, false if not, and boolean + * interpreation of result if metatag processing occurs. + * @throws LuaError if this is not a number and no {@link #LE} metatag is + * defined. * @see #gteq(int) * @see #comparemt(LuaValue, LuaValue) */ - public boolean lteq_b( int rhs ) { compareerror("number"); return false; } + public boolean lteq_b(int rhs) { compareerror("number"); return false; } - /** Less than or equals: Perform numeric comparison with another value - * of double type, - * including metatag processing, - * and returning java boolean. + /** + * Less than or equals: Perform numeric comparison with another value of + * double type, including metatag processing, and returning java boolean. *

* To be comparable, this must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return true if {@code (this <= rhs)}, false if not, - * and boolean interpreation of result if metatag processing occurs. - * @throws LuaError if this is not a number - * and no {@link #LE} metatag is defined. + * @return true if {@code (this <= rhs)}, false if not, and boolean + * interpreation of result if metatag processing occurs. + * @throws LuaError if this is not a number and no {@link #LE} metatag is + * defined. * @see #gteq(double) * @see #comparemt(LuaValue, LuaValue) */ - public boolean lteq_b( double rhs ) { compareerror("number"); return false; } + public boolean lteq_b(double rhs) { compareerror("number"); return false; } - /** Greater than: Perform numeric or string comparison with another value - * of unknown type, - * including metatag processing, and returning {@link LuaValue}. + /** + * Greater than: Perform numeric or string comparison with another value of + * unknown type, including metatag processing, and returning + * {@link LuaValue}. *

- * To be comparable, both operands must derive from {@link LuaString} - * or both must derive from {@link LuaNumber}. + * To be comparable, both operands must derive from {@link LuaString} or + * both must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return {@link #TRUE} if {@code (this > rhs)}, {@link #FALSE} if not, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if either both operands are not a strings or both are not numbers - * and no {@link #LE} metatag is defined. + * @return {@link #TRUE} if {@code (this > rhs)}, {@link #FALSE} if not, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if either both operands are not a strings or both are + * not numbers and no {@link #LE} metatag is defined. * @see #gteq_b(LuaValue) * @see #comparemt(LuaValue, LuaValue) */ - public LuaValue gt( LuaValue rhs ) { return rhs.comparemt(LE,this); } + public LuaValue gt(LuaValue rhs) { return rhs.comparemt(LE, this); } - /** Greater than: Perform numeric comparison with another value - * of double type, - * including metatag processing, and returning {@link LuaValue}. + /** + * Greater than: Perform numeric comparison with another value of double + * type, including metatag processing, and returning {@link LuaValue}. *

* To be comparable, this must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return {@link #TRUE} if {@code (this > rhs)}, {@link #FALSE} if not, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if this is not a number - * and no {@link #LE} metatag is defined. + * @return {@link #TRUE} if {@code (this > rhs)}, {@link #FALSE} if not, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number and no {@link #LE} metatag is + * defined. * @see #gteq_b(double) * @see #comparemt(LuaValue, LuaValue) */ - public LuaValue gt( double rhs ) { return compareerror("number"); } + public LuaValue gt(double rhs) { return compareerror("number"); } - /** Greater than: Perform numeric comparison with another value - * of int type, + /** + * Greater than: Perform numeric comparison with another value of int type, * including metatag processing, and returning {@link LuaValue}. *

* To be comparable, this must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return {@link #TRUE} if {@code (this > rhs)}, {@link #FALSE} if not, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if this is not a number - * and no {@link #LE} metatag is defined. + * @return {@link #TRUE} if {@code (this > rhs)}, {@link #FALSE} if not, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number and no {@link #LE} metatag is + * defined. * @see #gteq_b(int) * @see #comparemt(LuaValue, LuaValue) */ - public LuaValue gt( int rhs ) { return compareerror("number"); } + public LuaValue gt(int rhs) { return compareerror("number"); } - /** Greater than: Perform numeric or string comparison with another value - * of unknown type, including metatag processing, - * and returning java boolean. + /** + * Greater than: Perform numeric or string comparison with another value of + * unknown type, including metatag processing, and returning java boolean. *

- * To be comparable, both operands must derive from {@link LuaString} - * or both must derive from {@link LuaNumber}. + * To be comparable, both operands must derive from {@link LuaString} or + * both must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return true if {@code (this > rhs)}, false if not, - * and boolean interpreation of result if metatag processing occurs. - * @throws LuaError if either both operands are not a strings or both are not numbers - * and no {@link #LE} metatag is defined. + * @return true if {@code (this > rhs)}, false if not, and boolean + * interpreation of result if metatag processing occurs. + * @throws LuaError if either both operands are not a strings or both are + * not numbers and no {@link #LE} metatag is defined. * @see #gteq(LuaValue) * @see #comparemt(LuaValue, LuaValue) */ - public boolean gt_b( LuaValue rhs ) { return rhs.comparemt(LE,this).toboolean(); } + public boolean gt_b(LuaValue rhs) { return rhs.comparemt(LE, this).toboolean(); } - /** Greater than: Perform numeric comparison with another value - * of int type, - * including metatag processing, - * and returning java boolean. + /** + * Greater than: Perform numeric comparison with another value of int type, + * including metatag processing, and returning java boolean. *

* To be comparable, this must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return true if {@code (this > rhs)}, false if not, - * and boolean interpreation of result if metatag processing occurs. - * @throws LuaError if this is not a number - * and no {@link #LE} metatag is defined. + * @return true if {@code (this > rhs)}, false if not, and boolean + * interpreation of result if metatag processing occurs. + * @throws LuaError if this is not a number and no {@link #LE} metatag is + * defined. * @see #gteq(int) * @see #comparemt(LuaValue, LuaValue) */ - public boolean gt_b( int rhs ) { compareerror("number"); return false; } + public boolean gt_b(int rhs) { compareerror("number"); return false; } - /** Greater than: Perform numeric or string comparison with another value - * of unknown type, including metatag processing, - * and returning java boolean. + /** + * Greater than: Perform numeric or string comparison with another value of + * unknown type, including metatag processing, and returning java boolean. *

- * To be comparable, both operands must derive from {@link LuaString} - * or both must derive from {@link LuaNumber}. + * To be comparable, both operands must derive from {@link LuaString} or + * both must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return true if {@code (this > rhs)}, false if not, - * and boolean interpreation of result if metatag processing occurs. - * @throws LuaError if either both operands are not a strings or both are not numbers - * and no {@link #LE} metatag is defined. + * @return true if {@code (this > rhs)}, false if not, and boolean + * interpreation of result if metatag processing occurs. + * @throws LuaError if either both operands are not a strings or both are + * not numbers and no {@link #LE} metatag is defined. * @see #gteq(LuaValue) * @see #comparemt(LuaValue, LuaValue) */ - public boolean gt_b( double rhs ) { compareerror("number"); return false; } + public boolean gt_b(double rhs) { compareerror("number"); return false; } - /** Greater than or equals: Perform numeric or string comparison with another value - * of unknown type, - * including metatag processing, and returning {@link LuaValue}. + /** + * Greater than or equals: Perform numeric or string comparison with another + * value of unknown type, including metatag processing, and returning + * {@link LuaValue}. *

- * To be comparable, both operands must derive from {@link LuaString} - * or both must derive from {@link LuaNumber}. + * To be comparable, both operands must derive from {@link LuaString} or + * both must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return {@link #TRUE} if {@code (this >= rhs)}, {@link #FALSE} if not, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if either both operands are not a strings or both are not numbers - * and no {@link #LT} metatag is defined. + * @return {@link #TRUE} if {@code (this >= rhs)}, {@link #FALSE} if not, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if either both operands are not a strings or both are + * not numbers and no {@link #LT} metatag is defined. * @see #gteq_b(LuaValue) * @see #comparemt(LuaValue, LuaValue) */ - public LuaValue gteq( LuaValue rhs ) { return rhs.comparemt(LT,this); } + public LuaValue gteq(LuaValue rhs) { return rhs.comparemt(LT, this); } - /** Greater than or equals: Perform numeric comparison with another value - * of double type, - * including metatag processing, and returning {@link LuaValue}. + /** + * Greater than or equals: Perform numeric comparison with another value of + * double type, including metatag processing, and returning + * {@link LuaValue}. *

* To be comparable, this must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return {@link #TRUE} if {@code (this >= rhs)}, {@link #FALSE} if not, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if this is not a number - * and no {@link #LT} metatag is defined. + * @return {@link #TRUE} if {@code (this >= rhs)}, {@link #FALSE} if not, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number and no {@link #LT} metatag is + * defined. * @see #gteq_b(double) * @see #comparemt(LuaValue, LuaValue) */ - public LuaValue gteq( double rhs ) { return compareerror("number"); } + public LuaValue gteq(double rhs) { return compareerror("number"); } - /** Greater than or equals: Perform numeric comparison with another value - * of int type, - * including metatag processing, and returning {@link LuaValue}. + /** + * Greater than or equals: Perform numeric comparison with another value of + * int type, including metatag processing, and returning {@link LuaValue}. *

* To be comparable, this must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return {@link #TRUE} if {@code (this >= rhs)}, {@link #FALSE} if not, - * or {@link LuaValue} if metatag processing occurs - * @throws LuaError if this is not a number - * and no {@link #LT} metatag is defined. + * @return {@link #TRUE} if {@code (this >= rhs)}, {@link #FALSE} if not, or + * {@link LuaValue} if metatag processing occurs + * @throws LuaError if this is not a number and no {@link #LT} metatag is + * defined. * @see #gteq_b(int) * @see #comparemt(LuaValue, LuaValue) */ - public LuaValue gteq( int rhs ) { return valueOf(todouble() >= rhs); } + public LuaValue gteq(int rhs) { return valueOf(todouble() >= rhs); } - /** Greater than or equals: Perform numeric or string comparison with another value - * of unknown type, including metatag processing, - * and returning java boolean. + /** + * Greater than or equals: Perform numeric or string comparison with another + * value of unknown type, including metatag processing, and returning java + * boolean. *

- * To be comparable, both operands must derive from {@link LuaString} - * or both must derive from {@link LuaNumber}. + * To be comparable, both operands must derive from {@link LuaString} or + * both must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return true if {@code (this >= rhs)}, false if not, - * and boolean interpreation of result if metatag processing occurs. - * @throws LuaError if either both operands are not a strings or both are not numbers - * and no {@link #LT} metatag is defined. + * @return true if {@code (this >= rhs)}, false if not, and boolean + * interpreation of result if metatag processing occurs. + * @throws LuaError if either both operands are not a strings or both are + * not numbers and no {@link #LT} metatag is defined. * @see #gteq(LuaValue) * @see #comparemt(LuaValue, LuaValue) */ - public boolean gteq_b( LuaValue rhs ) { return rhs.comparemt(LT,this).toboolean(); } + public boolean gteq_b(LuaValue rhs) { return rhs.comparemt(LT, this).toboolean(); } - /** Greater than or equals: Perform numeric comparison with another value - * of int type, - * including metatag processing, - * and returning java boolean. + /** + * Greater than or equals: Perform numeric comparison with another value of + * int type, including metatag processing, and returning java boolean. *

* To be comparable, this must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return true if {@code (this >= rhs)}, false if not, - * and boolean interpreation of result if metatag processing occurs. - * @throws LuaError if this is not a number - * and no {@link #LT} metatag is defined. + * @return true if {@code (this >= rhs)}, false if not, and boolean + * interpreation of result if metatag processing occurs. + * @throws LuaError if this is not a number and no {@link #LT} metatag is + * defined. * @see #gteq(int) * @see #comparemt(LuaValue, LuaValue) */ - public boolean gteq_b( int rhs ) { compareerror("number"); return false; } + public boolean gteq_b(int rhs) { compareerror("number"); return false; } - /** Greater than or equals: Perform numeric comparison with another value - * of double type, - * including metatag processing, - * and returning java boolean. + /** + * Greater than or equals: Perform numeric comparison with another value of + * double type, including metatag processing, and returning java boolean. *

* To be comparable, this must derive from {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the comparison with - * @return true if {@code (this >= rhs)}, false if not, - * and boolean interpreation of result if metatag processing occurs. - * @throws LuaError if this is not a number - * and no {@link #LT} metatag is defined. + * @return true if {@code (this >= rhs)}, false if not, and boolean + * interpreation of result if metatag processing occurs. + * @throws LuaError if this is not a number and no {@link #LT} metatag is + * defined. * @see #gteq(double) * @see #comparemt(LuaValue, LuaValue) */ - public boolean gteq_b( double rhs ) { compareerror("number"); return false; } - - /** Perform metatag processing for comparison operations. + public boolean gteq_b(double rhs) { compareerror("number"); return false; } + + /** + * Perform metatag processing for comparison operations. *

- * Finds the supplied metatag value and invokes it, - * or throws {@link LuaError} if none applies. + * Finds the supplied metatag value and invokes it, or throws + * {@link LuaError} if none applies. + * * @param tag The metatag to look up * @param op1 The operand with which to to perform the operation * @return {@link LuaValue} resulting from metatag processing - * @throws LuaError if metatag was not defined for either operand, - * or if the operands are not the same type, - * or the metatag values for the two operands are different. + * @throws LuaError if metatag was not defined for either operand, or if the + * operands are not the same type, or the metatag values + * for the two operands are different. * @see #gt(LuaValue) * @see #gteq(LuaValue) * @see #lt(LuaValue) * @see #lteq(LuaValue) */ - public LuaValue comparemt( LuaValue tag, LuaValue op1 ) { + public LuaValue comparemt(LuaValue tag, LuaValue op1) { LuaValue h; if (!(h = metatag(tag)).isnil() || !(h = op1.metatag(tag)).isnil()) 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("attempt to compare " + tag + " on " + typename() + " and " + op1.typename()); } - - /** Perform string comparison with another value - * of any type - * using string comparison based on byte values. + + /** + * Perform string comparison with another value of any type using string + * comparison based on byte values. *

- * Only strings can be compared, meaning - * each operand must derive from {@link LuaString}. + * Only strings can be compared, meaning each operand must derive from + * {@link LuaString}. * * @param rhs The right-hand-side value to perform the comparison with - * @return int < 0 for {@code (this < rhs)}, int > 0 for {@code (this > rhs)}, or 0 when same string. + * @return int < 0 for {@code (this < rhs)}, int > 0 for + * {@code (this > rhs)}, or 0 when same string. * @throws LuaError if either operand is not a string */ - public int strcmp( LuaValue rhs ) { error("attempt to compare "+typename()); return 0; } + public int strcmp(LuaValue rhs) { error("attempt to compare " + typename()); return 0; } - /** Perform string comparison with another value - * known to be a {@link LuaString} - * using string comparison based on byte values. + /** + * Perform string comparison with another value known to be a + * {@link LuaString} using string comparison based on byte values. *

- * Only strings can be compared, meaning - * each operand must derive from {@link LuaString}. + * Only strings can be compared, meaning each operand must derive from + * {@link LuaString}. * * @param rhs The right-hand-side value to perform the comparison with - * @return int < 0 for {@code (this < rhs)}, int > 0 for {@code (this > rhs)}, or 0 when same string. + * @return int < 0 for {@code (this < rhs)}, int > 0 for + * {@code (this > rhs)}, or 0 when same string. * @throws LuaError if this is not a string */ - public int strcmp( LuaString rhs ) { error("attempt to compare "+typename()); return 0; } + public int strcmp(LuaString rhs) { error("attempt to compare " + typename()); return 0; } - /** Concatenate another value onto this value and return the result - * using rules of lua string concatenation including metatag processing. + /** + * Concatenate another value onto this value and return the result using + * rules of lua string concatenation including metatag processing. *

- * Only strings and numbers as represented can be concatenated, meaning - * each operand must derive from {@link LuaString} or {@link LuaNumber}. + * Only strings and numbers as represented can be concatenated, meaning each + * operand must derive from {@link LuaString} or {@link LuaNumber}. * * @param rhs The right-hand-side value to perform the operation with - * @return {@link LuaValue} resulting from concatenation of {@code (this .. rhs)} - * @throws LuaError if either operand is not of an appropriate type, - * such as nil or a table + * @return {@link LuaValue} resulting from concatenation of + * {@code (this .. rhs)} + * @throws LuaError if either operand is not of an appropriate type, such as + * nil or a table */ - public LuaValue concat(LuaValue rhs) { return this.concatmt(rhs); } + public LuaValue concat(LuaValue rhs) { return this.concatmt(rhs); } - /** Reverse-concatenation: concatenate this value onto another value - * whose type is unknwon - * and return the result using rules of lua string concatenation including - * metatag processing. + /** + * Reverse-concatenation: concatenate this value onto another value whose + * type is unknwon and return the result using rules of lua string + * concatenation including metatag processing. *

- * Only strings and numbers as represented can be concatenated, meaning - * each operand must derive from {@link LuaString} or {@link LuaNumber}. + * Only strings and numbers as represented can be concatenated, meaning each + * operand must derive from {@link LuaString} or {@link LuaNumber}. * * @param lhs The left-hand-side value onto which this will be concatenated - * @return {@link LuaValue} resulting from concatenation of {@code (lhs .. this)} - * @throws LuaError if either operand is not of an appropriate type, - * such as nil or a table + * @return {@link LuaValue} resulting from concatenation of + * {@code (lhs .. this)} + * @throws LuaError if either operand is not of an appropriate type, such as + * nil or a table * @see #concat(LuaValue) */ - public LuaValue concatTo(LuaValue lhs) { return lhs.concatmt(this); } + public LuaValue concatTo(LuaValue lhs) { return lhs.concatmt(this); } - /** Reverse-concatenation: concatenate this value onto another value - * known to be a {@link LuaNumber} - * and return the result using rules of lua string concatenation including - * metatag processing. + /** + * Reverse-concatenation: concatenate this value onto another value known to + * be a {@link LuaNumber} and return the result using rules of lua string + * concatenation including metatag processing. *

- * Only strings and numbers as represented can be concatenated, meaning - * each operand must derive from {@link LuaString} or {@link LuaNumber}. + * Only strings and numbers as represented can be concatenated, meaning each + * operand must derive from {@link LuaString} or {@link LuaNumber}. * * @param lhs The left-hand-side value onto which this will be concatenated - * @return {@link LuaValue} resulting from concatenation of {@code (lhs .. this)} - * @throws LuaError if either operand is not of an appropriate type, - * such as nil or a table + * @return {@link LuaValue} resulting from concatenation of + * {@code (lhs .. this)} + * @throws LuaError if either operand is not of an appropriate type, such as + * nil or a table * @see #concat(LuaValue) */ - public LuaValue concatTo(LuaNumber lhs) { return lhs.concatmt(this); } - - /** Reverse-concatenation: concatenate this value onto another value - * known to be a {@link LuaString} - * and return the result using rules of lua string concatenation including - * metatag processing. + public LuaValue concatTo(LuaNumber lhs) { return lhs.concatmt(this); } + + /** + * Reverse-concatenation: concatenate this value onto another value known to + * be a {@link LuaString} and return the result using rules of lua string + * concatenation including metatag processing. *

- * Only strings and numbers as represented can be concatenated, meaning - * each operand must derive from {@link LuaString} or {@link LuaNumber}. + * Only strings and numbers as represented can be concatenated, meaning each + * operand must derive from {@link LuaString} or {@link LuaNumber}. * * @param lhs The left-hand-side value onto which this will be concatenated - * @return {@link LuaValue} resulting from concatenation of {@code (lhs .. this)} - * @throws LuaError if either operand is not of an appropriate type, - * such as nil or a table + * @return {@link LuaValue} resulting from concatenation of + * {@code (lhs .. this)} + * @throws LuaError if either operand is not of an appropriate type, such as + * nil or a table * @see #concat(LuaValue) */ - public LuaValue concatTo(LuaString lhs) { return lhs.concatmt(this); } + public LuaValue concatTo(LuaString lhs) { return lhs.concatmt(this); } - /** Convert the value to a {@link Buffer} for more efficient concatenation of + /** + * Convert the value to a {@link Buffer} for more efficient concatenation of * multiple strings. + * * @return Buffer instance containing the string or number */ - public Buffer buffer() { return new Buffer(this); } - - /** Concatenate a {@link Buffer} onto this value and return the result - * using rules of lua string concatenation including metatag processing. + public Buffer buffer() { return new Buffer(this); } + + /** + * Concatenate a {@link Buffer} onto this value and return the result using + * rules of lua string concatenation including metatag processing. *

- * Only strings and numbers as represented can be concatenated, meaning - * each operand must derive from {@link LuaString} or {@link LuaNumber}. + * Only strings and numbers as represented can be concatenated, meaning each + * operand must derive from {@link LuaString} or {@link LuaNumber}. * - * @param rhs The right-hand-side {@link Buffer} to perform the operation with + * @param rhs The right-hand-side {@link Buffer} to perform the operation + * with * @return LuaString resulting from concatenation of {@code (this .. rhs)} - * @throws LuaError if either operand is not of an appropriate type, - * such as nil or a table + * @throws LuaError if either operand is not of an appropriate type, such as + * nil or a table */ - public Buffer concat(Buffer rhs) { return rhs.concatTo(this); } - - /** Perform metatag processing for concatenation operations. + public Buffer concat(Buffer rhs) { return rhs.concatTo(this); } + + /** + * Perform metatag processing for concatenation operations. *

- * Finds the {@link #CONCAT} metatag value and invokes it, - * or throws {@link LuaError} if it doesn't exist. + * Finds the {@link #CONCAT} metatag value and invokes it, or throws + * {@link LuaError} if it doesn't exist. + * * @param rhs The right-hand-side value to perform the operation with - * @return {@link LuaValue} resulting from metatag processing for {@link #CONCAT} metatag. + * @return {@link LuaValue} resulting from metatag processing for + * {@link #CONCAT} metatag. * @throws LuaError if metatag was not defined for either operand */ public LuaValue concatmt(LuaValue rhs) { - LuaValue h=metatag(CONCAT); - if ( h.isnil() && (h=rhs.metatag(CONCAT)).isnil()) - error("attempt to concatenate "+typename()+" and "+rhs.typename()); - return h.call(this,rhs); + LuaValue h = metatag(CONCAT); + if (h.isnil() && (h = rhs.metatag(CONCAT)).isnil()) + error("attempt to concatenate " + typename() + " and " + rhs.typename()); + return h.call(this, rhs); } - - /** Perform boolean {@code and} with another operand, based on lua rules for boolean evaluation. - * This returns either {@code this} or {@code rhs} depending on the boolean value for {@code this}. + + /** + * Perform boolean {@code and} with another operand, based on lua rules for + * boolean evaluation. This returns either {@code this} or {@code rhs} + * depending on the boolean value for {@code this}. * * @param rhs The right-hand-side value to perform the operation with - * @return {@code this} if {@code this.toboolean()} is false, {@code rhs} otherwise. + * @return {@code this} if {@code this.toboolean()} is false, {@code rhs} + * otherwise. */ - public LuaValue and( LuaValue rhs ) { return this.toboolean()? rhs: this; } - - /** Perform boolean {@code or} with another operand, based on lua rules for boolean evaluation. - * This returns either {@code this} or {@code rhs} depending on the boolean value for {@code this}. + public LuaValue and(LuaValue rhs) { return this.toboolean()? rhs: this; } + + /** + * Perform boolean {@code or} with another operand, based on lua rules for + * boolean evaluation. This returns either {@code this} or {@code rhs} + * depending on the boolean value for {@code this}. * * @param rhs The right-hand-side value to perform the operation with - * @return {@code this} if {@code this.toboolean()} is true, {@code rhs} otherwise. + * @return {@code this} if {@code this.toboolean()} is true, {@code rhs} + * otherwise. */ - public LuaValue or( LuaValue rhs ) { return this.toboolean()? this: rhs; } - - /** Perform end-condition test in for-loop processing. + public LuaValue or(LuaValue rhs) { return this.toboolean()? this: rhs; } + + /** + * Perform end-condition test in for-loop processing. *

* Used in lua-bytecode to Java-bytecode conversion. * * @param limit the numerical limit to complete the for loop - * @param step the numberical step size to use. + * @param step the numberical step size to use. * @return true if limit has not been reached, false otherwise. */ public boolean testfor_b(LuaValue limit, LuaValue step) { return step.gt_b(0)? lteq_b(limit): gteq_b(limit); } - + /** - * Convert this value to a string if it is a {@link LuaString} or {@link LuaNumber}, - * or throw a {@link LuaError} if it is not - * @return {@link LuaString} corresponding to the value if a string or number + * Convert this value to a string if it is a {@link LuaString} or + * {@link LuaNumber}, or throw a {@link LuaError} if it is not + * + * @return {@link LuaString} corresponding to the value if a string or + * number * @throws LuaError if not a string or number */ - public LuaString strvalue() { typerror("string or number"); return null; } + public LuaString strvalue() { typerror("string or number"); return null; } - /** Return this value as a strong reference, or null if it was weak and is no longer referenced. - * @return {@link LuaValue} referred to, or null if it was weak and is no longer referenced. + /** + * Return this value as a strong reference, or null if it was weak and is no + * longer referenced. + * + * @return {@link LuaValue} referred to, or null if it was weak and is no + * longer referenced. * @see WeakTable */ - public LuaValue strongvalue() { return this; } + public LuaValue strongvalue() { return this; } - /** Convert java boolean to a {@link LuaValue}. + /** + * Convert java boolean to a {@link LuaValue}. * * @param b boolean value to convert - * @return {@link #TRUE} if not or {@link #FALSE} if false + * @return {@link #TRUE} if not or {@link #FALSE} if false */ - public static LuaBoolean valueOf(boolean b) { return b? LuaValue.TRUE: FALSE; }; + public static LuaBoolean valueOf(boolean b) { return b? LuaValue.TRUE: FALSE; }; - /** Convert java int to a {@link LuaValue}. + /** + * Convert java int to a {@link LuaValue}. * * @param i int value to convert * @return {@link LuaInteger} instance, possibly pooled, whose value is i */ - public static LuaInteger valueOf(int i) { return LuaInteger.valueOf(i); } - - /** Convert java double to a {@link LuaValue}. - * This may return a {@link LuaInteger} or {@link LuaDouble} depending - * on the value supplied. + public static LuaInteger valueOf(int i) { return LuaInteger.valueOf(i); } + + /** + * Convert java double to a {@link LuaValue}. This may return a + * {@link LuaInteger} or {@link LuaDouble} depending on the value supplied. * * @param d double value to convert * @return {@link LuaNumber} instance, possibly pooled, whose value is d */ - public static LuaNumber valueOf(double d) { return LuaDouble.valueOf(d); }; - - /** Convert java string to a {@link LuaValue}. + public static LuaNumber valueOf(double d) { return LuaDouble.valueOf(d); }; + + /** + * Convert java string to a {@link LuaValue}. * * @param s String value to convert * @return {@link LuaString} instance, possibly pooled, whose value is s */ - public static LuaString valueOf(String s) { return LuaString.valueOf(s); } + public static LuaString valueOf(String s) { return LuaString.valueOf(s); } - /** Convert bytes in an array to a {@link LuaValue}. + /** + * Convert bytes in an array to a {@link LuaValue}. * * @param bytes byte array to convert - * @return {@link LuaString} instance, possibly pooled, whose bytes are those in the supplied array + * @return {@link LuaString} instance, possibly pooled, whose bytes are + * those in the supplied array */ public static LuaString valueOf(byte[] bytes) { return LuaString.valueOf(bytes); } - - /** Convert bytes in an array to a {@link LuaValue}. + + /** + * Convert bytes in an array to a {@link LuaValue}. * * @param bytes byte array to convert - * @param off offset into the byte array, starting at 0 - * @param len number of bytes to include in the {@link LuaString} - * @return {@link LuaString} instance, possibly pooled, whose bytes are those in the supplied array + * @param off offset into the byte array, starting at 0 + * @param len number of bytes to include in the {@link LuaString} + * @return {@link LuaString} instance, possibly pooled, whose bytes are + * those in the supplied array */ public static LuaString valueOf(byte[] bytes, int off, int len) { - return LuaString.valueOf(bytes,off,len); + return LuaString.valueOf(bytes, off, len); } - - /** Construct an empty {@link LuaTable}. + + /** + * Construct an empty {@link LuaTable}. + * * @return new {@link LuaTable} instance with no values and no metatable. */ public static LuaTable tableOf() { return new LuaTable(); } - /** Construct a {@link LuaTable} initialized with supplied array values. - * @param varargs {@link Varargs} containing the values to use in initialization - * @param firstarg the index of the first argument to use from the varargs, 1 being the first. - * @return new {@link LuaTable} instance with sequential elements coming from the varargs. + /** + * Construct a {@link LuaTable} initialized with supplied array values. + * + * @param varargs {@link Varargs} containing the values to use in + * initialization + * @param firstarg the index of the first argument to use from the varargs, + * 1 being the first. + * @return new {@link LuaTable} instance with sequential elements coming + * from the varargs. */ - public static LuaTable tableOf(Varargs varargs, int firstarg) { return new LuaTable(varargs,firstarg); } - - /** Construct an empty {@link LuaTable} preallocated to hold array and hashed elements + public static LuaTable tableOf(Varargs varargs, int firstarg) { return new LuaTable(varargs, firstarg); } + + /** + * Construct an empty {@link LuaTable} preallocated to hold array and hashed + * elements + * * @param narray Number of array elements to preallocate - * @param nhash Number of hash elements to preallocate - * @return new {@link LuaTable} instance with no values and no metatable, but preallocated for array and hashed elements. + * @param nhash Number of hash elements to preallocate + * @return new {@link LuaTable} instance with no values and no metatable, + * but preallocated for array and hashed elements. */ public static LuaTable tableOf(int narray, int nhash) { return new LuaTable(narray, nhash); } - - /** Construct a {@link LuaTable} initialized with supplied array values. - * @param unnamedValues array of {@link LuaValue} containing the values to use in initialization - * @return new {@link LuaTable} instance with sequential elements coming from the array. - */ - public static LuaTable listOf(LuaValue[] unnamedValues) { return new LuaTable(null,unnamedValues,null); } - - /** Construct a {@link LuaTable} initialized with supplied array values. - * @param unnamedValues array of {@link LuaValue} containing the first values to use in initialization - * @param lastarg {@link Varargs} containing additional values to use in initialization - * to be put after the last unnamedValues element - * @return new {@link LuaTable} instance with sequential elements coming from the array and varargs. - */ - public static LuaTable listOf(LuaValue[] unnamedValues,Varargs lastarg) { return new LuaTable(null,unnamedValues,lastarg); } - /** Construct a {@link LuaTable} initialized with supplied named values. - * @param namedValues array of {@link LuaValue} containing the keys and values to use in initialization - * in order {@code {key-a, value-a, key-b, value-b, ...} } - * @return new {@link LuaTable} instance with non-sequential keys coming from the supplied array. + /** + * Construct a {@link LuaTable} initialized with supplied array values. + * + * @param unnamedValues array of {@link LuaValue} containing the values to + * use in initialization + * @return new {@link LuaTable} instance with sequential elements coming + * from the array. */ - public static LuaTable tableOf(LuaValue[] namedValues) { return new LuaTable(namedValues,null,null); } + public static LuaTable listOf(LuaValue[] unnamedValues) { return new LuaTable(null, unnamedValues, null); } - /** Construct a {@link LuaTable} initialized with supplied named values and sequential elements. - * The named values will be assigned first, and the sequential elements will be assigned later, - * possibly overwriting named values at the same slot if there are conflicts. - * @param namedValues array of {@link LuaValue} containing the keys and values to use in initialization - * in order {@code {key-a, value-a, key-b, value-b, ...} } - * @param unnamedValues array of {@link LuaValue} containing the sequenctial elements to use in initialization - * in order {@code {value-1, value-2, ...} }, or null if there are none - * @return new {@link LuaTable} instance with named and sequential values supplied. + /** + * Construct a {@link LuaTable} initialized with supplied array values. + * + * @param unnamedValues array of {@link LuaValue} containing the first + * values to use in initialization + * @param lastarg {@link Varargs} containing additional values to use + * in initialization to be put after the last + * unnamedValues element + * @return new {@link LuaTable} instance with sequential elements coming + * from the array and varargs. */ - public static LuaTable tableOf(LuaValue[] namedValues, LuaValue[] unnamedValues) {return new LuaTable(namedValues,unnamedValues,null); } + public static LuaTable listOf(LuaValue[] unnamedValues, Varargs lastarg) { + return new LuaTable(null, unnamedValues, lastarg); + } - /** Construct a {@link LuaTable} initialized with supplied named values and sequential elements in an array part and as varargs. - * The named values will be assigned first, and the sequential elements will be assigned later, - * possibly overwriting named values at the same slot if there are conflicts. - * @param namedValues array of {@link LuaValue} containing the keys and values to use in initialization - * in order {@code {key-a, value-a, key-b, value-b, ...} } - * @param unnamedValues array of {@link LuaValue} containing the first sequenctial elements to use in initialization - * in order {@code {value-1, value-2, ...} }, or null if there are none - * @param lastarg {@link Varargs} containing additional values to use in the sequential part of the initialization, - * to be put after the last unnamedValues element - * @return new {@link LuaTable} instance with named and sequential values supplied. + /** + * Construct a {@link LuaTable} initialized with supplied named values. + * + * @param namedValues array of {@link LuaValue} containing the keys and + * values to use in initialization in order + * {@code {key-a, value-a, key-b, value-b, ...} } + * @return new {@link LuaTable} instance with non-sequential keys coming + * from the supplied array. */ - public static LuaTable tableOf(LuaValue[] namedValues, LuaValue[] unnamedValues, Varargs lastarg) {return new LuaTable(namedValues,unnamedValues,lastarg); } - - /** Construct a LuaUserdata for an object. + public static LuaTable tableOf(LuaValue[] namedValues) { return new LuaTable(namedValues, null, null); } + + /** + * Construct a {@link LuaTable} initialized with supplied named values and + * sequential elements. The named values will be assigned first, and the + * sequential elements will be assigned later, possibly overwriting named + * values at the same slot if there are conflicts. + * + * @param namedValues array of {@link LuaValue} containing the keys and + * values to use in initialization in order + * {@code {key-a, value-a, key-b, value-b, ...} } + * @param unnamedValues array of {@link LuaValue} containing the sequenctial + * elements to use in initialization in order + * {@code {value-1, value-2, ...} }, or null if there + * are none + * @return new {@link LuaTable} instance with named and sequential values + * supplied. + */ + public static LuaTable tableOf(LuaValue[] namedValues, LuaValue[] unnamedValues) { + return new LuaTable(namedValues, unnamedValues, null); + } + + /** + * Construct a {@link LuaTable} initialized with supplied named values and + * sequential elements in an array part and as varargs. The named values + * will be assigned first, and the sequential elements will be assigned + * later, possibly overwriting named values at the same slot if there are + * conflicts. + * + * @param namedValues array of {@link LuaValue} containing the keys and + * values to use in initialization in order + * {@code {key-a, value-a, key-b, value-b, ...} } + * @param unnamedValues array of {@link LuaValue} containing the first + * sequenctial elements to use in initialization in + * order {@code {value-1, value-2, ...} }, or null if + * there are none + * @param lastarg {@link Varargs} containing additional values to use + * in the sequential part of the initialization, to be + * put after the last unnamedValues element + * @return new {@link LuaTable} instance with named and sequential values + * supplied. + */ + public static LuaTable tableOf(LuaValue[] namedValues, LuaValue[] unnamedValues, Varargs lastarg) { + return new LuaTable(namedValues, unnamedValues, lastarg); + } + + /** + * Construct a LuaUserdata for an object. * * @param o The java instance to be wrapped as userdata * @return {@link LuaUserdata} value wrapping the java instance. */ public static LuaUserdata userdataOf(Object o) { return new LuaUserdata(o); } - - /** Construct a LuaUserdata for an object with a user supplied metatable. + + /** + * Construct a LuaUserdata for an object with a user supplied metatable. * - * @param o The java instance to be wrapped as userdata + * @param o The java instance to be wrapped as userdata * @param metatable The metatble to associate with the userdata instance. * @return {@link LuaUserdata} value wrapping the java instance. */ - public static LuaUserdata userdataOf(Object o,LuaValue metatable) { return new LuaUserdata(o,metatable); } + public static LuaUserdata userdataOf(Object o, LuaValue metatable) { return new LuaUserdata(o, metatable); } /** Constant limiting metatag loop processing */ - private static final int MAXTAGLOOP = 100; - + private static final int MAXTAGLOOP = 100; + /** - * Return value for field reference including metatag processing, or {@link LuaValue#NIL} if it doesn't exist. - * @param t {@link LuaValue} on which field is being referenced, typically a table or something with the metatag {@link LuaValue#INDEX} defined + * Return value for field reference including metatag processing, or + * {@link LuaValue#NIL} if it doesn't exist. + * + * @param t {@link LuaValue} on which field is being referenced, typically + * a table or something with the metatag {@link LuaValue#INDEX} + * defined * @param key {@link LuaValue} naming the field to reference - * @return {@link LuaValue} for the {@code key} if it exists, or {@link LuaValue#NIL} + * @return {@link LuaValue} for the {@code key} if it exists, or + * {@link LuaValue#NIL} * @throws LuaError if there is a loop in metatag processing */ - /** get value from metatable operations, or NIL if not defined by metatables */ + /** + * get value from metatable operations, or NIL if not defined by metatables + */ protected static LuaValue gettable(LuaValue t, LuaValue key) { LuaValue tm; int loop = 0; @@ -3300,19 +3832,22 @@ public class LuaValue extends Varargs { if (tm.isfunction()) return tm.call(t, key); t = tm; - } - while ( ++loop < MAXTAGLOOP ); + } while ( ++loop < MAXTAGLOOP ); error("loop in gettable"); return NIL; } - + /** * Perform field assignment including metatag processing. - * @param t {@link LuaValue} on which value is being set, typically a table or something with the metatag {@link LuaValue#NEWINDEX} defined - * @param key {@link LuaValue} naming the field to assign + * + * @param t {@link LuaValue} on which value is being set, typically a + * table or something with the metatag + * {@link LuaValue#NEWINDEX} defined + * @param key {@link LuaValue} naming the field to assign * @param value {@link LuaValue} the new value to assign to {@code key} * @throws LuaError if there is a loop in metatag processing - * @return true if assignment or metatag processing succeeded, false otherwise + * @return true if assignment or metatag processing succeeded, false + * otherwise */ protected static boolean settable(LuaValue t, LuaValue key, LuaValue value) { LuaValue tm; @@ -3330,68 +3865,73 @@ public class LuaValue extends Varargs { return true; } t = tm; - } - while ( ++loop < MAXTAGLOOP ); + } while ( ++loop < MAXTAGLOOP ); error("loop in settable"); return false; } - - /** - * Get particular metatag, or return {@link LuaValue#NIL} if it doesn't exist - * @param tag Metatag name to look up, typically a string such as - * {@link LuaValue#INDEX} or {@link LuaValue#NEWINDEX} - * @return {@link LuaValue} for tag {@code reason}, or {@link LuaValue#NIL} - */ - public LuaValue metatag(LuaValue tag) { - LuaValue mt = getmetatable(); - if ( mt == null ) - return NIL; - return mt.rawget(tag); - } - /** - * Get particular metatag, or throw {@link LuaError} if it doesn't exist - * @param tag Metatag name to look up, typically a string such as - * {@link LuaValue#INDEX} or {@link LuaValue#NEWINDEX} - * @param reason Description of error when tag lookup fails. - * @return {@link LuaValue} that can be called - * @throws LuaError when the lookup fails. - */ + /** + * Get particular metatag, or return {@link LuaValue#NIL} if it doesn't + * exist + * + * @param tag Metatag name to look up, typically a string such as + * {@link LuaValue#INDEX} or {@link LuaValue#NEWINDEX} + * @return {@link LuaValue} for tag {@code reason}, or {@link LuaValue#NIL} + */ + public LuaValue metatag(LuaValue tag) { + LuaValue mt = getmetatable(); + if (mt == null) + return NIL; + return mt.rawget(tag); + } + + /** + * Get particular metatag, or throw {@link LuaError} if it doesn't exist + * + * @param tag Metatag name to look up, typically a string such as + * {@link LuaValue#INDEX} or {@link LuaValue#NEWINDEX} + * @param reason Description of error when tag lookup fails. + * @return {@link LuaValue} that can be called + * @throws LuaError when the lookup fails. + */ protected LuaValue checkmetatag(LuaValue tag, String reason) { LuaValue h = this.metatag(tag); - if ( h.isnil() ) + if (h.isnil()) throw new LuaError(reason + "a " + typename() + " value"); return h; } /** Construct a Metatable instance from the given LuaValue */ protected static Metatable metatableOf(LuaValue mt) { - if ( mt != null && mt.istable() ) { + if (mt != null && mt.istable()) { LuaValue mode = mt.rawget(MODE); - if ( mode.isstring() ) { + if (mode.isstring()) { String m = mode.tojstring(); boolean weakkeys = m.indexOf('k') >= 0; boolean weakvalues = m.indexOf('v') >= 0; - if ( weakkeys || weakvalues ) { + if (weakkeys || weakvalues) { return new WeakTable(weakkeys, weakvalues, mt); } } - return (LuaTable)mt; - } else if ( mt != null ) { - return new NonTableMetatable( mt ); + return (LuaTable) mt; + } else if (mt != null) { + return new NonTableMetatable(mt); } else { return null; } } - /** Throw {@link LuaError} indicating index was attempted on illegal type + /** + * Throw {@link LuaError} indicating index was attempted on illegal type + * * @throws LuaError when called. */ - private void indexerror(String key) { - error( "attempt to index ? (a "+typename()+" value) with key '" + key + "'" ); + private void indexerror(String key) { + error("attempt to index ? (a " + typename() + " value) with key '" + key + "'"); } - - /** Construct a {@link Varargs} around an array of {@link LuaValue}s. + + /** + * Construct a {@link Varargs} around an array of {@link LuaValue}s. * * @param v The array of {@link LuaValue}s * @return {@link Varargs} wrapping the supplied values. @@ -3399,15 +3939,20 @@ public class LuaValue extends Varargs { * @see LuaValue#varargsOf(LuaValue[], int, int) */ public static Varargs varargsOf(final LuaValue[] v) { - switch ( v.length ) { - case 0: return NONE; - case 1: return v[0]; - case 2: return new Varargs.PairVarargs(v[0],v[1]); - default: return new Varargs.ArrayVarargs(v,NONE); + switch (v.length) { + case 0: + return NONE; + case 1: + return v[0]; + case 2: + return new Varargs.PairVarargs(v[0], v[1]); + default: + return new Varargs.ArrayVarargs(v, NONE); } } - - /** Construct a {@link Varargs} around an array of {@link LuaValue}s. + + /** + * Construct a {@link Varargs} around an array of {@link LuaValue}s. * * @param v The array of {@link LuaValue}s * @param r {@link Varargs} contain values to include at the end @@ -3415,22 +3960,24 @@ public class LuaValue extends Varargs { * @see LuaValue#varargsOf(LuaValue[]) * @see LuaValue#varargsOf(LuaValue[], int, int, Varargs) */ - public static Varargs varargsOf(final LuaValue[] v,Varargs r) { - switch ( v.length ) { - case 0: return r; - case 1: return r.narg()>0? - (Varargs) new Varargs.PairVarargs(v[0],r): - (Varargs) v[0]; - case 2: return r.narg()>0? - (Varargs) new Varargs.ArrayVarargs(v,r): - (Varargs) new Varargs.PairVarargs(v[0],v[1]); - default: return new Varargs.ArrayVarargs(v,r); + public static Varargs varargsOf(final LuaValue[] v, Varargs r) { + switch (v.length) { + case 0: + return r; + case 1: + return r.narg() > 0? (Varargs) new Varargs.PairVarargs(v[0], r): (Varargs) v[0]; + case 2: + return r.narg() > 0? (Varargs) new Varargs.ArrayVarargs(v, r) + : (Varargs) new Varargs.PairVarargs(v[0], v[1]); + default: + return new Varargs.ArrayVarargs(v, r); } } - /** Construct a {@link Varargs} around an array of {@link LuaValue}s. + /** + * Construct a {@link Varargs} around an array of {@link LuaValue}s. * - * @param v The array of {@link LuaValue}s + * @param v The array of {@link LuaValue}s * @param offset number of initial values to skip in the array * @param length number of values to include from the array * @return {@link Varargs} wrapping the supplied values. @@ -3438,82 +3985,95 @@ public class LuaValue extends Varargs { * @see LuaValue#varargsOf(LuaValue[], int, int, Varargs) */ public static Varargs varargsOf(final LuaValue[] v, final int offset, final int length) { - switch ( length ) { - case 0: return NONE; - case 1: return v[offset]; - case 2: return new Varargs.PairVarargs(v[offset+0],v[offset+1]); - default: return new Varargs.ArrayPartVarargs(v, offset, length, NONE); + switch (length) { + case 0: + return NONE; + case 1: + return v[offset]; + case 2: + return new Varargs.PairVarargs(v[offset+0], v[offset+1]); + default: + return new Varargs.ArrayPartVarargs(v, offset, length, NONE); } } - /** Construct a {@link Varargs} around an array of {@link LuaValue}s. + /** + * Construct a {@link Varargs} around an array of {@link LuaValue}s. * - * Caller must ensure that array contents are not mutated after this call - * or undefined behavior will result. + * Caller must ensure that array contents are not mutated after this call or + * undefined behavior will result. * - * @param v The array of {@link LuaValue}s + * @param v The array of {@link LuaValue}s * @param offset number of initial values to skip in the array * @param length number of values to include from the array - * @param more {@link Varargs} contain values to include at the end + * @param more {@link Varargs} contain values to include at the end * @return {@link Varargs} wrapping the supplied values. * @see LuaValue#varargsOf(LuaValue[], Varargs) * @see LuaValue#varargsOf(LuaValue[], int, int) */ public static Varargs varargsOf(final LuaValue[] v, final int offset, final int length, Varargs more) { - switch ( length ) { - case 0: return more; - case 1: return more.narg()>0? - (Varargs) new Varargs.PairVarargs(v[offset],more): - (Varargs) v[offset]; - case 2: return more.narg()>0? - (Varargs) new Varargs.ArrayPartVarargs(v,offset,length,more): - (Varargs) new Varargs.PairVarargs(v[offset],v[offset+1]); - default: return new Varargs.ArrayPartVarargs(v,offset,length,more); + switch (length) { + case 0: + return more; + case 1: + return more.narg() > 0? (Varargs) new Varargs.PairVarargs(v[offset], more): (Varargs) v[offset]; + case 2: + return more.narg() > 0? (Varargs) new Varargs.ArrayPartVarargs(v, offset, length, more) + : (Varargs) new Varargs.PairVarargs(v[offset], v[offset+1]); + default: + return new Varargs.ArrayPartVarargs(v, offset, length, more); } } - /** Construct a {@link Varargs} around a set of 2 or more {@link LuaValue}s. + /** + * Construct a {@link Varargs} around a set of 2 or more {@link LuaValue}s. *

- * This can be used to wrap exactly 2 values, or a list consisting of 1 initial value - * followed by another variable list of remaining values. + * This can be used to wrap exactly 2 values, or a list consisting of 1 + * initial value followed by another variable list of remaining values. * * @param v First {@link LuaValue} in the {@link Varargs} - * @param r {@link LuaValue} supplying the 2rd value, - * or {@link Varargs}s supplying all values beyond the first + * @param r {@link LuaValue} supplying the 2rd value, or {@link Varargs}s + * supplying all values beyond the first * @return {@link Varargs} wrapping the supplied values. */ public static Varargs varargsOf(LuaValue v, Varargs r) { - switch ( r.narg() ) { - case 0: return v; - default: return new Varargs.PairVarargs(v,r); + switch (r.narg()) { + case 0: + return v; + default: + return new Varargs.PairVarargs(v, r); } } - - /** Construct a {@link Varargs} around a set of 3 or more {@link LuaValue}s. + + /** + * Construct a {@link Varargs} around a set of 3 or more {@link LuaValue}s. *

- * This can be used to wrap exactly 3 values, or a list consisting of 2 initial values - * followed by another variable list of remaining values. + * This can be used to wrap exactly 3 values, or a list consisting of 2 + * initial values followed by another variable list of remaining values. * * @param v1 First {@link LuaValue} in the {@link Varargs} * @param v2 Second {@link LuaValue} in the {@link Varargs} - * @param v3 {@link LuaValue} supplying the 3rd value, - * or {@link Varargs}s supplying all values beyond the second + * @param v3 {@link LuaValue} supplying the 3rd value, or {@link Varargs}s + * supplying all values beyond the second * @return {@link Varargs} wrapping the supplied values. */ - public static Varargs varargsOf(LuaValue v1,LuaValue v2,Varargs v3) { - switch ( v3.narg() ) { - case 0: return new Varargs.PairVarargs(v1,v2); - default: return new Varargs.ArrayPartVarargs(new LuaValue[]{v1,v2}, 0, 2, v3); + public static Varargs varargsOf(LuaValue v1, LuaValue v2, Varargs v3) { + switch (v3.narg()) { + case 0: + return new Varargs.PairVarargs(v1, v2); + default: + return new Varargs.ArrayPartVarargs(new LuaValue[] { v1, v2 }, 0, 2, v3); } } - - /** Construct a {@link TailcallVarargs} around a function and arguments. + + /** + * Construct a {@link TailcallVarargs} around a function and arguments. *

* The tail call is not yet called or processing until the client invokes * {@link TailcallVarargs#eval()} which performs the tail call processing. *

- * This method is typically not used directly by client code. - * Instead use one of the function invocation methods. + * This method is typically not used directly by client code. Instead use + * one of the function invocation methods. * * @param func {@link LuaValue} to be called as a tail call * @param args {@link Varargs} containing the arguments to the call @@ -3526,13 +4086,14 @@ public class LuaValue extends Varargs { public static Varargs tailcallOf(LuaValue func, Varargs args) { return new TailcallVarargs(func, args); } - + /** * Callback used during tail call processing to invoke the function once. *

* This may return a {@link TailcallVarargs} to be evaluated by the client. *

- * This should not be called directly, instead use one of the call invocation functions. + * This should not be called directly, instead use one of the call + * invocation functions. * * @param args the arguments to the call invocation. * @return Varargs the return values, possible a TailcallVarargs. @@ -3545,34 +4106,51 @@ public class LuaValue extends Varargs { return invoke(args); } - /** Hook for implementations such as LuaJC to load the environment of the main chunk - * into the first upvalue location. If the function has no upvalues or is not a main chunk, - * calling this will be no effect. - * @param env The environment to load into the first upvalue, if there is one. + /** + * Hook for implementations such as LuaJC to load the environment of the + * main chunk into the first upvalue location. If the function has no + * upvalues or is not a main chunk, calling this will be no effect. + * + * @param env The environment to load into the first upvalue, if there is + * one. */ public void initupvalue1(LuaValue env) {} - /** Varargs implemenation with no values. + /** + * Varargs implemenation with no values. *

- * This is an internal class not intended to be used directly. - * Instead use the predefined constant {@link LuaValue#NONE} + * This is an internal class not intended to be used directly. Instead use + * the predefined constant {@link LuaValue#NONE} * * @see LuaValue#NONE */ private static final class None extends LuaNil { static None _NONE = new None(); + public LuaValue arg(int i) { return NIL; } + public int narg() { return 0; } + public LuaValue arg1() { return NIL; } + public String tojstring() { return "none"; } + public Varargs subargs(final int start) { return start > 0? this: argerror(1, "start must be > 0"); } - void copyto(LuaValue[] dest, int offset, int length) { for(;length>0; length--) dest[offset++] = NIL; } + + void copyto(LuaValue[] dest, int offset, int length) { + for (; length > 0; length--) + dest[offset++] = NIL; + } } - + /** - * 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 + * } */ public Varargs subargs(final int start) { if (start == 1) diff --git a/luaj-core/src/main/java/org/luaj/vm2/Metatable.java b/luaj-core/src/main/java/org/luaj/vm2/Metatable.java index 49c639b6..70f7418e 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/Metatable.java +++ b/luaj-core/src/main/java/org/luaj/vm2/Metatable.java @@ -38,14 +38,14 @@ interface Metatable { public LuaValue toLuaValue(); /** Return an instance of Slot appropriate for the given key and value. */ - public Slot entry( LuaValue key, LuaValue value ); + public Slot entry(LuaValue key, LuaValue value); /** Returns the given value wrapped in a weak reference if appropriate. */ - public LuaValue wrap( LuaValue value ); + public 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); } diff --git a/luaj-core/src/main/java/org/luaj/vm2/OrphanedThread.java b/luaj-core/src/main/java/org/luaj/vm2/OrphanedThread.java index b3c931f1..a1ff7a50 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/OrphanedThread.java +++ b/luaj-core/src/main/java/org/luaj/vm2/OrphanedThread.java @@ -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/luaj-core/src/main/java/org/luaj/vm2/Print.java b/luaj-core/src/main/java/org/luaj/vm2/Print.java index 8b0bd572..585d5bbd 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/Print.java +++ b/luaj-core/src/main/java/org/luaj/vm2/Print.java @@ -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)); } 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) { @@ -312,8 +279,8 @@ public class Print extends Lua { ps.print(" ; " + ((int) 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. + * 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)}: - *

 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * globals.load( new StringReader("print 'hello'"), "main.lua" ).call(); 
- * } 
+ * 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)}: + * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	globals.load(new StringReader("print 'hello'"), "main.lua").call();
+ * }
+ * 
* *

- * To create a {@link Prototype} directly, a compiler such as + * To create a {@link Prototype} directly, a compiler such as * {@link org.luaj.vm2.compiler.LuaC} may be used: - *

 {@code
- * InputStream is = new ByteArrayInputStream("print('hello,world')".getBytes());
- * Prototype p = LuaC.instance.compile(is, "script");
- * }
* - * To simplify loading, the {@link Globals#compilePrototype(java.io.InputStream, String)} method may be used: - *
 {@code
- * Prototype p = globals.compileProtoytpe(is, "script");
- * }
+ *
+ * {
+ * 	@code
+ * 	InputStream is = new ByteArrayInputStream("print('hello,world')".getBytes());
+ * 	Prototype p = LuaC.instance.compile(is, "script");
+ * }
+ * 
* - * It may also be loaded from a {@link java.io.Reader} via {@link Globals#compilePrototype(java.io.Reader, String)}: - *
 {@code
- * Prototype p = globals.compileProtoytpe(new StringReader(script), "script");
- * }
+ * To simplify loading, the + * {@link Globals#compilePrototype(java.io.InputStream, String)} method may be + * used: * - * 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");
- * }
+ *
+ * {
+ * 	@code
+ * 	Prototype p = globals.compileProtoytpe(is, "script");
+ * }
+ * 
* - * To execute the code represented by the {@link Prototype} it must be supplied to - * the constructor of a {@link LuaClosure}: - *
 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * LuaClosure f = new LuaClosure(p, globals);
- * f.call();
- * }
+ * It may also be loaded from a {@link java.io.Reader} via + * {@link Globals#compilePrototype(java.io.Reader, String)}: * - * To simplify the debugging of prototype values, the contents may be printed using {@link Print#print}: - *
 {@code
+ * 
+ * {
+ * 	@code
+ * 	Prototype p = globals.compileProtoytpe(new StringReader(script), "script");
+ * }
+ * 
+ * + * 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}: + * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	LuaClosure f = new LuaClosure(p, globals);
+ * 	f.call();
+ * }
+ * 
+ * + * 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 @@ -84,8 +116,8 @@ package org.luaj.vm2; public class Prototype { /* constants used by the function */ - public LuaValue[] k; - public int[] code; + public LuaValue[] k; + public int[] code; /* functions defined inside the function */ public Prototype[] p; /* map from opcodes to source lines */ @@ -93,14 +125,14 @@ public class Prototype { /* 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 = {}; + 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() { @@ -112,35 +144,36 @@ public class Prototype { p = NOSUBPROTOS; upvalues = new Upvaldesc[n_upvalues]; } - + public String toString() { - return source + ":" + linedefined+"-"+lastlinedefined; + return source + ":" + linedefined + "-" + lastlinedefined; } - - /** Get the name of a local variable. + + /** + * Get the name of a local variable. * * @param number the local variable number to look up - * @param pc the program counter + * @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 - * 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; - } - + + public boolean isTailcall() { return true; } + public Varargs eval() { while ( result == null ) { Varargs r = func.onInvoke(args); @@ -67,28 +64,27 @@ 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 ) + + public LuaValue arg(int i) { + if (result == null) eval(); return result.arg(i); } - + public LuaValue arg1() { if (result == null) eval(); return result.arg1(); } - + public int narg() { if (result == null) eval(); @@ -100,4 +96,4 @@ public class TailcallVarargs extends Varargs { eval(); return result.subargs(start); } -} \ No newline at end of file +} diff --git a/luaj-core/src/main/java/org/luaj/vm2/UpValue.java b/luaj-core/src/main/java/org/luaj/vm2/UpValue.java index 8fa8186b..62a3ac4e 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/UpValue.java +++ b/luaj-core/src/main/java/org/luaj/vm2/UpValue.java @@ -21,23 +21,25 @@ ******************************************************************************/ 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; + 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; } @@ -45,32 +47,31 @@ public final class UpValue { 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 final 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 final void setValue(LuaValue value) { array[index] = value; } + /** * Close this upvalue so it is no longer on the stack */ diff --git a/luaj-core/src/main/java/org/luaj/vm2/Upvaldesc.java b/luaj-core/src/main/java/org/luaj/vm2/Upvaldesc.java index c1e44974..041e8e33 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/Upvaldesc.java +++ b/luaj-core/src/main/java/org/luaj/vm2/Upvaldesc.java @@ -25,20 +25,20 @@ 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; } - + public String toString() { - return idx + (instack? " instack ": " closed ") + String.valueOf(name); + return idx+(instack? " instack ": " closed ")+String.valueOf(name); } } diff --git a/luaj-core/src/main/java/org/luaj/vm2/Varargs.java b/luaj-core/src/main/java/org/luaj/vm2/Varargs.java index e56d8dcf..b5f6c05e 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/Varargs.java +++ b/luaj-core/src/main/java/org/luaj/vm2/Varargs.java @@ -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,621 @@ 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() */ 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; } + 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; } + public LuaValue arg1() { return v.arg(start); } + public int narg() { return end+1-start; } + 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,20 +736,23 @@ 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) */ @@ -565,89 +760,104 @@ public abstract class Varargs { this.v1 = v1; this.v2 = v2; } + public LuaValue arg(int i) { - return i==1? v1: v2.arg(i-1); + return i == 1? v1: v2.arg(i-1); } + public int narg() { return 1+v2.narg(); } + public LuaValue arg1() { return v1; } + 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; } + 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); } + public int narg() { return v.length+r.narg(); } - public LuaValue arg1() { return v.length>0? v[0]: r.arg1(); } + + public LuaValue arg1() { return v.length > 0? v[0]: r.arg1(); } + 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); } + 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) */ @@ -657,10 +867,13 @@ 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) */ @@ -670,52 +883,66 @@ public abstract class Varargs { this.length = length; this.more = more; } + public LuaValue arg(final int i) { return i < 1? LuaValue.NIL: i <= length? v[offset+i-1]: more.arg(i-length); } + public int narg() { - return length + more.narg(); + return length+more.narg(); } + public LuaValue arg1() { - return length>0? v[offset]: more.arg1(); + return length > 0? v[offset]: more.arg1(); } + 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); } + 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 boolean weakkeys, weakvalues; private 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(); @@ -59,7 +59,8 @@ public class WeakTable implements Metatable { /** * 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) { @@ -82,26 +83,26 @@ public class WeakTable implements Metatable { 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 +110,14 @@ public class WeakTable implements Metatable { this.next = next; } - public abstract int keyindex( int hashMask ); + public abstract int keyindex(int hashMask); public abstract Slot set(LuaValue value); 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; @@ -127,12 +128,12 @@ public class WeakTable implements Metatable { public StrongSlot find(LuaValue key) { StrongSlot first = first(); - return ( first != null ) ? first.find( key ) : null; + return (first != null)? first.find(key): null; } public boolean keyeq(LuaValue key) { StrongSlot first = first(); - return ( first != null ) && first.keyeq( key ); + return (first != null) && first.keyeq(key); } public Slot rest() { @@ -146,46 +147,46 @@ public class WeakTable implements Metatable { 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 ) { + 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 ) { + 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 ) { + 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,25 +201,25 @@ 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 ); + public int keyindex(int mask) { + return LuaTable.hashmod(keyhash, mask); } public Slot set(LuaValue value) { @@ -227,26 +228,26 @@ public class WeakTable implements Metatable { } public LuaValue strongkey() { - return strengthen( key ); + return strengthen(key); } - protected WeakSlot copy( Slot rest ) { - return new WeakKeySlot( this, rest ); + 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 ); + public int keyindex(int mask) { + return LuaTable.hashSlot(strongkey(), mask); } public Slot set(LuaValue value) { @@ -255,11 +256,11 @@ public class WeakTable implements Metatable { } public LuaValue strongvalue() { - return strengthen( value ); + return strengthen(value); } protected WeakSlot copy(Slot next) { - return new WeakValueSlot( this, next ); + return new WeakValueSlot(this, next); } } @@ -267,18 +268,18 @@ 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 ); + public int keyindex(int hashMask) { + return LuaTable.hashmod(keyhash, hashMask); } public Slot set(LuaValue value) { @@ -287,53 +288,58 @@ public class WeakTable implements Metatable { } public LuaValue strongkey() { - return strengthen( key ); + return strengthen(key); } public LuaValue strongvalue() { - return strengthen( value ); + return strengthen(value); } - protected WeakSlot copy( Slot next ) { - return new WeakKeyAndValueSlot( this, next ); + 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 { @@ -344,36 +350,38 @@ public class WeakTable implements Metatable { } public int type() { - illegal("type","weak value"); + illegal("type", "weak value"); return 0; } public String typename() { - illegal("typename","weak value"); + illegal("typename", "weak value"); return null; } public String toString() { - return "weak<"+ref.get()+">"; + return "weak<" + ref.get() + ">"; } public LuaValue strongvalue() { Object o = ref.get(); - return (LuaValue)o; + return (LuaValue) o; } 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); @@ -383,11 +391,11 @@ public class WeakTable implements Metatable { 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 { @@ -397,7 +405,7 @@ public class WeakTable implements Metatable { } public LuaValue wrap(LuaValue value) { - return weakvalues ? weaken( value ) : value; + return weakvalues? weaken(value): value; } public LuaValue arrayget(LuaValue[] array, int index) { diff --git a/luaj-core/src/main/java/org/luaj/vm2/compiler/Constants.java b/luaj-core/src/main/java/org/luaj/vm2/compiler/Constants.java index fc505b49..60a7fcd6 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/compiler/Constants.java +++ b/luaj-core/src/main/java/org/luaj/vm2/compiler/Constants.java @@ -36,153 +36,141 @@ import org.luaj.vm2.Upvaldesc; * @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();
- * } 
+ * + *
+ * {
+ * 	@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();
+ * }
+ * 
* * The {@link LoadState} may be used directly to undump these bytes: - *
 {@code
+ * 
+ * 
+ *  {@code
  * Prototypep = LoadState.instance.undump(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua");
  * LuaClosure c = new LuaClosure(p, globals);
  * c.call();
- * } 
+ * } + *
* * * More commonly, the {@link Globals#undumper} may be used to undump them: - *
 {@code
- * Prototype p = globals.loadPrototype(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua", "b");
- * LuaClosure c = new LuaClosure(p, globals);
- * c.call();
- * } 
+ * + *
+ * {
+ * 	@code
+ * 	Prototype p = globals.loadPrototype(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua", "b");
+ * 	LuaClosure c = new LuaClosure(p, globals);
+ * 	c.call();
+ * }
+ * 
* * @see luac * @see LoadState @@ -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) { @@ -255,50 +248,49 @@ public class FuncState extends Constants { 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(); @@ -481,8 +468,8 @@ public class FuncState extends Constants { final int idx = this.nk; this.h.put(v, new Integer(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 == (double) 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; } } @@ -862,7 +845,7 @@ public class FuncState extends Constants { 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); + 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,13 +884,13 @@ 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; } @@ -915,8 +898,7 @@ public class FuncState extends Constants { if (constfolding(op, e1, e2)) return; else { - int o2 = (op != OP_UNM && op != OP_LEN) ? this.exp2RK(e2) - : 0; + 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 +913,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 +929,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 +951,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 +986,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 +997,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 +1006,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 +1055,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 = LuaC.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 = LuaC.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 +1107,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/luaj-core/src/main/java/org/luaj/vm2/compiler/InstructionPtr.java b/luaj-core/src/main/java/org/luaj/vm2/compiler/InstructionPtr.java index fbdf061a..1325b194 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/compiler/InstructionPtr.java +++ b/luaj-core/src/main/java/org/luaj/vm2/compiler/InstructionPtr.java @@ -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/luaj-core/src/main/java/org/luaj/vm2/compiler/IntPtr.java b/luaj-core/src/main/java/org/luaj/vm2/compiler/IntPtr.java index 0f42cb0e..a54fd083 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/compiler/IntPtr.java +++ b/luaj-core/src/main/java/org/luaj/vm2/compiler/IntPtr.java @@ -23,8 +23,10 @@ package org.luaj.vm2.compiler; public class IntPtr { int i; + IntPtr() { } + IntPtr(int value) { this.i = value; } diff --git a/luaj-core/src/main/java/org/luaj/vm2/compiler/LexState.java b/luaj-core/src/main/java/org/luaj/vm2/compiler/LexState.java index 0192de05..65849e99 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/compiler/LexState.java +++ b/luaj-core/src/main/java/org/luaj/vm2/compiler/LexState.java @@ -35,46 +35,41 @@ 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 String luaX_tokens[] = { "and", "break", "do", "else", "elseif", "end", "false", "for", "function", + "goto", "if", "in", "local", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while", "..", + "...", "==", ">=", "<=", "~=", "::", "", "", "", "", "", }; 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_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; + 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'); } - + 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 <= ' '); } - - + public LexState(LuaC.CompileState state, InputStream stream) { this.z = stream; this.buff = new char[32]; @@ -210,8 +185,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 +197,20 @@ 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(" + ((int) token) + ")") + : L.pushfstring(String.valueOf((char) token)); } else { return luaX_tokens[token-FIRST_RESERVED]; } @@ -248,44 +221,44 @@ 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"); } @@ -298,19 +271,17 @@ public class LexState extends Constants { 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 +289,6 @@ public class LexState extends Constants { ** ======================================================= */ - boolean check_next(String set) { if (set.indexOf(current) < 0) return false; @@ -329,7 +299,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 +307,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,7 +316,7 @@ public class LexState extends Constants { ++s; } /* Check for "0x" */ - if (s + 2 >= c.length ) + if (s+2 >= c.length) return LuaValue.ZERO; if (c[s++] != '0') return LuaValue.ZERO; @@ -357,13 +327,13 @@ public class LexState extends Constants { // 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) { @@ -437,8 +407,7 @@ public class LexState extends Constants { for (boolean endloop = false; !endloop;) { switch (current) { case EOZ: - lexerror((seminfo != null) ? "unfinished long string" - : "unfinished long comment", TK_EOS); + lexerror((seminfo != null)? "unfinished long string": "unfinished long comment", TK_EOS); break; /* to avoid warnings */ case '[': { if (skip_sep() == sep) { @@ -480,11 +449,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,13 +462,13 @@ 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); @@ -543,14 +512,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 +529,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 +553,7 @@ public class LexState extends Constants { int llex(SemInfo seminfo) { nbuff = 0; - while (true) { + while ( true ) { switch (current) { case '\n': case '\r': { @@ -612,7 +583,7 @@ public class LexState extends Constants { } } /* else short comment */ - while (!currIsNewline() && current != EOZ) + while ( !currIsNewline() && current != EOZ ) nextChar(); continue; } @@ -690,12 +661,20 @@ public class LexState extends Constants { return TK_NUMBER; } } - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': { - read_numeral(seminfo); - return TK_NUMBER; - } - case EOZ: { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + read_numeral(seminfo); + return TK_NUMBER; + } + case EOZ: { return TK_EOS; } default: { @@ -704,10 +683,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; @@ -725,22 +704,21 @@ public class LexState extends Constants { void next() { lastline = linenumber; if (lookahead.token != TK_EOS) { /* is there a look-ahead token? */ - t.set( lookahead ); /* use this one */ + t.set(lookahead); /* use this one */ lookahead.token = TK_EOS; /* and discharge it */ } else t.token = llex(t.seminfo); /* read next token */ } void lookahead() { - _assert (lookahead.token == TK_EOS); + _assert(lookahead.token == TK_EOS); lookahead.token = llex(lookahead.seminfo); } // ============================================================= // from lcode.h // ============================================================= - - + // ============================================================= // from lparser.c // ============================================================= @@ -755,23 +733,26 @@ public class LexState extends Constants { 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); } }; - 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; @@ -798,22 +779,22 @@ 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; @@ -822,18 +803,16 @@ public class LexState extends Constants { } }; - /* 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); } @@ -841,8 +820,8 @@ public class LexState extends Constants { /*---------------------------------------------------------------------- name args description ------------------------------------------------------------------------*/ - - void anchor_token () { + + void anchor_token() { /* last token from outer function must be EOS */ _assert(fs != null || t.token == TK_EOS); if (t.token == TK_NAME || t.token == TK_STRING) { @@ -853,8 +832,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,9 +854,9 @@ 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) { @@ -885,15 +864,13 @@ public class LexState extends Constants { 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 +882,7 @@ public class LexState extends Constants { next(); return ts; } - + void codestring(expdesc e, LuaString s) { e.init(VK, fs.stringK(s)); } @@ -914,21 +891,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, 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)); dyd.actvar[dyd.n_actvar++] = new Vardesc(reg); } @@ -939,33 +915,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 +950,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 +962,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 +979,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 +1000,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 +1020,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 +1044,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 +1098,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 +1117,7 @@ public class LexState extends Constants { this.checkname(key); fs.indexed(v, key); } - + void yindex(expdesc v) { /* index -> '[' expr ']' */ this.next(); /* skip the '[' */ @@ -1153,23 +1126,20 @@ 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 */ FuncState fs = this.fs; @@ -1188,17 +1158,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 +1181,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 +1203,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) | (((int) 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 +1279,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 +1292,6 @@ public class LexState extends Constants { return n; } - void funcargs(expdesc f, int line) { FuncState fs = this.fs; expdesc args = new expdesc(); @@ -1353,29 +1322,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 '(': { @@ -1397,10 +1365,9 @@ public class LexState extends Constants { } } - - 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 +1402,7 @@ public class LexState extends Constants { return; } } - } - + } void simpleexp(expdesc v) { /* @@ -1467,8 +1433,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 +1454,6 @@ public class LexState extends Constants { this.next(); } - int getunopr(int op) { switch (op) { case TK_NOT: @@ -1503,7 +1467,6 @@ public class LexState extends Constants { } } - int getbinopr(int op) { switch (op) { case '+': @@ -1551,17 +1514,17 @@ public class LexState extends Constants { 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 +1536,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 +1544,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,36 +1564,35 @@ 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: - return true; - case TK_UNTIL: - return withuntil; - default: return false; + case TK_ELSE: + case TK_ELSEIF: + case TK_END: + case TK_EOS: + return true; + case TK_UNTIL: + return withuntil; + default: + return false; } } - - 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 @@ -1641,73 +1603,67 @@ public class LexState extends Constants { expdesc v = new expdesc(); }; - /* ** check whether, in an assignment to a local variable, the local variable ** is needed in a previous assignment (to a table). If so, save original ** 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 = (short) 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 +1683,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 +1726,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 +1743,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 +1759,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 +1766,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 +1805,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 +1818,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 +1826,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 +1852,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 +1883,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 +1901,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 +1912,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 +1923,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 +1936,6 @@ public class LexState extends Constants { return ismethod; } - void funcstat(int line) { /* funcstat -> FUNCTION funcname body */ boolean needself; @@ -2005,7 +1948,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 +1956,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 +1975,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 +1985,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 +2041,7 @@ public class LexState extends Constants { break; } case TK_RETURN: { /* stat -> retstat */ - next(); /* skip RETURN */ + next(); /* skip RETURN */ this.retstat(); break; } @@ -2114,15 +2055,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 */ @@ -2136,18 +2076,18 @@ public class LexState extends Constants { ** upvalue named LUA_ENV */ public void mainfunc(FuncState funcstate) { - BlockCnt bl = new BlockCnt(); - open_func(funcstate, bl); - fs.f.is_vararg = 1; /* main function is always vararg */ - expdesc v = new expdesc(); - v.init(VLOCAL, 0); /* create and... */ - fs.newupvalue(envn, v); /* ...set environment upvalue */ - next(); /* read first token */ - statlist(); /* parse main body */ - check(TK_EOS); - close_func(); + BlockCnt bl = new BlockCnt(); + open_func(funcstate, bl); + fs.f.is_vararg = 1; /* main function is always vararg */ + expdesc v = new expdesc(); + v.init(VLOCAL, 0); /* create and... */ + fs.newupvalue(envn, v); /* ...set environment upvalue */ + next(); /* read first token */ + statlist(); /* parse main body */ + check(TK_EOS); + close_func(); } - + /* }====================================================================== */ - + } diff --git a/luaj-core/src/main/java/org/luaj/vm2/compiler/LuaC.java b/luaj-core/src/main/java/org/luaj/vm2/compiler/LuaC.java index 1e53636d..0728bade 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/compiler/LuaC.java +++ b/luaj-core/src/main/java/org/luaj/vm2/compiler/LuaC.java @@ -37,30 +37,37 @@ 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: - *

 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * globals.load(new StringReader("print 'hello'"), "main.lua" ).call();
- * } 
+ * 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: + * + *

+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	globals.load(new StringReader("print 'hello'"), "main.lua").call();
+ * }
+ * 
* * To load the LuaC compiler manually, use the install method: - *
 {@code
+ * 
+ * 
+ *  {@code
  * LuaC.install(globals);
- * } 
+ * } + *
* * @see #install(Globals) * @see Globals#compiler @@ -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,8 +97,11 @@ 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 @@ -103,55 +114,57 @@ public class LuaC extends Constants implements Globals.Compiler, Globals.Loader 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. */ public LuaValue load(InputStream stream, String chunkname, Globals globals) throws IOException { return new LuaClosure(compile(stream, chunkname), globals); } static class CompileState { - int nCcalls = 0; + int nCcalls = 0; private 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, (LuaString) LuaValue.valueOf(name)); /* main func. is always vararg */ funcstate.f = new Prototype(); funcstate.f.source = (LuaString) LuaValue.valueOf(name); lexstate.mainfunc(funcstate); - LuaC._assert (funcstate.prev == null); + LuaC._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)); + LuaC._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/luaj-core/src/main/java/org/luaj/vm2/lib/BaseLib.java b/luaj-core/src/main/java/org/luaj/vm2/lib/BaseLib.java index c9f9de40..3c5c2b65 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/lib/BaseLib.java +++ b/luaj-core/src/main/java/org/luaj/vm2/lib/BaseLib.java @@ -34,14 +34,14 @@ import org.luaj.vm2.LuaValue; import org.luaj.vm2.Varargs; /** - * Subclass of {@link LibFunction} which implements the lua basic library functions. + * 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. + * 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 @@ -50,47 +50,60 @@ import org.luaj.vm2.Varargs; * 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
- * Globals globals = JsePlatform.standardGlobals();
- * globals.get("print").call(LuaValue.valueOf("hello, world"));
- * } 
+ * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	globals.get("print").call(LuaValue.valueOf("hello, world"));
+ * }
+ * 
*

- * 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: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JseBaseLib());
- * globals.get("print").call(LuaValue.valueOf("hello, world"));
- * } 
- * Doing so will ensure the library is properly initialized - * and loaded into the globals table. + * 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: + * + *
+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JseBaseLib());
+ * 	globals.get("print").call(LuaValue.valueOf("hello, world"));
+ * }
+ * 
+ * + * 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 + * @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 + 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. + * @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("_G", env); + env.set("_VERSION", Lua._VERSION); env.set("assert", new _assert()); env.set("collectgarbage", new collectgarbage()); env.set("dofile", new dofile()); @@ -115,24 +128,24 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { env.set("next", next = new next()); env.set("pairs", new pairs(next)); env.set("ipairs", new ipairs()); - + return env; } - /** ResourceFinder implementation + /** + * 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); + 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!" ); + if (!args.arg1().toboolean()) + error(args.narg() > 1? args.optjstring(2, "assertion failed!"): "assertion failed!"); return args; } } @@ -141,14 +154,14 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { static final class collectgarbage extends VarArgFunction { public Varargs invoke(Varargs args) { String s = args.optjstring(1, "collect"); - if ( "collect".equals(s) ) { + if ("collect".equals(s)) { System.gc(); return ZERO; - } else if ( "count".equals(s) ) { + } else if ("count".equals(s)) { Runtime rt = Runtime.getRuntime(); - long used = rt.totalMemory() - rt.freeMemory(); + long used = rt.totalMemory()-rt.freeMemory(); return varargsOf(valueOf(used/1024.), valueOf(used%1024)); - } else if ( "step".equals(s) ) { + } else if ("step".equals(s)) { System.gc(); return LuaValue.TRUE; } else { @@ -163,9 +176,8 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { 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 ); + 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(); } } @@ -173,8 +185,10 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { // "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); + 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)); } } @@ -184,23 +198,26 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { 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; + 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() + ")"); + 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); + return loadStream(ld.isstring()? ld.strvalue().toInputStream(): new StringInputStream(ld.checkfunction()), + source, mode, env); } } @@ -211,12 +228,10 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { 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 ); + 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) { @@ -225,12 +240,12 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { globals.debuglib.onCall(this); try { return varargsOf(TRUE, func.invoke(args.subargs(2))); - } catch ( LuaError le ) { + } catch (LuaError le) { final LuaValue m = le.getMessageObject(); - return varargsOf(FALSE, m!=null? m: NIL); - } catch ( Exception e ) { + return varargsOf(FALSE, m != null? m: NIL); + } catch (Exception e) { final String m = e.getMessage(); - return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); + return varargsOf(FALSE, valueOf(m != null? m: e.toString())); } finally { if (globals != null && globals.debuglib != null) globals.debuglib.onReturn(); @@ -241,30 +256,34 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { // "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(); + 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)); } @@ -275,12 +294,12 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { 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) { @@ -291,68 +310,73 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { // "rawset", // (table, index, value) -> table static final class rawset extends TableLibFunction { public LuaValue call(LuaValue table) { - return argerror(2,"value expected"); + return argerror(2, "value expected"); } + public LuaValue call(LuaValue table, LuaValue index) { - return argerror(3,"value expected"); + 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"); + 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("#")) ) + 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); + 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"); + 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() ) + 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 ) + 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() ) + if (!h.isnil()) return h.call(arg); LuaValue v = arg.tostring(); - if ( ! v.isnil() ) + if (!v.isnil()) return v; return valueOf(arg.tojstring()); } @@ -376,12 +400,12 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { globals.debuglib.onCall(this); try { return varargsOf(TRUE, args.arg1().invoke(args.subargs(3))); - } catch ( LuaError le ) { + } catch (LuaError le) { final LuaValue m = le.getMessageObject(); - return varargsOf(FALSE, m!=null? m: NIL); - } catch ( Exception e ) { + return varargsOf(FALSE, m != null? m: NIL); + } catch (Exception e) { final String m = e.getMessage(); - return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); + return varargsOf(FALSE, valueOf(m != null? m: e.toString())); } finally { if (globals != null && globals.debuglib != null) globals.debuglib.onReturn(); @@ -391,56 +415,60 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { } } } - + // "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 ); + 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 ); + 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")); + if (is == null) + return varargsOf(NIL, valueOf("cannot open " + filename + ": No such file or directory")); try { - return loadStream(is, "@"+filename, mode, env); + return loadStream(is, "@" + filename, mode, env); } finally { try { is.close(); - } catch ( Exception e ) { + } catch (Exception e) { e.printStackTrace(); } } @@ -448,28 +476,29 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { public Varargs loadStream(InputStream is, String chunkname, String mode, LuaValue env) { try { - if ( is == null ) - return varargsOf(NIL, valueOf("not found: "+chunkname)); + 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; + byte[] bytes; + int offset, remaining = 0; + StringInputStream(LuaValue func) { this.func = func; } + public int read() throws IOException { - if ( remaining < 0 ) + if (remaining < 0) return -1; - if ( remaining == 0 ) { + if (remaining == 0) { LuaValue s = func.call(); - if ( s.isnil() ) + if (s.isnil()) return remaining = -1; LuaString ls = s.strvalue(); bytes = ls.m_bytes; @@ -479,7 +508,7 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder { return -1; } --remaining; - return 0xFF&bytes[offset++]; + return 0xFF & bytes[offset++]; } } } diff --git a/luaj-core/src/main/java/org/luaj/vm2/lib/Bit32Lib.java b/luaj-core/src/main/java/org/luaj/vm2/lib/Bit32Lib.java index 699c6945..f15c2efc 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/lib/Bit32Lib.java +++ b/luaj-core/src/main/java/org/luaj/vm2/lib/Bit32Lib.java @@ -26,68 +26,86 @@ 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()} - *

 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * System.out.println( globals.get("bit32").get("bnot").call( LuaValue.valueOf(2) ) );
- * } 
+ * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or + * {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()} + * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	System.out.println(globals.get("bit32").get("bnot").call(LuaValue.valueOf(2)));
+ * }
+ * 
*

- * To instantiate and use it directly, - * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JseBaseLib());
- * globals.load(new PackageLib());
- * globals.load(new Bit32Lib());
- * System.out.println( globals.get("bit32").get("bnot").call( LuaValue.valueOf(2) ) );
- * } 
+ * To instantiate and use it directly, link it into your globals table via + * {@link LuaValue#load(LuaValue)} using code such as: + * + *
+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JseBaseLib());
+ * 	globals.load(new PackageLib());
+ * 	globals.load(new Bit32Lib());
+ * 	System.out.println(globals.get("bit32").get("bnot").call(LuaValue.valueOf(2)));
+ * }
+ * 
*

- * 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. */ 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 { 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; } @@ -96,23 +114,28 @@ public class Bit32Lib extends TwoArgFunction { static final class Bit32Lib2 extends TwoArgFunction { 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 +143,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 +153,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 +200,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 +209,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 +220,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 +233,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()} - *

 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * System.out.println( globals.get("coroutine").get("running").call() );
- * } 
+ * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or + * {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()} + * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	System.out.println(globals.get("coroutine").get("running").call());
+ * }
+ * 
*

- * To instantiate and use it directly, - * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JseBaseLib());
- * globals.load(new PackageLib());
- * globals.load(new CoroutineLib());
- * System.out.println( globals.get("coroutine").get("running").call() );
- * } 
+ * To instantiate and use it directly, link it into your globals table via + * {@link LuaValue#load(LuaValue)} using code such as: + * + *
+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JseBaseLib());
+ * 	globals.load(new PackageLib());
+ * 	globals.load(new CoroutineLib());
+ * 	System.out.println(globals.get("coroutine").get("running").call());
+ * }
+ * 
*

+ * * @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. */ public LuaValue call(LuaValue modname, LuaValue env) { globals = env.checkglobals(); @@ -82,7 +97,8 @@ 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; } @@ -95,7 +111,7 @@ public class CoroutineLib extends TwoArgFunction { static final class resume extends VarArgFunction { public Varargs invoke(Varargs args) { final LuaThread t = args.checkthread(1); - return t.resume( args.subargs(2) ); + return t.resume(args.subargs(2)); } } @@ -109,13 +125,13 @@ public class CoroutineLib extends TwoArgFunction { static final class status extends LibFunction { public LuaValue call(LuaValue t) { LuaThread lt = t.checkthread(); - return valueOf( lt.getStatus() ); + return valueOf(lt.getStatus()); } } - + final class yield extends VarArgFunction { public Varargs invoke(Varargs args) { - return globals.yield( args ); + return globals.yield(args); } } @@ -129,15 +145,17 @@ public class CoroutineLib extends TwoArgFunction { static final class wrapper extends VarArgFunction { final LuaThread luathread; + wrapper(LuaThread luathread) { this.luathread = luathread; } + 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/luaj-core/src/main/java/org/luaj/vm2/lib/DebugLib.java b/luaj-core/src/main/java/org/luaj/vm2/lib/DebugLib.java index 167ea36c..959b71e3 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/lib/DebugLib.java +++ b/luaj-core/src/main/java/org/luaj/vm2/lib/DebugLib.java @@ -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()} - *

 {@code
- * Globals globals = JsePlatform.debugGlobals();
- * System.out.println( globals.get("debug").get("traceback").call() );
- * } 
+ * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.debugGlobals();
+ * 	System.out.println(globals.get("debug").get("traceback").call());
+ * }
+ * 
*

- * To instantiate and use it directly, - * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JseBaseLib());
- * globals.load(new PackageLib());
- * globals.load(new DebugLib());
- * System.out.println( globals.get("debug").get("traceback").call() );
- * } 
+ * To instantiate and use it directly, link it into your globals table via + * {@link LuaValue#load(LuaValue)} using code such as: + * + *
+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JseBaseLib());
+ * 	globals.load(new PackageLib());
+ * 	globals.load(new DebugLib());
+ * 	System.out.println(globals.get("debug").get("traceback").call());
+ * }
+ * 
*

- * 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,12 +122,16 @@ 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. */ public LuaValue call(LuaValue modname, LuaValue env) { globals = env.checkglobals(); @@ -135,7 +154,8 @@ 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; } @@ -149,19 +169,17 @@ public class DebugLib extends TwoArgFunction { // debug.gethook ([thread]) final class gethook extends VarArgFunction { 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 { 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 +187,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 +209,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 +217,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 +227,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; } @@ -224,7 +242,7 @@ public class DebugLib extends TwoArgFunction { // debug.getlocal ([thread,] f, local) final class getlocal extends VarArgFunction { 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++); @@ -253,11 +271,11 @@ public class DebugLib extends TwoArgFunction { 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; @@ -270,22 +288,27 @@ public class DebugLib extends TwoArgFunction { return u.isuserdata()? u: NIL; } } - - + // debug.sethook ([thread,] hook, mask [, count]) final class sethook extends VarArgFunction { 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()); } } @@ -402,29 +438,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 +475,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 +504,7 @@ public class DebugLib extends TwoArgFunction { s.inhook = false; } } - + CallStack callstack() { return callstack(globals.running); } @@ -471,27 +516,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 +547,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 +572,7 @@ public class DebugLib extends TwoArgFunction { } return frame[calls++]; } - + final synchronized void onCall(LuaFunction function) { pushcall().set(function); } @@ -535,12 +580,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 +593,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 +639,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; @@ -651,27 +696,32 @@ public class DebugLib extends TwoArgFunction { public static class CallFrame { LuaFunction f; - int pc; - int top; - Varargs v; - LuaValue[] stack; - CallFrame previous; + int pc; + int top; + Varargs v; + LuaValue[] stack; + 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; } + void instr(int pc, Varargs v, int top) { this.pc = pc; this.v = v; @@ -679,57 +729,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 +806,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 +886,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 +919,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/luaj-core/src/main/java/org/luaj/vm2/lib/IoLib.java b/luaj-core/src/main/java/org/luaj/vm2/lib/IoLib.java index 13f6f986..26c81b88 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/lib/IoLib.java +++ b/luaj-core/src/main/java/org/luaj/vm2/lib/IoLib.java @@ -32,77 +32,100 @@ 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()} - *

 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
- * } 
- * 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()} + * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
+ * }
+ * 
+ * + * 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: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JseBaseLib());
- * globals.load(new PackageLib());
- * globals.load(new OsLib());
- * globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
- * } 
+ * To instantiate and use it directly, link it into your globals table via + * {@link LuaValue#load(LuaValue)} using code such as: + * + *
+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JseBaseLib());
+ * 	globals.load(new PackageLib());
+ * 	globals.load(new OsLib());
+ * 	globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
+ * }
+ * 
*

- * 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 { +abstract public class IoLib extends TwoArgFunction { + + abstract protected class File extends LuaValue { + abstract public void write(LuaString string) throws IOException; - 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); + // get length remaining to read abstract public int remaining() throws IOException; + // peek ahead one character abstract public int peek() throws IOException, EOFException; + // return char if read, -1 if eof, throw IOException on other exception abstract public 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 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 ) { + public LuaValue get(LuaValue key) { return filemethods.get(key); } @@ -110,35 +133,38 @@ public class IoLib extends TwoArgFunction { public int type() { return LuaValue.TUSERDATA; } + public String typename() { return "userdata"; } - + // displays as "file" type public String tojstring() { return "file: " + Integer.toHexString(hashCode()); } - + 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 +172,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 +210,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,103 +227,88 @@ 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; - + 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 +399,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 +432,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 +440,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 +468,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 +479,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 +490,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 +548,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 +630,115 @@ 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) + continue; + if (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/luaj-core/src/main/java/org/luaj/vm2/lib/LibFunction.java b/luaj-core/src/main/java/org/luaj/vm2/lib/LibFunction.java index eba56072..26db9962 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/lib/LibFunction.java +++ b/luaj-core/src/main/java/org/luaj/vm2/lib/LibFunction.java @@ -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. *

    *
  • {@link ZeroArgFunction}
  • *
  • {@link OneArgFunction}
  • @@ -51,13 +51,15 @@ import org.luaj.vm2.Varargs; *
  • {@link VarArgFunction}
  • *
*

- * 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": -

 {@code
+ * 
+ * 
+ *  {@code
  * import org.luaj.vm2.LuaValue;
  * import org.luaj.vm2.lib.*;
  * 
@@ -85,18 +87,22 @@ import org.luaj.vm2.Varargs;
  *		}
  *	}
  *}
- *}
- * 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,147 @@ import org.luaj.vm2.Varargs;
  * end
  * print( 'sinh(.5)', hyperbolic.sinh(.5) )
  * print( 'cosh(.5)', hyperbolic.cosh(.5) )
- * }
+ * } + *
*

* It should produce something like: - *

 {@code
+ * 
+ * 
+ *  {@code
  * t	table: 3dbbd23f
  * hyperbolic	table: 3dbbd23f
  * k,v	cosh	function: 3dbbd128
  * k,v	sinh	function: 3dbbd242
  * sinh(.5)	0.5210953
  * cosh(.5)	1.127626
- * }
+ * } + *
*

- * 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() { } - + 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: *

    *
  • acos
  • *
  • asin
  • @@ -48,60 +48,81 @@ import org.luaj.vm2.Varargs; *
*

* 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()} - *

 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * System.out.println( globals.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
- * } 
- * 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. + * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	System.out.println(globals.get("math").get("sqrt").call(LuaValue.valueOf(2)));
+ * }
+ * 
+ * + * 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: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JseBaseLib());
- * globals.load(new PackageLib());
- * globals.load(new MathLib());
- * System.out.println( globals.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
- * } 
- * 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: + * + *
+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JseBaseLib());
+ * 	globals.load(new PackageLib());
+ * 	globals.load(new MathLib());
+ * 	System.out.println(globals.get("math").get("sqrt").call(LuaValue.valueOf(2)));
+ * }
+ * 
+ * + * 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. */ 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 +131,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,14 +146,16 @@ 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 { public LuaValue call(LuaValue arg) { return valueOf(call(arg.checkdouble())); } + abstract protected double call(double d); } @@ -140,43 +163,74 @@ public class MathLib extends TwoArgFunction { 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 { + 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 exp extends UnaryOp { final MathLib mathlib; + exp(MathLib mathlib) { this.mathlib = mathlib; } + 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 { public LuaValue call(LuaValue xv, LuaValue yv) { 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 { 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 { protected double call(double x, double y) { return MathLib.dpow_default(x, y); @@ -186,117 +240,127 @@ public class MathLib extends TwoArgFunction { static class frexp extends VarArgFunction { 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 { public Varargs invoke(Varargs args) { LuaValue m = args.checkvalue(1); - for ( int i=2,n=args.narg(); i<=n; ++i ) { + for (int i = 2, n = args.narg(); i <= n; ++i) { LuaValue v = args.checkvalue(i); - if (m.lt_b(v)) m = v; + if (m.lt_b(v)) + m = v; } return m; } } - + static class min extends VarArgFunction { public Varargs invoke(Varargs args) { LuaValue m = args.checkvalue(1); - for ( int i=2,n=args.narg(); i<=n; ++i ) { + for (int i = 2, n = args.narg(); i <= n; ++i) { LuaValue v = args.checkvalue(i); - if (v.lt_b(m)) m = v; + if (v.lt_b(m)) + m = v; } return m; } } - + static class modf extends VarArgFunction { 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, 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(); + public LuaValue call() { - return valueOf( random.nextDouble() ); + return valueOf(random.nextDouble()); } + 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)); } + 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/luaj-core/src/main/java/org/luaj/vm2/lib/OneArgFunction.java b/luaj-core/src/main/java/org/luaj/vm2/lib/OneArgFunction.java index 3db6a321..8271ddfc 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/lib/OneArgFunction.java +++ b/luaj-core/src/main/java/org/luaj/vm2/lib/OneArgFunction.java @@ -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 @@ -49,11 +51,11 @@ import org.luaj.vm2.Varargs; abstract public class OneArgFunction extends LibFunction { abstract public LuaValue call(LuaValue arg); - + /** Default constructor */ public OneArgFunction() { } - + public final LuaValue call() { return call(NIL); } @@ -69,4 +71,4 @@ abstract public class OneArgFunction extends LibFunction { 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 index 85b8677e..7666a307 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/lib/OsLib.java +++ b/luaj-core/src/main/java/org/luaj/vm2/lib/OsLib.java @@ -32,21 +32,21 @@ import org.luaj.vm2.LuaValue; import org.luaj.vm2.Varargs; /** - * Subclass of {@link LibFunction} which implements the standard lua {@code os} library. + * 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. + * 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. + * 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. + * 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: + * The following functions have limited implementations of features that are not + * supported well on Jme: *

    *
  • {@code execute()}
  • *
  • {@code remove()}
  • @@ -55,33 +55,46 @@ import org.luaj.vm2.Varargs; *
*

* 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
- * Globals globals = JsePlatform.standardGlobals();
- * System.out.println( globals.get("os").get("time").call() );
- * } 
- * 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. + * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or + * {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()} + * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	System.out.println(globals.get("os").get("time").call());
+ * }
+ * 
+ * + * 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: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JseBaseLib());
- * globals.load(new PackageLib());
- * globals.load(new OsLib());
- * System.out.println( globals.get("os").get("time").call() );
- * } 
+ * To instantiate and use it directly, link it into your globals table via + * {@link LuaValue#load(LuaValue)} using code such as: + * + *
+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JseBaseLib());
+ * 	globals.load(new PackageLib());
+ * 	globals.load(new OsLib());
+ * 	System.out.println(globals.get("os").get("time").call());
+ * }
+ * 
*

- * @see LibFunction + * + * @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 + * @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"; + 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; @@ -95,36 +108,29 @@ public class OsLib extends TwoArgFunction { 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; + 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. + + /** + * 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. */ public LuaValue call(LuaValue modname, LuaValue env) { globals = env.checkglobals(); @@ -132,7 +138,8 @@ public class OsLib extends TwoArgFunction { 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); + if (!env.get("package").isnil()) + env.get("package").get("loaded").set("os", os); return os; } @@ -141,9 +148,10 @@ public class OsLib extends TwoArgFunction { this.opcode = opcode; this.name = name; } + public Varargs invoke(Varargs args) { try { - switch ( opcode ) { + switch (opcode) { case CLOCK: return valueOf(clock()); case DATE: { @@ -151,7 +159,7 @@ public class OsLib extends TwoArgFunction { double t = args.isnumber(2)? args.todouble(2): time(null); if (s.equals("*t")) { Calendar d = Calendar.getInstance(); - d.setTime(new Date((long)(t*1000))); + d.setTime(new Date((long) (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)); @@ -164,10 +172,10 @@ public class OsLib extends TwoArgFunction { tbl.set("isdst", LuaValue.valueOf(isDaylightSavingsTime(d))); return tbl; } - return valueOf( date(s, t==-1? time(null): t) ); + return valueOf(date(s, t == -1? time(null): t)); } case DIFFTIME: - return valueOf(difftime(args.checkdouble(1),args.checkdouble(2))); + return valueOf(difftime(args.checkdouble(1), args.checkdouble(2))); case EXECUTE: return execute(args.optjstring(1, null)); case EXIT: @@ -175,7 +183,7 @@ public class OsLib extends TwoArgFunction { return NONE; case GETENV: { final String val = getenv(args.checkjstring(1)); - return val!=null? valueOf(val): NIL; + return val != null? valueOf(val): NIL; } case REMOVE: remove(args.checkjstring(1)); @@ -184,8 +192,8 @@ public class OsLib extends TwoArgFunction { 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; + 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))); @@ -193,78 +201,79 @@ public class OsLib extends TwoArgFunction { return valueOf(tmpname()); } return NONE; - } catch ( IOException e ) { + } 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. + * @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.; + 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. + * 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; + 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. + * 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. + * 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")). + * 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 time 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. + * @param time 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. */ public String date(String format, double time) { Calendar d = Calendar.getInstance(); - d.setTime(new Date((long)(time*1000))); + d.setTime(new Date((long) (time*1000))); if (format.startsWith("!")) { time -= timeZoneOffset(d); - d.setTime(new Date((long)(time*1000))); + d.setTime(new Date((long) (time*1000))); format = format.substring(1); } byte[] fmt = format.getBytes(); final int n = fmt.length; Buffer result = new Buffer(n); byte c; - for ( int i = 0; i < n; ) { - switch ( c = fmt[i++ ] ) { + for (int i = 0; i < n;) { + switch (c = fmt[i++]) { case '\n': - result.append( "\n" ); + result.append("\n"); break; default: - result.append( c ); + result.append(c); break; case '%': - if (i >= n) break; - switch ( c = fmt[i++ ] ) { + if (i >= n) + break; + switch (c = fmt[i++]) { default: - LuaValue.argerror(1, "invalid conversion specifier '%"+c+"'"); + LuaValue.argerror(1, "invalid conversion specifier '%" + c + "'"); break; case '%': - result.append( (byte)'%' ); + result.append((byte) '%'); break; case 'a': result.append(WeekdayNameAbbrev[d.get(Calendar.DAY_OF_WEEK)-1]); @@ -292,7 +301,7 @@ public class OsLib extends TwoArgFunction { break; case 'j': { // day of year. Calendar y0 = beginningOfYear(d); - int dayOfYear = (int) ((d.getTime().getTime() - y0.getTime().getTime()) / (24 * 3600L * 1000L)); + int dayOfYear = (int) ((d.getTime().getTime()-y0.getTime().getTime())/(24*3600L*1000L)); result.append(String.valueOf(1001+dayOfYear).substring(1)); break; } @@ -330,11 +339,11 @@ public class OsLib extends TwoArgFunction { result.append(String.valueOf(d.get(Calendar.YEAR))); break; case 'z': { - final int tzo = timeZoneOffset(d) / 60; + 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); - result.append((tzo>=0? "+": "-") + h + m); + final String h = String.valueOf(100+a/60).substring(1); + final String m = String.valueOf(100+a%60).substring(1); + result.append((tzo >= 0? "+": "-")+h+m); break; } } @@ -342,11 +351,14 @@ public class OsLib extends TwoArgFunction { } 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 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 Calendar beginningOfYear(Calendar d) { Calendar y0 = Calendar.getInstance(); @@ -359,42 +371,35 @@ public class OsLib extends TwoArgFunction { y0.set(Calendar.MILLISECOND, 0); return y0; } - + private 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); + 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); + 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)); + long dt = d.getTime().getTime()-y0.getTime().getTime(); + return 1+(int) (dt/(7L*24L*3600L*1000L)); } - + private 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; + 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; + 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. + * 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) { @@ -402,7 +407,9 @@ public class OsLib extends TwoArgFunction { } /** - * Calls the C function exit, with an optional code, to terminate the host program. + * Calls the C function exit, with an optional code, to terminate the host + * program. + * * @param code */ protected void exit(int code) { @@ -410,19 +417,19 @@ public class OsLib extends TwoArgFunction { } /** - * 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. + * 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 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. + * 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'. * - * A SecurityException may be thrown if access is not allowed - * for 'varname'. * @param varname * @return String value, or null if not defined */ @@ -431,57 +438,57 @@ public class OsLib extends TwoArgFunction { } /** - * Deletes the file or directory with the given name. - * Directories must be empty to be removed. - * If this function fails, it throws and IOException + * 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" ); + throw new IOException("not implemented"); } /** - * Renames file or directory named oldname to newname. - * If this function fails,it throws and IOException + * 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" ); + 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". + * 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. + * 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. + * 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. + * @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). + * 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 */ @@ -500,7 +507,7 @@ public class OsLib extends TwoArgFunction { c.set(Calendar.MILLISECOND, 0); d = c.getTime(); } - return d.getTime() / 1000.; + return d.getTime()/1000.; } /** @@ -508,16 +515,16 @@ public class OsLib extends TwoArgFunction { * 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). + * 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 ) { + synchronized (OsLib.class) { return TMP_PREFIX+(tmpnames++)+TMP_SUFFIX; } } diff --git a/luaj-core/src/main/java/org/luaj/vm2/lib/PackageLib.java b/luaj-core/src/main/java/org/luaj/vm2/lib/PackageLib.java index 4c2147c9..e5450cf1 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/lib/PackageLib.java +++ b/luaj-core/src/main/java/org/luaj/vm2/lib/PackageLib.java @@ -31,56 +31,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. + * 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: + *

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.preload" Lua table of uninitialized preload + * functions. + *
  • "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()} + * + *
+ *  {@code
  * Globals globals = JsePlatform.standardGlobals();
  * System.out.println( globals.get("require").call"foo") );
- * } 
+ * } + *
*

- * To instantiate and use it directly, - * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JseBaseLib());
- * globals.load(new PackageLib());
- * System.out.println( globals.get("require").call("foo") );
- * } 
- *

Limitations

- * 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: + * + *
+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JseBaseLib());
+ * 	globals.load(new PackageLib());
+ * 	System.out.println(globals.get("require").call("foo"));
+ * }
+ * 
+ * + *

Limitations

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,40 +112,49 @@ 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"); + /** 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 LuaString _SENTINEL = valueOf("\u0001"); + private static final String FILE_SEP = System.getProperty("file.separator"); 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. */ public LuaValue call(LuaValue modname, LuaValue env) { globals = env.checkglobals(); @@ -141,8 +167,8 @@ public class PackageLib extends TwoArgFunction { package_.set(_SEARCHPATH, new searchpath()); 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,94 +176,100 @@ 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)); } - + 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. + * 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. + * 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. + * 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]. + * 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. + * 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 ) { + 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 ) { + public Varargs invoke(Varargs args) { args.checkstring(1); return varargsOf(NIL, valueOf("dynamic libraries not enabled"), valueOf("absent")); } @@ -247,36 +279,34 @@ public class PackageLib extends TwoArgFunction { 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 { 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())); } } @@ -286,90 +316,91 @@ public class PackageLib extends TwoArgFunction { 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 java_searcher extends VarArgFunction { 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/luaj-core/src/main/java/org/luaj/vm2/lib/ResourceFinder.java b/luaj-core/src/main/java/org/luaj/vm2/lib/ResourceFinder.java index 3a7b38a6..f67c1b8b 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/lib/ResourceFinder.java +++ b/luaj-core/src/main/java/org/luaj/vm2/lib/ResourceFinder.java @@ -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 + public InputStream findResource(String filename); +} diff --git a/luaj-core/src/main/java/org/luaj/vm2/lib/StringLib.java b/luaj-core/src/main/java/org/luaj/vm2/lib/StringLib.java index 8011459a..c49f741f 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/lib/StringLib.java +++ b/luaj-core/src/main/java/org/luaj/vm2/lib/StringLib.java @@ -33,53 +33,70 @@ import org.luaj.vm2.Varargs; import org.luaj.vm2.compiler.DumpState; /** - * Subclass of {@link LibFunction} which implements the lua standard {@code string} - * library. + * Subclass of {@link LibFunction} which implements the lua standard + * {@code string} 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()} - *

 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * System.out.println( globals.get("string").get("upper").call( LuaValue.valueOf("abcde") ) );
- * } 
+ * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or + * {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()} + * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	System.out.println(globals.get("string").get("upper").call(LuaValue.valueOf("abcde")));
+ * }
+ * 
*

- * To instantiate and use it directly, - * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JseBaseLib());
- * globals.load(new PackageLib());
- * globals.load(new JseStringLib());
- * System.out.println( globals.get("string").get("upper").call( LuaValue.valueOf("abcde") ) );
- * } 
+ * To instantiate and use it directly, link it into your globals table via + * {@link LuaValue#load(LuaValue)} using code such as: + * + *
+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JseBaseLib());
+ * 	globals.load(new PackageLib());
+ * 	globals.load(new JseStringLib());
+ * 	System.out.println(globals.get("string").get("upper").call(LuaValue.valueOf("abcde")));
+ * }
+ * 
*

* This is a direct port of 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 String Lib Reference + * @see Lua 5.2 String + * Lib Reference */ public class StringLib extends TwoArgFunction { - /** Construct a StringLib, which can be initialized by calling it with a + /** + * Construct a StringLib, 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 StringLib() { } - /** 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. - * Creates a metatable that uses __INDEX to fall back on itself to support string - * method operations. - * If the shared strings metatable instance is null, will set the metatable as - * the global shared metatable for strings. + /** + * 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. Creates a metatable that uses __INDEX to fall back on + * itself to support string method operations. If the shared strings + * metatable instance is null, will set the metatable as the global shared + * metatable for strings. *

- * All tables and metatables are read-write by default so if this will be used in - * a server environment, sandboxing should be used. In particular, the - * {@link LuaString#s_metatable} table should probably be made read-only. + * All tables and metatables are read-write by default so if this will be + * used in a server environment, sandboxing should be used. In particular, + * the {@link LuaString#s_metatable} table should probably be made + * read-only. + * * @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. */ public LuaValue call(LuaValue modname, LuaValue env) { LuaTable string = new LuaTable(); @@ -97,21 +114,21 @@ public class StringLib extends TwoArgFunction { string.set("reverse", new reverse()); string.set("sub", new sub()); string.set("upper", new upper()); - + env.set("string", string); - if (!env.get("package").isnil()) env.get("package").get("loaded").set("string", string); + if (!env.get("package").isnil()) + env.get("package").get("loaded").set("string", string); if (LuaString.s_metatable == null) { LuaString.s_metatable = LuaValue.tableOf(new LuaValue[] { INDEX, string }); } return string; } - + /** * string.byte (s [, i [, j]]) * - * Returns the internal numerical codes of the - * characters s[i], s[i+1], ..., s[j]. The default value for i is 1; the - * default value for j is i. + * Returns the internal numerical codes of the characters s[i], s[i+1], ..., + * s[j]. The default value for i is 1; the default value for j is i. * * Note that numerical codes are not necessarily portable across platforms. * @@ -121,17 +138,20 @@ public class StringLib extends TwoArgFunction { public Varargs invoke(Varargs args) { LuaString s = args.checkstring(1); int l = s.m_length; - int posi = posrelat( args.optint(2,1), l ); - int pose = posrelat( args.optint(3,posi), l ); - int n,i; - if (posi <= 0) posi = 1; - if (pose > l) pose = l; - if (posi > pose) return NONE; /* empty interval; return no values */ - n = (int)(pose - posi + 1); - if (posi + n <= pose) /* overflow? */ - error("string slice too long"); + int posi = posrelat(args.optint(2, 1), l); + int pose = posrelat(args.optint(3, posi), l); + int n, i; + if (posi <= 0) + posi = 1; + if (pose > l) + pose = l; + if (posi > pose) + return NONE; /* empty interval; return no values */ + n = (int) (pose-posi+1); + if (posi+n <= pose) /* overflow? */ + error("string slice too long"); LuaValue[] v = new LuaValue[n]; - for (i=0; i=256) argerror(a, "invalid value for string.char [0; 255]: " + c); + if (c < 0 || c >= 256) + argerror(a, "invalid value for string.char [0; 255]: " + c); bytes[i] = (byte) c; } - return LuaString.valueUsing( bytes ); + return LuaString.valueUsing(bytes); } } - + /** * string.dump (function[, stripDebug]) * - * Returns a string containing a binary representation of the given function, - * so that a later loadstring on this string returns a copy of the function. - * function must be a Lua function without upvalues. - * Boolean param stripDebug - true to strip debugging info, false otherwise. - * The default value for stripDebug is true. + * Returns a string containing a binary representation of the given + * function, so that a later loadstring on this string returns a copy of the + * function. function must be a Lua function without upvalues. Boolean param + * stripDebug - true to strip debugging info, false otherwise. The default + * value for stripDebug is true. * * TODO: port dumping code as optional add-on */ @@ -177,10 +198,10 @@ public class StringLib extends TwoArgFunction { LuaValue f = args.checkfunction(1); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { - DumpState.dump( ((LuaClosure)f).p, baos, args.optboolean(2, true) ); + DumpState.dump(((LuaClosure) f).p, baos, args.optboolean(2, true)); return LuaString.valueUsing(baos.toByteArray()); } catch (IOException e) { - return error( e.getMessage() ); + return error(e.getMessage()); } } } @@ -188,22 +209,21 @@ public class StringLib extends TwoArgFunction { /** * string.find (s, pattern [, init [, plain]]) * - * Looks for the first match of pattern in the string s. - * If it finds a match, then find returns the indices of s - * where this occurrence starts and ends; otherwise, it returns nil. - * A third, optional numerical argument init specifies where to start the search; - * its default value is 1 and may be negative. A value of true as a fourth, - * optional argument plain turns off the pattern matching facilities, - * so the function does a plain "find substring" operation, - * with no characters in pattern being considered "magic". - * Note that if plain is given, then init must be given as well. + * Looks for the first match of pattern in the string s. If it finds a + * match, then find returns the indices of s where this occurrence starts + * and ends; otherwise, it returns nil. A third, optional numerical argument + * init specifies where to start the search; its default value is 1 and may + * be negative. A value of true as a fourth, optional argument plain turns + * off the pattern matching facilities, so the function does a plain "find + * substring" operation, with no characters in pattern being considered + * "magic". Note that if plain is given, then init must be given as well. * - * If the pattern has captures, then in a successful match the captured values - * are also returned, after the two indices. + * If the pattern has captures, then in a successful match the captured + * values are also returned, after the two indices. */ static final class find extends VarArgFunction { public Varargs invoke(Varargs args) { - return str_find_aux( args, true ); + return str_find_aux(args, true); } } @@ -211,113 +231,115 @@ public class StringLib extends TwoArgFunction { * string.format (formatstring, ...) * * Returns a formatted version of its variable number of arguments following - * the description given in its first argument (which must be a string). - * The format string follows the same rules as the printf family of standard C functions. - * The only differences are that the options/modifiers *, l, L, n, p, and h are not supported - * and that there is an extra option, q. The q option formats a string in a form suitable - * to be safely read back by the Lua interpreter: the string is written between double quotes, - * and all double quotes, newlines, embedded zeros, and backslashes in the string are correctly - * escaped when written. For instance, the call - * string.format('%q', 'a string with "quotes" and \n new line') + * the description given in its first argument (which must be a string). The + * format string follows the same rules as the printf family of standard C + * functions. The only differences are that the options/modifiers *, l, L, + * n, p, and h are not supported and that there is an extra option, q. The q + * option formats a string in a form suitable to be safely read back by the + * Lua interpreter: the string is written between double quotes, and all + * double quotes, newlines, embedded zeros, and backslashes in the string + * are correctly escaped when written. For instance, the call + * string.format('%q', 'a string with "quotes" and \n new line') * - * will produce the string: - * "a string with \"quotes\" and \ - * new line" + * will produce the string: "a string with \"quotes\" and \ new line" * - * The options c, d, E, e, f, g, G, i, o, u, X, and x all expect a number as argument, - * whereas q and s expect a string. + * The options c, d, E, e, f, g, G, i, o, u, X, and x all expect a number as + * argument, whereas q and s expect a string. * * This function does not accept string values containing embedded zeros, * except as arguments to the q option. */ final class format extends VarArgFunction { public Varargs invoke(Varargs args) { - LuaString fmt = args.checkstring( 1 ); + LuaString fmt = args.checkstring(1); final int n = fmt.length(); Buffer result = new Buffer(n); int arg = 1; int c; - - for ( int i = 0; i < n; ) { - switch ( c = fmt.luaByte( i++ ) ) { + + for (int i = 0; i < n;) { + switch (c = fmt.luaByte(i++)) { case '\n': - result.append( "\n" ); + result.append("\n"); break; default: - result.append( (byte) c ); + result.append((byte) c); break; case L_ESC: - if ( i < n ) { - if ( ( c = fmt.luaByte( i ) ) == L_ESC ) { + if (i < n) { + if ((c = fmt.luaByte(i)) == L_ESC) { ++i; - result.append( (byte)L_ESC ); + result.append((byte) L_ESC); } else { arg++; - FormatDesc fdsc = new FormatDesc(args, fmt, i ); + FormatDesc fdsc = new FormatDesc(args, fmt, i); i += fdsc.length; - switch ( fdsc.conversion ) { + switch (fdsc.conversion) { case 'c': - fdsc.format( result, (byte)args.checkint( arg ) ); + fdsc.format(result, (byte) args.checkint(arg)); break; case 'i': case 'd': - fdsc.format( result, args.checklong( arg ) ); + fdsc.format(result, args.checklong(arg)); break; case 'o': case 'u': case 'x': case 'X': - fdsc.format( result, args.checklong( arg ) ); + fdsc.format(result, args.checklong(arg)); break; case 'e': case 'E': case 'f': case 'g': case 'G': - fdsc.format( result, args.checkdouble( arg ) ); + fdsc.format(result, args.checkdouble(arg)); break; case 'q': - addquoted( result, args.checkstring( arg ) ); + addquoted(result, args.checkstring(arg)); break; case 's': { - LuaString s = args.checkstring( arg ); - if ( fdsc.precision == -1 && s.length() >= 100 ) { - result.append( s ); + LuaString s = args.checkstring(arg); + if (fdsc.precision == -1 && s.length() >= 100) { + result.append(s); } else { - fdsc.format( result, s ); + fdsc.format(result, s); } - } break; + } + break; default: - error("invalid option '%"+(char)fdsc.conversion+"' to 'format'"); + error("invalid option '%" + (char) fdsc.conversion + "' to 'format'"); break; } } } } } - + return result.tostring(); } } - + static void addquoted(Buffer buf, LuaString s) { int c; - buf.append( (byte) '"' ); - for ( int i = 0, n = s.length(); i < n; i++ ) { - switch ( c = s.luaByte( i ) ) { - case '"': case '\\': case '\n': - buf.append( (byte)'\\' ); - buf.append( (byte)c ); + buf.append((byte) '"'); + for (int i = 0, n = s.length(); i < n; i++) { + switch (c = s.luaByte(i)) { + case '"': + case '\\': + case '\n': + buf.append((byte) '\\'); + buf.append((byte) c); break; default: if (c <= 0x1F || c == 0x7F) { - buf.append( (byte) '\\' ); + buf.append((byte) '\\'); if (i+1 == n || s.luaByte(i+1) < '0' || s.luaByte(i+1) > '9') { buf.append(Integer.toString(c)); } else { - buf.append( (byte) '0' ); - buf.append( (byte) (char) ('0' + c / 10) ); - buf.append( (byte) (char) ('0' + c % 10) ); + buf.append((byte) '0'); + buf.append((byte) (char) ('0'+c/10)); + buf.append((byte) (char) ('0'+c%10)); } } else { buf.append((byte) c); @@ -325,91 +347,103 @@ public class StringLib extends TwoArgFunction { break; } } - buf.append( (byte) '"' ); + buf.append((byte) '"'); } - + private static final String FLAGS = "-+ #0"; - + class FormatDesc { - - private boolean leftAdjust; - private boolean zeroPad; - private boolean explicitPlus; - private boolean space; - private boolean alternateForm; + + private boolean leftAdjust; + private boolean zeroPad; + private boolean explicitPlus; + private boolean space; + private boolean alternateForm; private static final int MAX_FLAGS = 5; - + private int width; - int precision; - + int precision; + public final int conversion; public final int length; - + public final String src; - + public FormatDesc(Varargs args, LuaString strfrmt, final int start) { int p = start, n = strfrmt.length(); int c = 0; - + boolean moreFlags = true; while ( moreFlags ) { - switch ( c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ) ) { - case '-': leftAdjust = true; break; - case '+': explicitPlus = true; break; - case ' ': space = true; break; - case '#': alternateForm = true; break; - case '0': zeroPad = true; break; - default: moreFlags = false; break; + switch (c = ((p < n)? strfrmt.luaByte(p++): 0)) { + case '-': + leftAdjust = true; + break; + case '+': + explicitPlus = true; + break; + case ' ': + space = true; + break; + case '#': + alternateForm = true; + break; + case '0': + zeroPad = true; + break; + default: + moreFlags = false; + break; } } - if ( p - start > MAX_FLAGS ) + if (p-start > MAX_FLAGS) error("invalid format (repeated flags)"); - + width = -1; - if ( Character.isDigit( (char)c ) ) { - width = c - '0'; - c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ); - if ( Character.isDigit( (char) c ) ) { - width = width * 10 + (c - '0'); - c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ); + if (Character.isDigit((char) c)) { + width = c-'0'; + c = ((p < n)? strfrmt.luaByte(p++): 0); + if (Character.isDigit((char) c)) { + width = width*10+(c-'0'); + c = ((p < n)? strfrmt.luaByte(p++): 0); } } - + precision = -1; - if ( c == '.' ) { - c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ); - if ( Character.isDigit( (char) c ) ) { - precision = c - '0'; - c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ); - if ( Character.isDigit( (char) c ) ) { - precision = precision * 10 + (c - '0'); - c = ( (p < n) ? strfrmt.luaByte( p++ ) : 0 ); + if (c == '.') { + c = ((p < n)? strfrmt.luaByte(p++): 0); + if (Character.isDigit((char) c)) { + precision = c-'0'; + c = ((p < n)? strfrmt.luaByte(p++): 0); + if (Character.isDigit((char) c)) { + precision = precision*10+(c-'0'); + c = ((p < n)? strfrmt.luaByte(p++): 0); } } } - - if ( Character.isDigit( (char) c ) ) + + if (Character.isDigit((char) c)) error("invalid format (width or precision too long)"); - + zeroPad &= !leftAdjust; // '-' overrides '0' conversion = c; - length = p - start; - src = strfrmt.substring(start - 1, p).tojstring(); + 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. buf.append(c); } - + public void format(Buffer buf, long number) { String digits; - - if ( number == 0 && precision == 0 ) { + + if (number == 0 && precision == 0) { digits = ""; } else { int radix; - switch ( conversion ) { + switch (conversion) { case 'x': case 'X': radix = 16; @@ -421,217 +455,213 @@ public class StringLib extends TwoArgFunction { radix = 10; break; } - digits = Long.toString( number, radix ); - if ( conversion == 'X' ) + digits = Long.toString(number, radix); + if (conversion == 'X') digits = digits.toUpperCase(); } - + int minwidth = digits.length(); int ndigits = minwidth; int nzeros; - - if ( number < 0 ) { + + if (number < 0) { ndigits--; - } else if ( explicitPlus || space ) { + } else if (explicitPlus || space) { minwidth++; } - - if ( precision > ndigits ) - nzeros = precision - ndigits; - else if ( precision == -1 && zeroPad && width > minwidth ) - nzeros = width - minwidth; + + if (precision > ndigits) + nzeros = precision-ndigits; + else if (precision == -1 && zeroPad && width > minwidth) + nzeros = width-minwidth; else nzeros = 0; - + minwidth += nzeros; - int nspaces = width > minwidth ? width - minwidth : 0; - - if ( !leftAdjust ) - pad( buf, ' ', nspaces ); - - if ( number < 0 ) { - if ( nzeros > 0 ) { - buf.append( (byte)'-' ); - digits = digits.substring( 1 ); + int nspaces = width > minwidth? width-minwidth: 0; + + if (!leftAdjust) + pad(buf, ' ', nspaces); + + if (number < 0) { + if (nzeros > 0) { + buf.append((byte) '-'); + digits = digits.substring(1); } - } else if ( explicitPlus ) { - buf.append( (byte)'+' ); - } else if ( space ) { - buf.append( (byte)' ' ); + } else if (explicitPlus) { + buf.append((byte) '+'); + } else if (space) { + buf.append((byte) ' '); } - - if ( nzeros > 0 ) - pad( buf, '0', nzeros ); - - buf.append( digits ); - - if ( leftAdjust ) - pad( buf, ' ', nspaces ); + + if (nzeros > 0) + pad(buf, '0', nzeros); + + buf.append(digits); + + if (leftAdjust) + pad(buf, ' ', nspaces); } - + public void format(Buffer buf, double x) { - buf.append( StringLib.this.format(src, x) ); + buf.append(StringLib.this.format(src, x)); } - + public void format(Buffer buf, LuaString s) { - int nullindex = s.indexOf( (byte)'\0', 0 ); - if ( nullindex != -1 ) - s = s.substring( 0, nullindex ); + int nullindex = s.indexOf((byte) '\0', 0); + if (nullindex != -1) + s = s.substring(0, nullindex); buf.append(s); } - + public final void pad(Buffer buf, char c, int n) { - byte b = (byte)c; + byte b = (byte) c; while ( n-- > 0 ) buf.append(b); } } - + protected String format(String src, double x) { return String.valueOf(x); } - + /** * string.gmatch (s, pattern) * - * Returns an iterator function that, each time it is called, returns the next captures - * from pattern over string s. If pattern specifies no captures, then the - * whole match is produced in each call. + * Returns an iterator function that, each time it is called, returns the + * next captures from pattern over string s. If pattern specifies no + * captures, then the whole match is produced in each call. * - * As an example, the following loop - * s = "hello world from Lua" - * for w in string.gmatch(s, "%a+") do - * print(w) - * end + * As an example, the following loop s = "hello world from Lua" for w in + * string.gmatch(s, "%a+") do print(w) end * - * will iterate over all the words from string s, printing one per line. - * The next example collects all pairs key=value from the given string into a table: - * t = {} - * s = "from=world, to=Lua" - * for k, v in string.gmatch(s, "(%w+)=(%w+)") do - * t[k] = v - * end + * will iterate over all the words from string s, printing one per line. The + * next example collects all pairs key=value from the given string into a + * table: t = {} s = "from=world, to=Lua" for k, v in string.gmatch(s, + * "(%w+)=(%w+)") do t[k] = v end * - * For this function, a '^' at the start of a pattern does not work as an anchor, - * as this would prevent the iteration. + * For this function, a '^' at the start of a pattern does not work as an + * anchor, as this would prevent the iteration. */ static final class gmatch extends VarArgFunction { public Varargs invoke(Varargs args) { - LuaString src = args.checkstring( 1 ); - LuaString pat = args.checkstring( 2 ); + LuaString src = args.checkstring(1); + LuaString pat = args.checkstring(2); return new GMatchAux(args, src, pat); } } static class GMatchAux extends VarArgFunction { - private final int srclen; + private final int srclen; private final MatchState ms; - private int soffset; - private int lastmatch; + private int soffset; + private int lastmatch; + public GMatchAux(Varargs args, LuaString src, LuaString pat) { this.srclen = src.length(); this.ms = new MatchState(args, src, pat); this.soffset = 0; this.lastmatch = -1; } + public Varargs invoke(Varargs args) { - for ( ; soffset<=srclen; soffset++ ) { + for (; soffset <= srclen; soffset++) { ms.reset(); int res = ms.match(soffset, 0); - if ( res >=0 && res != lastmatch ) { + if (res >= 0 && res != lastmatch) { int soff = soffset; lastmatch = soffset = res; - return ms.push_captures( true, soff, res ); + return ms.push_captures(true, soff, res); } } return NIL; } } - /** - * string.gsub (s, pattern, repl [, n]) - * Returns a copy of s in which all (or the first n, if given) occurrences of the - * pattern have been replaced by a replacement string specified by repl, which - * may be a string, a table, or a function. gsub also returns, as its second value, - * the total number of matches that occurred. + * string.gsub (s, pattern, repl [, n]) Returns a copy of s in which all (or + * the first n, if given) occurrences of the pattern have been replaced by a + * replacement string specified by repl, which may be a string, a table, or + * a function. gsub also returns, as its second value, the total number of + * matches that occurred. * - * If repl is a string, then its value is used for replacement. - * The character % works as an escape character: any sequence in repl of the form %n, - * with n between 1 and 9, stands for the value of the n-th captured substring (see below). - * The sequence %0 stands for the whole match. The sequence %% stands for a single %. + * If repl is a string, then its value is used for replacement. The + * character % works as an escape character: any sequence in repl of the + * form %n, with n between 1 and 9, stands for the value of the n-th + * captured substring (see below). The sequence %0 stands for the whole + * match. The sequence %% stands for a single %. * - * If repl is a table, then the table is queried for every match, using the first capture - * as the key; if the pattern specifies no captures, then the whole match is used as the key. + * If repl is a table, then the table is queried for every match, using the + * first capture as the key; if the pattern specifies no captures, then the + * whole match is used as the key. * - * If repl is a function, then this function is called every time a match occurs, - * with all captured substrings passed as arguments, in order; if the pattern specifies - * no captures, then the whole match is passed as a sole argument. + * If repl is a function, then this function is called every time a match + * occurs, with all captured substrings passed as arguments, in order; if + * the pattern specifies no captures, then the whole match is passed as a + * sole argument. * - * If the value returned by the table query or by the function call is a string or a number, - * then it is used as the replacement string; otherwise, if it is false or nil, - * then there is no replacement (that is, the original match is kept in the string). + * If the value returned by the table query or by the function call is a + * string or a number, then it is used as the replacement string; otherwise, + * if it is false or nil, then there is no replacement (that is, the + * original match is kept in the string). * - * Here are some examples: - * x = string.gsub("hello world", "(%w+)", "%1 %1") - * --> x="hello hello world world" + * Here are some examples: x = string.gsub("hello world", "(%w+)", "%1 %1") + * --> x="hello hello world world" * - * x = string.gsub("hello world", "%w+", "%0 %0", 1) - * --> x="hello hello world" + * x = string.gsub("hello world", "%w+", "%0 %0", 1) --> x="hello hello + * world" * - * x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1") - * --> x="world hello Lua from" + * x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1") --> + * x="world hello Lua from" * - * x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv) - * --> x="home = /home/roberto, user = roberto" + * x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv) --> + * x="home = /home/roberto, user = roberto" * - * x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s) - * return loadstring(s)() - * end) - * --> x="4+5 = 9" + * x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s) return + * loadstring(s)() end) --> x="4+5 = 9" * - * local t = {name="lua", version="5.1"} - * x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t) - * --> x="lua-5.1.tar.gz" + * local t = {name="lua", version="5.1"} x = + * string.gsub("$name-$version.tar.gz", "%$(%w+)", t) --> x="lua-5.1.tar.gz" */ static final class gsub extends VarArgFunction { public Varargs invoke(Varargs args) { - LuaString src = args.checkstring( 1 ); + LuaString src = args.checkstring(1); final int srclen = src.length(); - LuaString p = args.checkstring( 2 ); + LuaString p = args.checkstring(2); int lastmatch = -1; /* end of last match */ - LuaValue repl = args.arg( 3 ); - int max_s = args.optint( 4, srclen + 1 ); - final boolean anchor = p.length() > 0 && p.charAt( 0 ) == '^'; - - Buffer lbuf = new Buffer( srclen ); - MatchState ms = new MatchState( args, src, p ); - + LuaValue repl = args.arg(3); + int max_s = args.optint(4, srclen+1); + final boolean anchor = p.length() > 0 && p.charAt(0) == '^'; + + Buffer lbuf = new Buffer(srclen); + MatchState ms = new MatchState(args, src, p); + int soffset = 0; int n = 0; while ( n < max_s ) { ms.reset(); - int res = ms.match( soffset, anchor ? 1 : 0 ); - if ( res != -1 && res != lastmatch ) { /* match? */ + int res = ms.match(soffset, anchor? 1: 0); + if (res != -1 && res != lastmatch) { /* match? */ n++; - ms.add_value( lbuf, soffset, res, repl ); /* add replacement to buffer */ + ms.add_value(lbuf, soffset, res, repl); /* add replacement to buffer */ soffset = lastmatch = res; - } - else if ( soffset < srclen ) /* otherwise, skip one character */ - lbuf.append( (byte) src.luaByte( soffset++ ) ); - else break; /* end of subject */ - if ( anchor ) break; + } else if (soffset < srclen) /* otherwise, skip one character */ + lbuf.append((byte) src.luaByte(soffset++)); + else + break; /* end of subject */ + if (anchor) + break; } - lbuf.append( src.substring( soffset, srclen ) ); + lbuf.append(src.substring(soffset, srclen)); return varargsOf(lbuf.tostring(), valueOf(n)); } } - + /** * string.len (s) * - * Receives a string and returns its length. The empty string "" has length 0. - * Embedded zeros are counted, so "a\000bc\000" has length 5. + * Receives a string and returns its length. The empty string "" has length + * 0. Embedded zeros are counted, so "a\000bc\000" has length 5. */ static final class len extends OneArgFunction { public LuaValue call(LuaValue arg) { @@ -642,13 +672,14 @@ public class StringLib extends TwoArgFunction { /** * string.lower (s) * - * Receives a string and returns a copy of this string with all uppercase letters - * changed to lowercase. All other characters are left unchanged. - * The definition of what an uppercase letter is depends on the current locale. + * Receives a string and returns a copy of this string with all uppercase + * letters changed to lowercase. All other characters are left unchanged. + * The definition of what an uppercase letter is depends on the current + * locale. */ static final class lower extends OneArgFunction { public LuaValue call(LuaValue arg) { - return valueOf( arg.checkjstring().toLowerCase() ); + return valueOf(arg.checkjstring().toLowerCase()); } } @@ -663,10 +694,10 @@ public class StringLib extends TwoArgFunction { */ static final class match extends VarArgFunction { public Varargs invoke(Varargs args) { - return str_find_aux( args, false ); + return str_find_aux(args, false); } } - + /** * string.rep (s, n) * @@ -674,14 +705,14 @@ public class StringLib extends TwoArgFunction { */ 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); + final byte[] bytes = new byte[s.length()*n]; int len = s.length(); - for ( int offset = 0; offset < bytes.length; offset += len ) { - s.copyInto( 0, bytes, offset, len ); + for (int offset = 0; offset < bytes.length; offset += len) { + s.copyInto(0, bytes, offset, len); } - return LuaString.valueUsing( bytes ); + return LuaString.valueUsing(bytes); } } @@ -695,150 +726,148 @@ public class StringLib extends TwoArgFunction { LuaString s = arg.checkstring(); int n = s.length(); byte[] b = new byte[n]; - for ( int i=0, j=n-1; i l ) + if (end > l) end = l; - - if ( start <= end ) { - return s.substring( start-1 , end ); + + if (start <= end) { + return s.substring(start-1, end); } else { return EMPTYSTRING; } } } - + /** * string.upper (s) * - * Receives a string and returns a copy of this string with all lowercase letters - * changed to uppercase. All other characters are left unchanged. - * The definition of what a lowercase letter is depends on the current locale. + * Receives a string and returns a copy of this string with all lowercase + * letters changed to uppercase. All other characters are left unchanged. + * The definition of what a lowercase letter is depends on the current + * locale. */ static final class upper extends OneArgFunction { public LuaValue call(LuaValue arg) { return valueOf(arg.checkjstring().toUpperCase()); } } - + /** * This utility method implements both string.find and string.match. */ - static Varargs str_find_aux( Varargs args, boolean find ) { - LuaString s = args.checkstring( 1 ); - LuaString pat = args.checkstring( 2 ); - int init = args.optint( 3, 1 ); - - if ( init > 0 ) { - init = Math.min( init - 1, s.length() ); - } else if ( init < 0 ) { - init = Math.max( 0, s.length() + init ); + static Varargs str_find_aux(Varargs args, boolean find) { + LuaString s = args.checkstring(1); + LuaString pat = args.checkstring(2); + int init = args.optint(3, 1); + + if (init > 0) { + init = Math.min(init-1, s.length()); + } else if (init < 0) { + init = Math.max(0, s.length()+init); } - - boolean fastMatch = find && ( args.arg(4).toboolean() || pat.indexOfAny( SPECIALS ) == -1 ); - - if ( fastMatch ) { - int result = s.indexOf( pat, init ); - if ( result != -1 ) { - return varargsOf( valueOf(result+1), valueOf(result+pat.length()) ); + + boolean fastMatch = find && (args.arg(4).toboolean() || pat.indexOfAny(SPECIALS) == -1); + + if (fastMatch) { + int result = s.indexOf(pat, init); + if (result != -1) { + return varargsOf(valueOf(result+1), valueOf(result+pat.length())); } } else { - MatchState ms = new MatchState( args, s, pat ); - + MatchState ms = new MatchState(args, s, pat); + boolean anchor = false; int poff = 0; - if ( pat.length() > 0 && pat.luaByte( 0 ) == '^' ) { + if (pat.length() > 0 && pat.luaByte(0) == '^') { anchor = true; poff = 1; } - + int soff = init; do { int res; ms.reset(); - if ( ( res = ms.match( soff, poff ) ) != -1 ) { - if ( find ) { - return varargsOf( valueOf(soff+1), valueOf(res), ms.push_captures( false, soff, res )); + if ((res = ms.match(soff, poff)) != -1) { + if (find) { + return varargsOf(valueOf(soff+1), valueOf(res), ms.push_captures(false, soff, res)); } else { - return ms.push_captures( true, soff, res ); + return ms.push_captures(true, soff, res); } } } while ( soff++ < s.length() && !anchor ); } return NIL; } - - static int posrelat( int pos, int len ) { - return ( pos >= 0 ) ? pos : len + pos + 1; + + static int posrelat(int pos, int len) { + return (pos >= 0)? pos: len+pos+1; } - + // Pattern matching implementation - - private static final int L_ESC = '%'; - private static final LuaString SPECIALS = valueOf("^$*+?.([%-"); - private static final int MAX_CAPTURES = 32; - + + private static final int L_ESC = '%'; + private static final LuaString SPECIALS = valueOf("^$*+?.([%-"); + private static final int MAX_CAPTURES = 32; + private static final int MAXCCALLS = 200; - + private static final int CAP_UNFINISHED = -1; - private static final int CAP_POSITION = -2; - - private static final byte MASK_ALPHA = 0x01; - private static final byte MASK_LOWERCASE = 0x02; - private static final byte MASK_UPPERCASE = 0x04; - private static final byte MASK_DIGIT = 0x08; - private static final byte MASK_PUNCT = 0x10; - private static final byte MASK_SPACE = 0x20; - private static final byte MASK_CONTROL = 0x40; - private static final byte MASK_HEXDIGIT = (byte)0x80; - + private static final int CAP_POSITION = -2; + + private static final byte MASK_ALPHA = 0x01; + private static final byte MASK_LOWERCASE = 0x02; + private static final byte MASK_UPPERCASE = 0x04; + private static final byte MASK_DIGIT = 0x08; + private static final byte MASK_PUNCT = 0x10; + private static final byte MASK_SPACE = 0x20; + private static final byte MASK_CONTROL = 0x40; + private static final byte MASK_HEXDIGIT = (byte) 0x80; + static final byte[] CHAR_TABLE; - + static { CHAR_TABLE = new byte[256]; - - for ( int i = 0; i < 128; ++i ) { + + for (int i = 0; i < 128; ++i) { final char c = (char) i; - CHAR_TABLE[i] = (byte)( ( Character.isDigit( c ) ? MASK_DIGIT : 0 ) | - ( Character.isLowerCase( c ) ? MASK_LOWERCASE : 0 ) | - ( Character.isUpperCase( c ) ? MASK_UPPERCASE : 0 ) | - ( ( c < ' ' || c == 0x7F ) ? MASK_CONTROL : 0 ) ); - if ( ( c >= 'a' && c <= 'f' ) || ( c >= 'A' && c <= 'F' ) || ( c >= '0' && c <= '9' ) ) { + CHAR_TABLE[i] = (byte) ((Character.isDigit(c)? MASK_DIGIT: 0) + | (Character.isLowerCase(c)? MASK_LOWERCASE: 0) | (Character.isUpperCase(c)? MASK_UPPERCASE: 0) + | ((c < ' ' || c == 0x7F)? MASK_CONTROL: 0)); + if ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (c >= '0' && c <= '9')) { CHAR_TABLE[i] |= MASK_HEXDIGIT; } - if ( ( c >= '!' && c <= '/' ) || ( c >= ':' && c <= '@' ) || ( c >= '[' && c <= '`' ) || ( c >= '{' && c <= '~' ) ) { + if ((c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~')) { CHAR_TABLE[i] |= MASK_PUNCT; } - if ( ( CHAR_TABLE[i] & ( MASK_LOWERCASE | MASK_UPPERCASE ) ) != 0 ) { + if ((CHAR_TABLE[i] & (MASK_LOWERCASE | MASK_UPPERCASE)) != 0) { CHAR_TABLE[i] |= MASK_ALPHA; } } - + CHAR_TABLE[' '] = MASK_SPACE; CHAR_TABLE['\r'] |= MASK_SPACE; CHAR_TABLE['\n'] |= MASK_SPACE; @@ -846,289 +875,318 @@ public class StringLib extends TwoArgFunction { CHAR_TABLE[0x0B /* '\v' */ ] |= MASK_SPACE; CHAR_TABLE['\f'] |= MASK_SPACE; }; - + static class MatchState { - int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ + int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ final LuaString s; final LuaString p; - final Varargs args; - int level; - int[] cinit; - int[] clen; - - MatchState( Varargs args, LuaString s, LuaString pattern ) { + final Varargs args; + int level; + int[] cinit; + int[] clen; + + MatchState(Varargs args, LuaString s, LuaString pattern) { this.s = s; this.p = pattern; this.args = args; this.level = 0; - this.cinit = new int[ MAX_CAPTURES ]; - this.clen = new int[ MAX_CAPTURES ]; + this.cinit = new int[MAX_CAPTURES]; + this.clen = new int[MAX_CAPTURES]; this.matchdepth = MAXCCALLS; } - + void reset() { level = 0; this.matchdepth = MAXCCALLS; } - - private void add_s( Buffer lbuf, LuaString news, int soff, int e ) { + + private void add_s(Buffer lbuf, LuaString news, int soff, int e) { int l = news.length(); - for ( int i = 0; i < l; ++i ) { - byte b = (byte) news.luaByte( i ); - if ( b != L_ESC ) { - lbuf.append( (byte) b ); + for (int i = 0; i < l; ++i) { + byte b = (byte) news.luaByte(i); + if (b != L_ESC) { + lbuf.append((byte) b); } else { ++i; // skip ESC - b = (byte)(i < l ? news.luaByte( i ) : 0); - if ( !Character.isDigit( (char) b ) ) { - if (b != L_ESC) error( "invalid use of '" + (char)L_ESC + - "' in replacement string: after '" + (char)L_ESC + - "' must be '0'-'9' or '" + (char)L_ESC + - "', but found " + (i < l ? "symbol '" + (char)b + "' with code " + b + - " at pos " + (i + 1) : - "end of string")); - lbuf.append( b ); - } else if ( b == '0' ) { - lbuf.append( s.substring( soff, e ) ); + b = (byte) (i < l? news.luaByte(i): 0); + if (!Character.isDigit((char) b)) { + if (b != L_ESC) + error("invalid use of '" + (char) L_ESC + "' in replacement string: after '" + (char) L_ESC + + "' must be '0'-'9' or '" + (char) L_ESC + "', but found " + + (i < l? "symbol '" + (char) b + "' with code " + b + " at pos " + (i+1) + : "end of string")); + lbuf.append(b); + } else if (b == '0') { + lbuf.append(s.substring(soff, e)); } else { - lbuf.append( push_onecapture( b - '1', soff, e ).strvalue() ); + lbuf.append(push_onecapture(b-'1', soff, e).strvalue()); } } } } - - public void add_value( Buffer lbuf, int soffset, int end, LuaValue repl ) { - switch ( repl.type() ) { + + public void add_value(Buffer lbuf, int soffset, int end, LuaValue repl) { + switch (repl.type()) { case LuaValue.TSTRING: case LuaValue.TNUMBER: - add_s( lbuf, repl.strvalue(), soffset, end ); + add_s(lbuf, repl.strvalue(), soffset, end); return; - + case LuaValue.TFUNCTION: - repl = repl.invoke( push_captures( true, soffset, end ) ).arg1(); + repl = repl.invoke(push_captures(true, soffset, end)).arg1(); break; - + case LuaValue.TTABLE: // Need to call push_onecapture here for the error checking - repl = repl.get( push_onecapture( 0, soffset, end ) ); + repl = repl.get(push_onecapture(0, soffset, end)); break; - + default: - error( "bad argument: string/function/table expected" ); + error("bad argument: string/function/table expected"); return; } - - if ( !repl.toboolean() ) { - repl = s.substring( soffset, end ); - } else if ( ! repl.isstring() ) { - error( "invalid replacement value (a "+repl.typename()+")" ); + + if (!repl.toboolean()) { + repl = s.substring(soffset, end); + } else if (!repl.isstring()) { + error("invalid replacement value (a " + repl.typename() + ")"); } - lbuf.append( repl.strvalue() ); + lbuf.append(repl.strvalue()); } - - Varargs push_captures( boolean wholeMatch, int soff, int end ) { - int nlevels = ( this.level == 0 && wholeMatch ) ? 1 : this.level; - switch ( nlevels ) { - case 0: return NONE; - case 1: return push_onecapture( 0, soff, end ); + + Varargs push_captures(boolean wholeMatch, int soff, int end) { + int nlevels = (this.level == 0 && wholeMatch)? 1: this.level; + switch (nlevels) { + case 0: + return NONE; + case 1: + return push_onecapture(0, soff, end); } LuaValue[] v = new LuaValue[nlevels]; - for ( int i = 0; i < nlevels; ++i ) - v[i] = push_onecapture( i, soff, end ); + for (int i = 0; i < nlevels; ++i) + v[i] = push_onecapture(i, soff, end); return varargsOf(v); } - - private LuaValue push_onecapture( int i, int soff, int end ) { - if ( i >= this.level ) { - if ( i == 0 ) { - return s.substring( soff, end ); + + private LuaValue push_onecapture(int i, int soff, int end) { + if (i >= this.level) { + if (i == 0) { + return s.substring(soff, end); } else { - return error( "invalid capture index %" + (i + 1) ); + return error("invalid capture index %" + (i+1)); } } else { int l = clen[i]; - if ( l == CAP_UNFINISHED ) { - return error( "unfinished capture" ); + if (l == CAP_UNFINISHED) { + return error("unfinished capture"); } - if ( l == CAP_POSITION ) { - return valueOf( cinit[i] + 1 ); + if (l == CAP_POSITION) { + return valueOf(cinit[i]+1); } else { int begin = cinit[i]; - return s.substring( begin, begin + l ); + return s.substring(begin, begin+l); } } } - - private int check_capture( int l ) { + + private int check_capture(int l) { l -= '1'; - if ( l < 0 || l >= level || this.clen[l] == CAP_UNFINISHED ) { - error("invalid capture index %" + (l + 1)); + if (l < 0 || l >= level || this.clen[l] == CAP_UNFINISHED) { + error("invalid capture index %" + (l+1)); } return l; } - + private int capture_to_close() { int level = this.level; - for ( level--; level >= 0; level-- ) - if ( clen[level] == CAP_UNFINISHED ) + for (level--; level >= 0; level--) + if (clen[level] == CAP_UNFINISHED) return level; error("invalid pattern capture"); return 0; } - - int classend( int poffset ) { - switch ( p.luaByte( poffset++ ) ) { + + int classend(int poffset) { + switch (p.luaByte(poffset++)) { case L_ESC: - if ( poffset == p.length() ) { - error( "malformed pattern (ends with '%')" ); + if (poffset == p.length()) { + error("malformed pattern (ends with '%')"); } - return poffset + 1; - + return poffset+1; + case '[': - if ( poffset != p.length() && p.luaByte( poffset ) == '^' ) poffset++; + if (poffset != p.length() && p.luaByte(poffset) == '^') + poffset++; do { - if ( poffset == p.length() ) { - error( "malformed pattern (missing ']')" ); + if (poffset == p.length()) { + error("malformed pattern (missing ']')"); } - if ( p.luaByte( poffset++ ) == L_ESC && poffset < p.length() ) + if (p.luaByte(poffset++) == L_ESC && poffset < p.length()) poffset++; /* skip escapes (e.g. '%]') */ - } while ( poffset == p.length() || p.luaByte( poffset ) != ']' ); - return poffset + 1; + } while ( poffset == p.length() || p.luaByte(poffset) != ']' ); + return poffset+1; default: return poffset; } } - - static boolean match_class( int c, int cl ) { - final char lcl = Character.toLowerCase( (char) cl ); + + static boolean match_class(int c, int cl) { + final char lcl = Character.toLowerCase((char) cl); int cdata = CHAR_TABLE[c]; - + boolean res; - switch ( lcl ) { - case 'a': res = ( cdata & MASK_ALPHA ) != 0; break; - case 'd': res = ( cdata & MASK_DIGIT ) != 0; break; - case 'l': res = ( cdata & MASK_LOWERCASE ) != 0; break; - case 'u': res = ( cdata & MASK_UPPERCASE ) != 0; break; - case 'c': res = ( cdata & MASK_CONTROL ) != 0; break; - case 'p': res = ( cdata & MASK_PUNCT ) != 0; break; - case 's': res = ( cdata & MASK_SPACE ) != 0; break; - case 'g': res = ( cdata & ( MASK_ALPHA | MASK_DIGIT | MASK_PUNCT ) ) != 0; break; - case 'w': res = ( cdata & ( MASK_ALPHA | MASK_DIGIT ) ) != 0; break; - case 'x': res = ( cdata & MASK_HEXDIGIT ) != 0; break; - case 'z': res = ( c == 0 ); break; /* deprecated option */ - default: return cl == c; + switch (lcl) { + case 'a': + res = (cdata & MASK_ALPHA) != 0; + break; + case 'd': + res = (cdata & MASK_DIGIT) != 0; + break; + case 'l': + res = (cdata & MASK_LOWERCASE) != 0; + break; + case 'u': + res = (cdata & MASK_UPPERCASE) != 0; + break; + case 'c': + res = (cdata & MASK_CONTROL) != 0; + break; + case 'p': + res = (cdata & MASK_PUNCT) != 0; + break; + case 's': + res = (cdata & MASK_SPACE) != 0; + break; + case 'g': + res = (cdata & (MASK_ALPHA | MASK_DIGIT | MASK_PUNCT)) != 0; + break; + case 'w': + res = (cdata & (MASK_ALPHA | MASK_DIGIT)) != 0; + break; + case 'x': + res = (cdata & MASK_HEXDIGIT) != 0; + break; + case 'z': + res = (c == 0); + break; /* deprecated option */ + default: + return cl == c; } - return ( lcl == cl ) ? res : !res; + return (lcl == cl)? res: !res; } - - boolean matchbracketclass( int c, int poff, int ec ) { + + boolean matchbracketclass(int c, int poff, int ec) { boolean sig = true; - if ( p.luaByte( poff + 1 ) == '^' ) { + if (p.luaByte(poff+1) == '^') { sig = false; poff++; } while ( ++poff < ec ) { - if ( p.luaByte( poff ) == L_ESC ) { + if (p.luaByte(poff) == L_ESC) { poff++; - if ( match_class( c, p.luaByte( poff ) ) ) + if (match_class(c, p.luaByte(poff))) return sig; - } - else if ( ( p.luaByte( poff + 1 ) == '-' ) && ( poff + 2 < ec ) ) { + } else if ((p.luaByte(poff+1) == '-') && (poff+2 < ec)) { poff += 2; - if ( p.luaByte( poff - 2 ) <= c && c <= p.luaByte( poff ) ) + if (p.luaByte(poff-2) <= c && c <= p.luaByte(poff)) return sig; - } - else if ( p.luaByte( poff ) == c ) return sig; + } else if (p.luaByte(poff) == c) + return sig; } return !sig; } - - boolean singlematch( int c, int poff, int ep ) { - switch ( p.luaByte( poff ) ) { - case '.': return true; - case L_ESC: return match_class( c, p.luaByte( poff + 1 ) ); - case '[': return matchbracketclass( c, poff, ep - 1 ); - default: return p.luaByte( poff ) == c; + + boolean singlematch(int c, int poff, int ep) { + switch (p.luaByte(poff)) { + case '.': + return true; + case L_ESC: + return match_class(c, p.luaByte(poff+1)); + case '[': + return matchbracketclass(c, poff, ep-1); + default: + return p.luaByte(poff) == c; } } - + /** * Perform pattern matching. If there is a match, returns offset into s * where match ends, otherwise returns -1. */ - int match( int soffset, int poffset ) { - if (matchdepth-- == 0) error("pattern too complex"); + int match(int soffset, int poffset) { + if (matchdepth-- == 0) + error("pattern too complex"); try { while ( true ) { // Check if we are at the end of the pattern - // equivalent to the '\0' case in the C version, but our pattern // string is not NUL-terminated. - if ( poffset == p.length() ) + if (poffset == p.length()) return soffset; - switch ( p.luaByte( poffset ) ) { + switch (p.luaByte(poffset)) { case '(': - if ( ++poffset < p.length() && p.luaByte( poffset ) == ')' ) - return start_capture( soffset, poffset + 1, CAP_POSITION ); + if (++poffset < p.length() && p.luaByte(poffset) == ')') + return start_capture(soffset, poffset+1, CAP_POSITION); else - return start_capture( soffset, poffset, CAP_UNFINISHED ); + return start_capture(soffset, poffset, CAP_UNFINISHED); case ')': - return end_capture( soffset, poffset + 1 ); + return end_capture(soffset, poffset+1); case L_ESC: - if ( poffset + 1 == p.length() ) + if (poffset+1 == p.length()) error("malformed pattern (ends with '%')"); - switch ( p.luaByte( poffset + 1 ) ) { + switch (p.luaByte(poffset+1)) { case 'b': - soffset = matchbalance( soffset, poffset + 2 ); - if ( soffset == -1 ) return -1; + soffset = matchbalance(soffset, poffset+2); + if (soffset == -1) + return -1; poffset += 4; continue; case 'f': { poffset += 2; - if ( poffset == p.length() || p.luaByte( poffset ) != '[' ) { + if (poffset == p.length() || p.luaByte(poffset) != '[') { error("missing '[' after '%f' in pattern"); } - int ep = classend( poffset ); - int previous = ( soffset == 0 ) ? '\0' : s.luaByte( soffset - 1 ); - int next = ( soffset == s.length() ) ? '\0' : s.luaByte( soffset ); - if ( matchbracketclass( previous, poffset, ep - 1 ) || - !matchbracketclass( next, poffset, ep - 1 ) ) + int ep = classend(poffset); + int previous = (soffset == 0)? '\0': s.luaByte(soffset-1); + int next = (soffset == s.length())? '\0': s.luaByte(soffset); + if (matchbracketclass(previous, poffset, ep-1) || !matchbracketclass(next, poffset, ep-1)) return -1; poffset = ep; continue; } default: { - int c = p.luaByte( poffset + 1 ); - if ( Character.isDigit( (char) c ) ) { - soffset = match_capture( soffset, c ); - if ( soffset == -1 ) + int c = p.luaByte(poffset+1); + if (Character.isDigit((char) c)) { + soffset = match_capture(soffset, c); + if (soffset == -1) return -1; - return match( soffset, poffset + 2 ); + return match(soffset, poffset+2); } } } case '$': - if ( poffset + 1 == p.length() ) - return ( soffset == s.length() ) ? soffset : -1; + if (poffset+1 == p.length()) + return (soffset == s.length())? soffset: -1; } - int ep = classend( poffset ); - boolean m = soffset < s.length() && singlematch( s.luaByte( soffset ), poffset, ep ); - int pc = ( ep < p.length() ) ? p.luaByte( ep ) : '\0'; - - switch ( pc ) { + int ep = classend(poffset); + boolean m = soffset < s.length() && singlematch(s.luaByte(soffset), poffset, ep); + int pc = (ep < p.length())? p.luaByte(ep): '\0'; + + switch (pc) { case '?': int res; - if ( m && ( ( res = match( soffset + 1, ep + 1 ) ) != -1 ) ) + if (m && ((res = match(soffset+1, ep+1)) != -1)) return res; - poffset = ep + 1; + poffset = ep+1; continue; case '*': - return max_expand( soffset, poffset, ep ); + return max_expand(soffset, poffset, ep); case '+': - return ( m ? max_expand( soffset + 1, poffset, ep ) : -1 ); + return (m? max_expand(soffset+1, poffset, ep): -1); case '-': - return min_expand( soffset, poffset, ep ); + return min_expand(soffset, poffset, ep); default: - if ( !m ) + if (!m) return -1; soffset++; poffset = ep; @@ -1139,83 +1197,83 @@ public class StringLib extends TwoArgFunction { matchdepth++; } } - - int max_expand( int soff, int poff, int ep ) { + + int max_expand(int soff, int poff, int ep) { int i = 0; - while ( soff + i < s.length() && - singlematch( s.luaByte( soff + i ), poff, ep ) ) + while ( soff+i < s.length() && singlematch(s.luaByte(soff+i), poff, ep) ) i++; while ( i >= 0 ) { - int res = match( soff + i, ep + 1 ); - if ( res != -1 ) + int res = match(soff+i, ep+1); + if (res != -1) return res; i--; } return -1; } - - int min_expand( int soff, int poff, int ep ) { - for ( ;; ) { - int res = match( soff, ep + 1 ); - if ( res != -1 ) + + int min_expand(int soff, int poff, int ep) { + for (;;) { + int res = match(soff, ep+1); + if (res != -1) return res; - else if ( soff < s.length() && singlematch( s.luaByte( soff ), poff, ep ) ) + else if (soff < s.length() && singlematch(s.luaByte(soff), poff, ep)) soff++; - else return -1; + else + return -1; } } - - int start_capture( int soff, int poff, int what ) { + + int start_capture(int soff, int poff, int what) { int res; int level = this.level; - if ( level >= MAX_CAPTURES ) { - error( "too many captures" ); + if (level >= MAX_CAPTURES) { + error("too many captures"); } - cinit[ level ] = soff; - clen[ level ] = what; - this.level = level + 1; - if ( ( res = match( soff, poff ) ) == -1 ) + cinit[level] = soff; + clen[level] = what; + this.level = level+1; + if ((res = match(soff, poff)) == -1) this.level--; return res; } - - int end_capture( int soff, int poff ) { + + int end_capture(int soff, int poff) { int l = capture_to_close(); int res; - clen[l] = soff - cinit[l]; - if ( ( res = match( soff, poff ) ) == -1 ) + clen[l] = soff-cinit[l]; + if ((res = match(soff, poff)) == -1) clen[l] = CAP_UNFINISHED; return res; } - - int match_capture( int soff, int l ) { - l = check_capture( l ); - int len = clen[ l ]; - if ( ( s.length() - soff ) >= len && - LuaString.equals( s, cinit[l], s, soff, len ) ) - return soff + len; + + int match_capture(int soff, int l) { + l = check_capture(l); + int len = clen[l]; + if ((s.length()-soff) >= len && LuaString.equals(s, cinit[l], s, soff, len)) + return soff+len; else return -1; } - - int matchbalance( int soff, int poff ) { + + int matchbalance(int soff, int poff) { final int plen = p.length(); - if ( poff == plen || poff + 1 == plen ) { - error( "malformed pattern (missing arguments to '%b')" ); + if (poff == plen || poff+1 == plen) { + error("malformed pattern (missing arguments to '%b')"); } final int slen = s.length(); - if ( soff >= slen ) + if (soff >= slen) return -1; - final int b = p.luaByte( poff ); - if ( s.luaByte( soff ) != b ) + final int b = p.luaByte(poff); + if (s.luaByte(soff) != b) return -1; - final int e = p.luaByte( poff + 1 ); + final int e = p.luaByte(poff+1); int cont = 1; while ( ++soff < slen ) { - if ( s.luaByte( soff ) == e ) { - if ( --cont == 0 ) return soff + 1; - } - else if ( s.luaByte( soff ) == b ) cont++; + if (s.luaByte(soff) == e) { + if (--cont == 0) + return soff+1; + } else if (s.luaByte(soff) == b) + cont++; } return -1; } diff --git a/luaj-core/src/main/java/org/luaj/vm2/lib/TableLib.java b/luaj-core/src/main/java/org/luaj/vm2/lib/TableLib.java index 64959277..0472dfed 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/lib/TableLib.java +++ b/luaj-core/src/main/java/org/luaj/vm2/lib/TableLib.java @@ -26,40 +26,56 @@ 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()} - *

 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * System.out.println( globals.get("table").get("length").call( LuaValue.tableOf() ) );
- * } 
+ * {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or + * {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()} + * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	System.out.println(globals.get("table").get("length").call(LuaValue.tableOf()));
+ * }
+ * 
*

- * To instantiate and use it directly, - * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JseBaseLib());
- * globals.load(new PackageLib());
- * globals.load(new TableLib());
- * System.out.println( globals.get("table").get("length").call( LuaValue.tableOf() ) );
- * } 
+ * To instantiate and use it directly, link it into your globals table via + * {@link LuaValue#load(LuaValue)} using code such as: + * + *
+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JseBaseLib());
+ * 	globals.load(new PackageLib());
+ * 	globals.load(new TableLib());
+ * 	System.out.println(globals.get("table").get("length").call(LuaValue.tableOf()));
+ * }
+ * 
*

- * 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. */ public LuaValue call(LuaValue modname, LuaValue env) { LuaTable table = new LuaTable(); @@ -70,23 +86,27 @@ 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 { public LuaValue call(LuaValue list) { - return list.checktable().concat(EMPTYSTRING,1,list.length()); + return list.checktable().concat(EMPTYSTRING, 1, list.length()); } + 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()); } + 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()); } + 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()); } } @@ -96,14 +116,15 @@ public class TableLib extends TwoArgFunction { 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,7 +134,7 @@ public class TableLib extends TwoArgFunction { } } } - + // "pack" (...) -> table static class pack extends VarArgFunction { public Varargs invoke(Varargs args) { @@ -129,8 +150,8 @@ public class TableLib extends TwoArgFunction { 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); } @@ -139,19 +160,17 @@ public class TableLib extends TwoArgFunction { // "sort" (table [, comp]) static class sort extends VarArgFunction { 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 { 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/luaj-core/src/main/java/org/luaj/vm2/lib/ThreeArgFunction.java b/luaj-core/src/main/java/org/luaj/vm2/lib/ThreeArgFunction.java index 68ceb243..dcb72db8 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/lib/ThreeArgFunction.java +++ b/luaj-core/src/main/java/org/luaj/vm2/lib/ThreeArgFunction.java @@ -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 @@ -49,11 +52,11 @@ import org.luaj.vm2.Varargs; abstract public class ThreeArgFunction extends LibFunction { abstract public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3); - + /** Default constructor */ public ThreeArgFunction() { } - + public final LuaValue call() { return call(NIL, NIL, NIL); } @@ -65,9 +68,9 @@ abstract public class ThreeArgFunction extends LibFunction { public LuaValue call(LuaValue arg1, LuaValue arg2) { return call(arg1, arg2, NIL); } - + 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/luaj-core/src/main/java/org/luaj/vm2/lib/TwoArgFunction.java b/luaj-core/src/main/java/org/luaj/vm2/lib/TwoArgFunction.java index 8a97f6fb..7309946b 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/lib/TwoArgFunction.java +++ b/luaj-core/src/main/java/org/luaj/vm2/lib/TwoArgFunction.java @@ -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 @@ -49,11 +52,11 @@ import org.luaj.vm2.Varargs; abstract public class TwoArgFunction extends LibFunction { abstract public LuaValue call(LuaValue arg1, LuaValue arg2); - + /** Default constructor */ public TwoArgFunction() { } - + public final LuaValue call() { return call(NIL, NIL); } @@ -65,9 +68,9 @@ abstract public class TwoArgFunction extends LibFunction { public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { return call(arg1, arg2); } - + public Varargs invoke(Varargs varargs) { - return call(varargs.arg1(),varargs.arg(2)); + return call(varargs.arg1(), varargs.arg(2)); } - -} + +} diff --git a/luaj-core/src/main/java/org/luaj/vm2/lib/VarArgFunction.java b/luaj-core/src/main/java/org/luaj/vm2/lib/VarArgFunction.java index 8e2bd614..8fc7a743 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/lib/VarArgFunction.java +++ b/luaj-core/src/main/java/org/luaj/vm2/lib/VarArgFunction.java @@ -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,7 +52,7 @@ abstract public class VarArgFunction extends LibFunction { public VarArgFunction() { } - + public LuaValue call() { return invoke(NONE).arg1(); } @@ -59,25 +62,25 @@ abstract public class VarArgFunction extends LibFunction { } public LuaValue call(LuaValue arg1, LuaValue arg2) { - return invoke(varargsOf(arg1,arg2)).arg1(); + return invoke(varargsOf(arg1, arg2)).arg1(); } 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. */ public Varargs invoke(Varargs args) { return onInvoke(args).eval(); } - + public Varargs onInvoke(Varargs args) { return invoke(args); } -} +} diff --git a/luaj-core/src/main/java/org/luaj/vm2/lib/ZeroArgFunction.java b/luaj-core/src/main/java/org/luaj/vm2/lib/ZeroArgFunction.java index 06169d74..d40f4f6e 100644 --- a/luaj-core/src/main/java/org/luaj/vm2/lib/ZeroArgFunction.java +++ b/luaj-core/src/main/java/org/luaj/vm2/lib/ZeroArgFunction.java @@ -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}. *

- * 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() * @see LibFunction * @see OneArgFunction @@ -51,7 +53,7 @@ abstract public class ZeroArgFunction extends LibFunction { /** Default constructor */ public ZeroArgFunction() { } - + public LuaValue call(LuaValue arg) { return call(); } @@ -67,4 +69,4 @@ abstract public class ZeroArgFunction extends LibFunction { public Varargs invoke(Varargs varargs) { return call(); } -} +} diff --git a/luaj-jme/src/main/java/org/luaj/vm2/lib/jme/JmeIoLib.java b/luaj-jme/src/main/java/org/luaj/vm2/lib/jme/JmeIoLib.java index e7cbd3c1..c0b41e8a 100644 --- a/luaj-jme/src/main/java/org/luaj/vm2/lib/jme/JmeIoLib.java +++ b/luaj-jme/src/main/java/org/luaj/vm2/lib/jme/JmeIoLib.java @@ -34,61 +34,74 @@ import org.luaj.vm2.LuaValue; 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. - *

- * 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()} - *

 {@code
- * Globals globals = JmePlatform.standardGlobals();
- * globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
- * } 
+ * + *
+ * {
+ * 	@code
+ * 	Globals globals = JmePlatform.standardGlobals();
+ * 	globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
+ * }
+ * 
*

- * 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: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JmeBaseLib());
- * globals.load(new PackageLib());
- * globals.load(new JmeIoLib());
- * globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
- * } 
- *

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: + * + *

+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JmeBaseLib());
+ * 	globals.load(new PackageLib());
+ * 	globals.load(new JmeIoLib());
+ * 	globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
+ * }
+ * 
*

- * 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 { - + protected File wrapStdin() throws IOException { return new FileImpl(globals.STDIN); } - + protected File wrapStdout() throws IOException { return new FileImpl(globals.STDOUT); } - + 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 { + + 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); + File f = readMode? new FileImpl(conn, conn.openInputStream(), null) + : new FileImpl(conn, conn.openInputStream(), conn.openOutputStream()); /* if ( appendMode ) { f.seek("end",0); @@ -99,11 +112,11 @@ public class JmeIoLib extends IoLib { */ return f; } - + private static void notimplemented() throws IOException { throw new IOException("not implemented"); } - + protected File openProgram(String prog, String mode) throws IOException { notimplemented(); return null; @@ -113,52 +126,62 @@ public class JmeIoLib extends IoLib { 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); } + public String tojstring() { - return "file ("+this.hashCode()+")"; + return "file (" + this.hashCode() + ")"; } + public boolean isstdfile() { return conn == null; } - public void close() throws IOException { + + public void close() throws IOException { closed = true; - if ( conn != null ) { + if (conn != null) { conn.close(); } } + public void flush() throws IOException { - if ( os != null ) + if (os != null) os.flush(); } + 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(); } + public boolean isclosed() { return closed; } + public int seek(String option, int pos) throws IOException { /* if ( conn != null ) { @@ -177,6 +200,7 @@ public class JmeIoLib extends IoLib { notimplemented(); return 0; } + public void setvbuf(String mode, int size) { nobuffer = "no".equals(mode); } @@ -185,22 +209,22 @@ public class JmeIoLib extends IoLib { public int remaining() throws IOException { return -1; } - + // peek ahead one character 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 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; @@ -208,17 +232,17 @@ public class JmeIoLib extends IoLib { // return number of bytes read if positive, -1 if eof, throws IOException 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/luaj-jme/src/main/java/org/luaj/vm2/lib/jme/JmePlatform.java b/luaj-jme/src/main/java/org/luaj/vm2/lib/jme/JmePlatform.java index c7c8bb66..d9614f49 100644 --- a/luaj-jme/src/main/java/org/luaj/vm2/lib/jme/JmePlatform.java +++ b/luaj-jme/src/main/java/org/luaj/vm2/lib/jme/JmePlatform.java @@ -37,40 +37,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: - *

 {@code
- * Globals global = JmePlatform.standardGlobals();
- * global.get("print").call(LuaValue.valueOf("hello, world"));
- * } 
+ * + *
+ * {
+ * 	@code
+ * 	Globals global = JmePlatform.standardGlobals();
+ * 	global.get("print").call(LuaValue.valueOf("hello, world"));
+ * }
+ * 
*

* Once globals are created, a simple way to load and run a script is: - *

 {@code
+ * 
+ * 
+ *  {@code
  * LoadState.load( getClass().getResourceAsStream("main.lua"), "main.lua", globals ).call();
- * } 
+ * } + *
*

- * although {@code require} could also be used: - *

 {@code
+ * although {@code require} could also be used:
+ * 
+ * 
+ *  {@code
  * globals.get("require").call(LuaValue.valueOf("main"));
- * } 
- * 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: *

    *
  • {@link Globals}
  • *
  • {@link BaseLib}
  • @@ -83,12 +103,14 @@ import org.luaj.vm2.lib.TableLib; *
  • {@link org.luaj.vm2.lib.jme.JmeIoLib}
  • *
  • {@link OsLib}
  • *
- * 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 @@ -116,12 +138,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. + + /** + * Create standard globals including the {@link DebugLib} library. * - * @return Table of globals initialized with the standard JSE and debug libraries + * @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-jse/src/main/java/lua.java b/luaj-jse/src/main/java/lua.java index 39e488f2..073bdf07 100644 --- a/luaj-jse/src/main/java/lua.java +++ b/luaj-jse/src/main/java/lua.java @@ -1,3 +1,4 @@ + /******************************************************************************* * Copyright (c) 2009-2012 Luaj.org. All rights reserved. * @@ -38,37 +39,30 @@ 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); @@ -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/luaj-jse/src/main/java/luac.java b/luaj-jse/src/main/java/luac.java index f0af43fe..3331f62d 100644 --- a/luaj-jse/src/main/java/luac.java +++ b/luaj-jse/src/main/java/luac.java @@ -1,3 +1,4 @@ + /******************************************************************************* * Copyright (c) 2009 Luaj.org. All rights reserved. * @@ -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,26 @@ public class luac { } } } - + // echo version - if ( versioninfo ) + if (versioninfo) System.out.println(version); // open output file - OutputStream fos = new FileOutputStream( output ); - + OutputStream fos = new FileOutputStream(output); + // process input files try { Globals globals = JsePlatform.standardGlobals(); processing = true; - for ( int i=0; i= args.length ) + if (++i >= args.length) usageExit(); srcdir = args[i]; break; case 'd': - if ( ++i >= args.length ) + if (++i >= args.length) usageExit(); destdir = args[i]; break; @@ -99,7 +95,7 @@ public class luajc { loadclasses = true; break; case 'p': - if ( ++i >= args.length ) + if (++i >= args.length) usageExit(); pkgprefix = args[i]; break; @@ -110,7 +106,7 @@ public class luajc { recurse = true; break; case 'c': - if ( ++i >= args.length ) + if (++i >= args.length) usageExit(); encoding = args[i]; break; @@ -123,60 +119,61 @@ public class luajc { } } } - + // echo version - if ( verbose ) { + 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); + 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 ) { + if (seeds.size() <= 0) { System.err.println(usage); System.exit(-1); } // collect up files to process - for ( int i=0; i= 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 ); + 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/luaj-jse/src/main/java/org/luaj/vm2/ast/Block.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Block.java index d63df608..dbd86de4 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/ast/Block.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Block.java @@ -25,12 +25,12 @@ import java.util.ArrayList; import java.util.List; public class Block extends Stat { - + public List stats = new ArrayList(); - public NameScope scope; - + public NameScope scope; + public void add(Stat s) { - if ( s == null ) + if (s == null) return; stats.add(s); } diff --git a/luaj-jse/src/main/java/org/luaj/vm2/ast/Chunk.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Chunk.java index f09ff461..958078b3 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/ast/Chunk.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Chunk.java @@ -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/luaj-jse/src/main/java/org/luaj/vm2/ast/Exp.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Exp.java index 7b41b60b..c46083f8 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/ast/Exp.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Exp.java @@ -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,11 +161,12 @@ public class Exp extends SyntaxElement { public boolean isvarargexp() { return false; } - + abstract public static class PrimaryExp extends Exp { public boolean isvarexp() { return false; } + public boolean isfunccall() { return false; } @@ -157,64 +176,71 @@ public class Exp extends SyntaxElement { 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); } + public void markHasAssignment() { name.variable.hasassignments = true; } + 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; } - + 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); } - + 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; } - + 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; @@ -223,19 +249,19 @@ public class Exp extends SyntaxElement { public boolean isfunccall() { return true; } - + public void accept(Visitor visitor) { visitor.visit(this); } - + 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); @@ -244,7 +270,7 @@ public class Exp extends SyntaxElement { public boolean isfunccall() { return true; } - + public void accept(Visitor visitor) { visitor.visit(this); } @@ -252,29 +278,31 @@ 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 { - + public void accept(Visitor visitor) { visitor.visit(this); } - + 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; @@ -282,12 +310,13 @@ public class Exp extends SyntaxElement { 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; @@ -296,18 +325,19 @@ public class Exp extends SyntaxElement { 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; } public void accept(Visitor visitor) { visitor.visit(this); - } + } } } diff --git a/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncArgs.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncArgs.java index 8c34cfc7..3152c6be 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncArgs.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncArgs.java @@ -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); @@ -51,12 +51,12 @@ public class FuncArgs extends SyntaxElement { public FuncArgs(LuaString string) { this.exps = new ArrayList(); - this.exps.add( Exp.constant(string) ); + this.exps.add(Exp.constant(string)); } public FuncArgs(TableConstructor table) { this.exps = new ArrayList(); - this.exps.add( table ); + this.exps.add(table); } public void accept(Visitor visitor) { diff --git a/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncBody.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncBody.java index 41d37ff3..30ab12bb 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncBody.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncBody.java @@ -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/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncName.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncName.java index e0f8cb90..d1146425 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncName.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/FuncName.java @@ -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 ) + if (dots == null) dots = new ArrayList(); dots.add(dot); } - + } diff --git a/luaj-jse/src/main/java/org/luaj/vm2/ast/Name.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Name.java index 11b4acc2..44507069 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/ast/Name.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Name.java @@ -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/luaj-jse/src/main/java/org/luaj/vm2/ast/NameResolver.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/NameResolver.java index 73ea1ede..6abd46a9 100644 --- a/luaj-jse/src/main/java/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,12 +25,13 @@ public class NameResolver extends Visitor { private void pushScope() { scope = new NameScope(scope); } + private void popScope() { scope = scope.outerScope; } - + public void visit(NameScope scope) { - } + } public void visit(Block block) { pushScope(); @@ -38,7 +39,7 @@ public class NameResolver extends Visitor { super.visit(block); popScope(); } - + public void visit(FuncBody body) { pushScope(); scope.functionNestingCount++; @@ -46,7 +47,7 @@ public class NameResolver extends Visitor { super.visit(body); popScope(); } - + public void visit(LocalFuncDef stat) { defineLocalVar(stat.name); super.visit(stat); @@ -63,7 +64,7 @@ public class NameResolver extends Visitor { public void visit(GenericFor stat) { pushScope(); stat.scope = scope; - defineLocalVars( stat.names ); + defineLocalVars(stat.names); super.visit(stat); popScope(); } @@ -72,16 +73,16 @@ public class NameResolver extends Visitor { exp.name.variable = resolveNameReference(exp.name); super.visit(exp); } - + public void visit(FuncDef stat) { stat.name.name.variable = resolveNameReference(stat.name.name); stat.name.name.variable.hasassignments = true; super.visit(stat); } - + public void visit(Assign stat) { super.visit(stat); - for ( int i=0, n=stat.vars.size(); i0 && m 0 && m < n && ((Exp) 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) + ((Name) stat.names.get(i)).variable.initialValue = ((Constant) stat.values.get(i)).value; + if (!isvarlist) + for (int i = m; i < n; i++) + ((Name) stat.names.get(i)).variable.initialValue = LuaValue.NIL; } 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 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 (Variable) 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/luaj-jse/src/main/java/org/luaj/vm2/ast/ParList.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/ParList.java index 76044806..a347eec9 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/ast/ParList.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/ParList.java @@ -26,10 +26,10 @@ 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 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/luaj-jse/src/main/java/org/luaj/vm2/ast/Stat.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Stat.java index 275fdfeb..f3010460 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/ast/Stat.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Stat.java @@ -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,11 @@ public class Stat extends SyntaxElement { public static class Goto extends Stat { public final String name; + public Goto(String name) { this.name = name; } + public void accept(Visitor visitor) { visitor.visit(this); } @@ -101,9 +103,11 @@ public class Stat extends SyntaxElement { public static class Label extends Stat { public final String name; + public Label(String name) { this.name = name; } + public void accept(Visitor visitor) { visitor.visit(this); } @@ -111,8 +115,8 @@ 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; @@ -125,95 +129,104 @@ 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; } + 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; } + public void accept(Visitor visitor) { - visitor.visit( this ); + visitor.visit(this); } } public static class Break extends Stat { 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; } 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 && ((Exp) 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; } 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; } 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; } 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; @@ -221,15 +234,16 @@ public class Stat extends SyntaxElement { } 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; @@ -239,31 +253,32 @@ public class Stat extends SyntaxElement { } 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; } 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; @@ -272,7 +287,7 @@ public class Stat extends SyntaxElement { } public void accept(Visitor visitor) { - visitor.visit( this ); + visitor.visit(this); } } } diff --git a/luaj-jse/src/main/java/org/luaj/vm2/ast/Str.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Str.java index dd682291..6fd44eb8 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/ast/Str.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Str.java @@ -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 = (int) (c[i++]-'0'); + for (int j = 0; i < n && j < 2 && c[i] >= '0' && c[i] <= '9'; i++, j++) + d = d*10+(int) (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/luaj-jse/src/main/java/org/luaj/vm2/ast/SyntaxElement.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/SyntaxElement.java index 8cd790e6..f42c858b 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/ast/SyntaxElement.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/SyntaxElement.java @@ -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/luaj-jse/src/main/java/org/luaj/vm2/ast/TableField.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/TableField.java index 2793f02d..6a606586 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/ast/TableField.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/TableField.java @@ -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/luaj-jse/src/main/java/org/luaj/vm2/ast/Variable.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Variable.java index 7405be42..69ff2e31 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/ast/Variable.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Variable.java @@ -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/luaj-jse/src/main/java/org/luaj/vm2/ast/Visitor.java b/luaj-jse/src/main/java/org/luaj/vm2/ast/Visitor.java index 8f49a566..d33a6069 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/ast/Visitor.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/ast/Visitor.java @@ -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: *

    *
  • {@link LuaValue#valueOf(boolean)}
  • *
  • {@link LuaValue#valueOf(byte[])}
  • @@ -47,69 +47,69 @@ import org.luaj.vm2.LuaValue; *
  • {@link LuaValue#valueOf(String)}
  • *
*

- * 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: *

    *
  • {@link LuaValue#listOf(LuaValue[])}
  • *
  • {@link LuaValue#listOf(LuaValue[], org.luaj.vm2.Varargs)}
  • *
  • {@link LuaValue#tableOf(LuaValue[])}
  • *
  • {@link LuaValue#tableOf(LuaValue[], LuaValue[], org.luaj.vm2.Varargs)}
  • *
- * 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 ); + static interface Coercion { + public LuaValue coerce(Object javaValue); }; - + private static final class BoolCoercion implements Coercion { - public LuaValue coerce( Object javaValue ) { + 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 ) { + 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 ) { + 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 ) { + 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() ); + public LuaValue coerce(Object javaValue) { + return LuaString.valueOf(javaValue.toString()); } } private static final class BytesCoercion implements Coercion { - public LuaValue coerce( Object javaValue ) { + public LuaValue coerce(Object javaValue) { return LuaValue.valueOf((byte[]) javaValue); } } private static final class ClassCoercion implements Coercion { - public LuaValue coerce( Object javaValue ) { + public LuaValue coerce(Object javaValue) { return JavaClass.forClass((Class) javaValue); } } @@ -128,46 +128,46 @@ public class CoerceJavaToLua { } private static final class LuaCoercion implements Coercion { - public LuaValue coerce( Object javaValue ) { + 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 +175,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/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/CoerceLuaToJava.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/CoerceLuaToJava.java index c658aacc..eb72abfc 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/CoerceLuaToJava.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/CoerceLuaToJava.java @@ -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: *

    *
  • {@link LuaValue#toboolean()}
  • *
  • {@link LuaValue#tobyte()}
  • @@ -51,41 +51,45 @@ import org.luaj.vm2.LuaValue; *
  • {@link LuaValue#touserdata(Class)}
  • *
*

- * 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; + + static interface Coercion { + public int score(LuaValue value); + + public 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 { public String toString() { return "BoolCoercion()"; } - public int score( LuaValue value ) { - switch ( value.type() ) { + + public int score(LuaValue value) { + switch (value.type()) { case LuaValue.TBOOLEAN: return 0; } @@ -98,74 +102,84 @@ public class CoerceLuaToJava { } 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; + public String toString() { - return "NumericCoercion("+TYPE_NAMES[targetType]+")"; + return "NumericCoercion(" + TYPE_NAMES[targetType] + ")"; } + NumericCoercion(int targetType) { this.targetType = targetType; } - public int score( LuaValue value ) { + + 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; @@ -173,45 +187,56 @@ public class CoerceLuaToJava { } 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 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; } } } 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; } + public String toString() { - return "StringCoercion("+(targetType==TARGET_TYPE_STRING? "String": "byte[]")+")"; + return "StringCoercion(" + (targetType == TARGET_TYPE_STRING? "String": "byte[]") + ")"; } + 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; } } + 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 +246,37 @@ 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); } + public String toString() { - return "ArrayCoercion("+componentType.getName()+")"; + return "ArrayCoercion(" + componentType.getName() + ")"; } + 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; } } + 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 */ @@ -43,44 +43,43 @@ class JavaArray extends LuaUserdata { private static final class LenFunction extends OneArgFunction { 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); } - + 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); } 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/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JavaClass.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JavaClass.java index 553c8e73..235d6c2e 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JavaClass.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JavaClass.java @@ -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,18 +51,18 @@ 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; @@ -71,14 +71,14 @@ class JavaClass extends JavaInstance implements CoerceJavaToLua.Coercion { 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; } - + 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,12 +82,13 @@ 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; } @@ -95,20 +96,20 @@ class JavaConstructor extends JavaMember { 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); } 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); } 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 +77,6 @@ class JavaInstance extends LuaUserdata { throw new LuaError(e); } super.set(key, value); - } - + } + } diff --git a/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JavaMember.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JavaMember.java index e4e9b7ed..886b7c40 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JavaMember.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JavaMember.java @@ -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); 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()) @@ -81,39 +81,39 @@ class JavaMethod extends JavaMember { public LuaValue call(LuaValue arg1, LuaValue arg2) { return invokeMethod(arg1.checkuserdata(), arg2); } - + public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { return invokeMethod(arg1.checkuserdata(), LuaValue.varargsOf(arg2, arg3)); } - + 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; } @@ -129,11 +129,11 @@ class JavaMethod extends JavaMember { public LuaValue call(LuaValue arg1, LuaValue arg2) { return invokeBestMethod(arg1.checkuserdata(), arg2); } - + public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { return invokeBestMethod(arg1.checkuserdata(), LuaValue.varargsOf(arg2, arg3)); } - + public Varargs invoke(Varargs args) { return invokeBestMethod(args.checkuserdata(1), args.subargs(2)); } @@ -141,20 +141,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()} - *

 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * globals.get("print").call(LuaValue.valueOf("hello, world"));
- * } 
+ * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	globals.get("print").call(LuaValue.valueOf("hello, world"));
+ * }
+ * 
*

- * 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: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JseBaseLib());
- * globals.get("print").call(LuaValue.valueOf("hello, world"));
- * } 
- *

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: + * + *

+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JseBaseLib());
+ * 	globals.get("print").call(LuaValue.valueOf("hello, world"));
+ * }
+ * 
+ *

+ * 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,18 +81,24 @@ 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} + /** + * 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. */ public LuaValue call(LuaValue modname, LuaValue env) { super.call(modname, env); @@ -87,30 +106,28 @@ public class JseBaseLib extends org.luaj.vm2.lib.BaseLib { return env; } - - /** - * Try to open a file in the current working directory, - * or fall back to base opener if not found. + /** + * 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). + * 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. */ 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/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseIoLib.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseIoLib.java index cfaf6f4a..99d4b6ac 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseIoLib.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseIoLib.java @@ -37,135 +37,157 @@ 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()} - *

 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
- * } 
+ * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
+ * }
+ * 
*

- * 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: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JseBaseLib());
- * globals.load(new PackageLib());
- * globals.load(new JseIoLib());
- * globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
- * } 
- *

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: + * + *

+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JseBaseLib());
+ * 	globals.load(new PackageLib());
+ * 	globals.load(new JseIoLib());
+ * 	globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
+ * }
+ * 
*

- * 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 { protected File wrapStdin() throws IOException { return new StdinFile(); } - + protected File wrapStdout() throws IOException { return new StdoutFile(FTYPE_STDOUT); } - + 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 ) { + + 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 ); + 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 "w".equals(mode)? new FileImpl(p.getOutputStream()): new FileImpl(p.getInputStream()); } protected File tmpFile() throws IOException { - java.io.File f = java.io.File.createTempFile(".luaj","bin"); + java.io.File f = java.io.File.createTempFile(".luaj", "bin"); f.deleteOnExit(); - return new FileImpl( new RandomAccessFile(f,"rw") ); + 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); } + public String tojstring() { - return "file (" + (this.closed ? "closed" : String.valueOf(this.hashCode())) + ")"; + return "file (" + (this.closed? "closed": String.valueOf(this.hashCode())) + ")"; } + public boolean isstdfile() { return file == null; } - public void close() throws IOException { + + public void close() throws IOException { closed = true; - if ( file != null ) { + if (file != null) { file.close(); } } + public void flush() throws IOException { - if ( os != null ) + if (os != null) os.flush(); } + 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(); } + public boolean isclosed() { return closed; } + 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 +197,24 @@ public class JseIoLib extends IoLib { notimplemented(); return 0; } + public void setvbuf(String mode, int size) { nobuffer = "no".equals(mode); } // get length remaining to read 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 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 +223,12 @@ public class JseIoLib extends IoLib { notimplemented(); return 0; } - + // return char if read, -1 if eof, throw IOException on other exception 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(); @@ -214,9 +237,9 @@ public class JseIoLib extends IoLib { // return number of bytes read if positive, -1 if eof, throws IOException 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(); @@ -233,14 +256,10 @@ public class JseIoLib extends IoLib { } 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 final PrintStream getPrintStream() { return file_type == FTYPE_STDERR? globals.STDERR: globals.STDOUT; } public void write(LuaString string) throws IOException { getPrintStream().write(string.m_bytes, string.m_offset, string.m_length); @@ -281,8 +300,7 @@ public class JseIoLib extends IoLib { return 0; } - public int read(byte[] bytes, int offset, int length) - throws IOException { + public int read(byte[] bytes, int offset, int length) throws IOException { return 0; } } @@ -292,7 +310,7 @@ public class JseIoLib extends IoLib { } public String tojstring() { - return "file ("+this.hashCode()+")"; + return "file (" + this.hashCode() + ")"; } public void write(LuaString string) throws IOException { @@ -335,8 +353,7 @@ public class JseIoLib extends IoLib { return globals.STDIN.read(); } - public int read(byte[] bytes, int offset, int length) - throws IOException { + public int read(byte[] bytes, int offset, int length) throws IOException { return globals.STDIN.read(bytes, offset, length); } } diff --git a/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseMathLib.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseMathLib.java index 87f133a1..516f8277 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseMathLib.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseMathLib.java @@ -26,58 +26,76 @@ 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()} - *

 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * System.out.println( globals.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
- * } 
+ * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	System.out.println(globals.get("math").get("sqrt").call(LuaValue.valueOf(2)));
+ * }
+ * 
*

- * 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: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JseBaseLib());
- * globals.load(new PackageLib());
- * globals.load(new JseMathLib());
- * System.out.println( globals.get("math").get("sqrt").call( LuaValue.valueOf(2) ) );
- * } 
- *

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: + * + *

+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JseBaseLib());
+ * 	globals.load(new PackageLib());
+ * 	globals.load(new JseMathLib());
+ * 	System.out.println(globals.get("math").get("sqrt").call(LuaValue.valueOf(2)));
+ * }
+ * 
*

- * 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. */ 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(); + LuaValue atan = new atan2(); math.set("atan", atan); math.set("atan2", atan); math.set("cosh", new cosh()); @@ -89,32 +107,53 @@ 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 { + 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 { 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 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 log extends TwoArgFunction { 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 { + 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); } + } /** Faster, better version of pow() used by arithmetic operator ^ */ public double dpow_lib(double a, double b) { return Math.pow(a, b); } - - -} +} diff --git a/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseOsLib.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseOsLib.java index af63c8af..af21d7cc 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseOsLib.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseOsLib.java @@ -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: *

    *
  • {@code execute()}
  • *
  • {@code remove()}
  • @@ -42,53 +43,65 @@ import org.luaj.vm2.lib.OsLib; *
  • {@code tmpname()}
  • *
*

- * 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()} - *

 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * System.out.println( globals.get("os").get("time").call() );
- * } 
+ * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	System.out.println(globals.get("os").get("time").call());
+ * }
+ * 
*

- * 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: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JseBaseLib());
- * globals.load(new PackageLib());
- * globals.load(new JseOsLib());
- * System.out.println( globals.get("os").get("time").call() );
- * } 
- *

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: + * + *

+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JseBaseLib());
+ * 	globals.load(new PackageLib());
+ * 	globals.load(new JseOsLib());
+ * 	System.out.println(globals.get("os").get("time").call());
+ * }
+ * 
*

+ * 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() { } protected String getenv(String varname) { String s = System.getenv(varname); - return s != null? s : System.getProperty(varname); + return s != null? s: System.getProperty(varname); } protected Varargs execute(String command) { @@ -109,27 +122,27 @@ public class JseOsLib extends org.luaj.vm2.lib.OsLib { 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"); } 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"); } 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/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JsePlatform.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JsePlatform.java index 00575aaf..7c5954b6 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JsePlatform.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JsePlatform.java @@ -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: - *

 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * globals.get("print").call(LuaValue.valueOf("hello, world"));
- * } 
+ * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	globals.get("print").call(LuaValue.valueOf("hello, world"));
+ * }
+ * 
*

* Once globals are created, a simple way to load and run a script is: - *

 {@code
+ * 
+ * 
+ *  {@code
  * globals.load( new FileInputStream("main.lua"), "main.lua" ).call();
- * } 
+ * } + *
*

* although {@code require} could also be used: - *

 {@code
+ * 
+ * 
+ *  {@code
  * globals.get("require").call(LuaValue.valueOf("main"));
- * } 
- * 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}: *

    *
  • {@link Globals}
  • *
  • {@link org.luaj.vm2.lib.jse.JseBaseLib}
  • @@ -72,9 +86,11 @@ import org.luaj.vm2.lib.TableLib; *
  • {@link org.luaj.vm2.lib.jse.JseOsLib}
  • *
  • {@link org.luaj.vm2.lib.jse.LuajavaLib}
  • *
- * 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. * @@ -108,9 +124,11 @@ public class JsePlatform { return globals; } - /** Create standard globals including the {@link DebugLib} library. + /** + * Create standard globals including the {@link DebugLib} library. * - * @return Table of globals initialized with the standard JSE and debug libraries + * @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/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseProcess.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseProcess.java index 3fcd79f1..42a5d528 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseProcess.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseProcess.java @@ -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. + /** + * 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. + * @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. + /** + * 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. + * @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,9 +100,8 @@ 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) { + 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,11 +110,10 @@ 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; @@ -114,7 +125,7 @@ public class JseProcess { 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/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseStringLib.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseStringLib.java index 41177787..87c9f097 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseStringLib.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/JseStringLib.java @@ -22,7 +22,7 @@ package org.luaj.vm2.lib.jse; public class JseStringLib extends org.luaj.vm2.lib.StringLib { - + /** public constructor */ public JseStringLib() { } @@ -30,7 +30,7 @@ public class JseStringLib extends org.luaj.vm2.lib.StringLib { protected String format(String src, double x) { String out; try { - out = String.format(src, new Object[] {Double.valueOf(x)}); + out = String.format(src, new Object[] { Double.valueOf(x) }); } catch (Throwable e) { out = super.format(src, x); } diff --git a/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/LuajavaLib.java b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/LuajavaLib.java index 35f1f850..53d46ccc 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/LuajavaLib.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/lib/jse/LuajavaLib.java @@ -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,40 +37,51 @@ 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()} - *

 {@code
- * Globals globals = JsePlatform.standardGlobals();
- * System.out.println( globals.get("luajava").get("bindClass").call( LuaValue.valueOf("java.lang.System") ).invokeMethod("currentTimeMillis") );
- * } 
+ * + *
+ * {
+ * 	@code
+ * 	Globals globals = JsePlatform.standardGlobals();
+ * 	System.out.println(globals.get("luajava").get("bindClass").call(LuaValue.valueOf("java.lang.System"))
+ * 		.invokeMethod("currentTimeMillis"));
+ * }
+ * 
*

- * To instantiate and use it directly, - * link it into your globals table via {@link Globals#load} using code such as: - *

 {@code
- * Globals globals = new Globals();
- * globals.load(new JseBaseLib());
- * globals.load(new PackageLib());
- * globals.load(new LuajavaLib());
- * globals.load(
- *      "sys = luajava.bindClass('java.lang.System')\n"+
- *      "print ( sys:currentTimeMillis() )\n", "main.lua" ).call();
- * } 
+ * To instantiate and use it directly, link it into your globals table via + * {@link Globals#load} using code such as: + * + *
+ * {
+ * 	@code
+ * 	Globals globals = new Globals();
+ * 	globals.load(new JseBaseLib());
+ * 	globals.load(new PackageLib());
+ * 	globals.load(new LuajavaLib());
+ * 	globals.load("sys = luajava.bindClass('java.lang.System')\n" + "print ( sys:currentTimeMillis() )\n", "main.lua")
+ * 		.call();
+ * }
+ * 
*

* - * 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 @@ -79,25 +89,20 @@ import org.luaj.vm2.lib.VarArgFunction; * @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() { @@ -105,14 +110,15 @@ public class LuajavaLib extends VarArgFunction { 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,30 +129,31 @@ 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,34 +49,33 @@ 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 +198,23 @@ public class JavaBuilder { main = new InstructionList(); // create the fields - for ( int i=0; i", - cg.getClassName(), init, cg.getConstantPool()); + 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,7 +276,7 @@ public class JavaBuilder { // add default constructor cg.addEmptyConstructor(Constants.ACC_PUBLIC); - + // gen method resolveBranches(); mg.setMaxStack(); @@ -285,18 +285,18 @@ public class JavaBuilder { // 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 +306,35 @@ public class JavaBuilder { cg.addMethod(mg.getMethod()); main.dispose(); } - + // 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,7 +349,7 @@ 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)); } @@ -358,14 +358,15 @@ public class JavaBuilder { 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 ) { + + 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(); + if (map.containsKey(islot)) + return ((Integer) map.get(islot)).intValue(); String name = prefix+slot; LocalVariableGen local = mg.addLocalVariable(name, type, null, null); int index = local.getIndex(); @@ -373,15 +374,15 @@ public class JavaBuilder { 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 +392,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 +413,13 @@ public class JavaBuilder { } public void createUpvalues(int pc, int firstslot, int numslots) { - for ( int i=0; i constants = new HashMap(); - + + private 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()); + 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 +193,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 +209,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) 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(); - + private Map 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(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(JavaGen jg, LuaValue env) { + include(jg); + return load(jg.classname, env); } - + public LuaFunction load(String classname, LuaValue env) { try { - Class c = loadClass( classname ); + Class c = loadClass(classname); LuaFunction v = (LuaFunction) c.newInstance(); v.initupvalue1(env); return v; - } catch ( Exception e ) { + } catch (Exception e) { e.printStackTrace(); - throw new IllegalStateException("bad class gen: "+e); + 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 - * 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) @@ -63,70 +65,75 @@ import 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; + + private static String toStub(String s) { + String stub = s.endsWith(".lua")? s.substring(0, s.length()-4): s; return stub; } } diff --git a/luaj-jse/src/main/java/org/luaj/vm2/luajc/ProtoInfo.java b/luaj-jse/src/main/java/org/luaj/vm2/luajc/ProtoInfo.java index 0d33f00a..fa302979 100644 --- a/luaj-jse/src/main/java/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) =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 +486,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; + includeVarAndPosteriorVars(pi.vars[slot][pc]); + for (int i = 0; i < nvars; i++) + var[i].allocupvalue = testIsAllocUpvalue(var[i]); + this.rw = nvars > 1; } - private boolean includeVarAndPosteriorVars( VarInfo var ) { - if ( var == null || var == VarInfo.INVALID ) + private boolean includeVarAndPosteriorVars(VarInfo var) { + if (var == null || var == VarInfo.INVALID) return false; - if ( var.upvalue == this ) + if (var.upvalue == this) return true; var.upvalue = this; - appendVar( var ); - if ( isLoopVariable( var ) ) + appendVar(var); + if (isLoopVariable(var)) return false; - boolean loopDetected = includePosteriorVarsCheckLoops( var ); - if ( loopDetected ) - includePriorVarsIgnoreLoops( var ); + 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]) ) { + if (var.pc >= 0) { + switch (Lua.GET_OPCODE(pi.prototype.code[var.pc])) { case Lua.OP_TFORLOOP: case Lua.OP_FORLOOP: return true; @@ -58,25 +58,25 @@ public class UpvalInfo { return false; } - private boolean includePosteriorVarsCheckLoops( VarInfo prior ) { + private boolean includePosteriorVarsCheckLoops(VarInfo prior) { boolean loopDetected = false; - for ( int i=0, n=pi.blocklist.length; i=b.pc0; pc-- ) { - if ( pi.vars[slot][pc] == prior ) { - loopDetected |= includeVarAndPosteriorVars( pi.vars[slot][pc+1] ); + for (int pc = b.pc1-1; pc >= b.pc0; pc--) { + if (pi.vars[slot][pc] == prior) { + loopDetected |= includeVarAndPosteriorVars(pi.vars[slot][pc+1]); break; } } @@ -84,22 +84,22 @@ public class UpvalInfo { } return loopDetected; } - + private void includePriorVarsIgnoreLoops(VarInfo poster) { - for ( int i=0, n=pi.blocklist.length; i= var.length ) { + } else if (nvars+1 >= var.length) { VarInfo[] s = var; var = new VarInfo[nvars*2+1]; - System.arraycopy(s, 0, var, 0, nvars); + System.arraycopy(s, 0, var, 0, nvars); } var[nvars++] = v; } public String toString() { StringBuffer sb = new StringBuffer(); - sb.append( pi.name ); - for ( int i=0; i0? ",": " " ); - sb.append( String.valueOf(var[i])); + 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)" ); + if (rw) + sb.append("(rw)"); return sb.toString(); } - + private boolean testIsAllocUpvalue(VarInfo v) { - if ( v.pc < 0 ) + if (v.pc < 0) return true; BasicBlock b = pi.blocks[v.pc]; - if ( v.pc > b.pc0 ) + if (v.pc > b.pc0) return pi.vars[slot][v.pc-1].upvalue != this; - if ( b.prev == null ) { + if (b.prev == null) { v = pi.params[slot]; - if ( v != null && v.upvalue != this ) + if (v != null && v.upvalue != this) return true; } else { - for ( int i=0, n=b.prev.length; 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("}"); @@ -119,7 +117,7 @@ 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 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 +80,18 @@ 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 { + 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(); } - } catch ( Exception e ) { - throw new ScriptException("eval threw "+e.toString()); + } catch (Exception e) { + throw new ScriptException("eval threw " + e.toString()); } } @@ -116,49 +116,43 @@ 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; + public ScriptEngine getEngine() { return LuaScriptEngine.this; } + + 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)); + 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)); + + 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); @@ -178,37 +172,37 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin 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; } 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() { public LuaValue call(LuaValue table, LuaValue key) { - if (key.isstring()) + if (key.isstring()) return toLua(bindings.get(key.tojstring())); else return this.rawget(key); @@ -231,33 +225,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) new Integer(luajValue.toint()) + : (Object) new Double(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 List mimeTypes; - private List names; - - public LuaScriptEngineFactory() { - extensions = Arrays.asList(EXTENSIONS); - mimeTypes = Arrays.asList(MIMETYPES); - names = Arrays.asList(NAMES); - } - - public String getEngineName() { - return getScriptEngine().get(ScriptEngine.ENGINE).toString(); - } - - public String getEngineVersion() { - return getScriptEngine().get(ScriptEngine.ENGINE_VERSION).toString(); - } - - public List getExtensions() { - return extensions; - } - - public List getMimeTypes() { - return mimeTypes; - } - - public List getNames() { - return names; - } - - public String getLanguageName() { - return getScriptEngine().get(ScriptEngine.LANGUAGE).toString(); - } - - public String getLanguageVersion() { - return getScriptEngine().get(ScriptEngine.LANGUAGE_VERSION).toString(); - } - - public Object getParameter(String key) { - return getScriptEngine().get(key).toString(); - } - - 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(); - } - - public String getOutputStatement(String toDisplay) { - return "print(" + toDisplay + ")"; - } - - 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(); - } - - public ScriptEngine getScriptEngine() { - return new LuaScriptEngine(); - } + + private static final String[] EXTENSIONS = { "lua", ".lua", }; + + private static final String[] MIMETYPES = { "text/lua", "application/lua" }; + + private static final String[] NAMES = { "lua", "luaj", }; + + private List extensions; + private List mimeTypes; + private List names; + + public LuaScriptEngineFactory() { + extensions = Arrays.asList(EXTENSIONS); + mimeTypes = Arrays.asList(MIMETYPES); + names = Arrays.asList(NAMES); + } + + public String getEngineName() { return getScriptEngine().get(ScriptEngine.ENGINE).toString(); } + + public String getEngineVersion() { return getScriptEngine().get(ScriptEngine.ENGINE_VERSION).toString(); } + + public List getExtensions() { return extensions; } + + public List getMimeTypes() { return mimeTypes; } + + public List getNames() { return names; } + + public String getLanguageName() { return getScriptEngine().get(ScriptEngine.LANGUAGE).toString(); } + + public String getLanguageVersion() { return getScriptEngine().get(ScriptEngine.LANGUAGE_VERSION).toString(); } + + public Object getParameter(String key) { + return getScriptEngine().get(key).toString(); + } + + 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(); + } + + public String getOutputStatement(String toDisplay) { + return "print(" + toDisplay + ")"; + } + + 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(); + } + + public ScriptEngine getScriptEngine() { return new LuaScriptEngine(); } } diff --git a/luaj-jse/src/main/java/org/luaj/vm2/script/LuajContext.java b/luaj-jse/src/main/java/org/luaj/vm2/script/LuajContext.java index 4668e41c..417caa8d 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/script/LuajContext.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/script/LuajContext.java @@ -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,90 @@ 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; } + public void write(int b) throws IOException { - w.write(new String(new byte[] {(byte)b})); + w.write(new String(new byte[] { (byte) b })); } + public void write(byte[] b, int o, int l) throws IOException { w.write(new String(b, o, l)); } + public void write(byte[] b) throws IOException { w.write(new String(b)); } + public void close() throws IOException { w.close(); } + public void flush() throws IOException { w.flush(); } } - + static final class ReaderInputStream extends InputStream { final Reader r; + ReaderInputStream(Reader r) { this.r = r; } + public int read() throws IOException { return r.read(); } diff --git a/luaj-jse/src/main/java/org/luaj/vm2/server/DefaultLauncher.java b/luaj-jse/src/main/java/org/luaj/vm2/server/DefaultLauncher.java index 098f64a4..73e0491b 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/server/DefaultLauncher.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/server/DefaultLauncher.java @@ -31,13 +31,13 @@ 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 @@ -51,13 +51,15 @@ public class DefaultLauncher implements Launcher { public DefaultLauncher() { g = JsePlatform.standardGlobals(); } - + /** Launches the script with chunk name 'main' */ 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' + */ public Object[] launch(InputStream script, Object[] arg) { return launchChunk(g.load(script, "main", "bt", g), arg); } @@ -102,4 +104,4 @@ public class DefaultLauncher implements Launcher { } return return_values; } -} \ No newline at end of file +} diff --git a/luaj-jse/src/main/java/org/luaj/vm2/server/Launcher.java b/luaj-jse/src/main/java/org/luaj/vm2/server/Launcher.java index 378f7c81..3d236be6 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/server/Launcher.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/server/Launcher.java @@ -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. + + /** + * Launch a script contained in a String. * - * @param script The script contents. - * @param arg Optional arguments supplied to the script. + * @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); + public Object[] launch(String script, Object[] arg); - /** Launch a script from an InputStream. + /** + * Launch a script from an InputStream. * - * @param script The script as an InputStream. - * @param arg Optional arguments supplied to the script. + * @param script The script as an InputStream. + * @param arg Optional arguments supplied to the script. * @return return values from the script. */ - public Object[] launch(InputStream script, Object[] arg); + public Object[] launch(InputStream script, Object[] arg); - /** Launch a script from a Reader. + /** + * Launch a script from a Reader. * - * @param script The script as a Reader. - * @param arg Optional arguments supplied to the script. + * @param script The script as a Reader. + * @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 +} diff --git a/luaj-jse/src/main/java/org/luaj/vm2/server/LuajClassLoader.java b/luaj-jse/src/main/java/org/luaj/vm2/server/LuajClassLoader.java index 3886c1f8..4e3d75d6 100644 --- a/luaj-jse/src/main/java/org/luaj/vm2/server/LuajClassLoader.java +++ b/luaj-jse/src/main/java/org/luaj/vm2/server/LuajClassLoader.java @@ -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 @@ -61,10 +61,14 @@ 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. */ @@ -75,54 +79,52 @@ public class LuajClassLoader extends ClassLoader { * 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. + * 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. + * @return instance of type 'launcher_class' that can be used to launch + * scripts. * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException */ public static Launcher NewLauncher(Class 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); } public Class loadClass(String classname) throws ClassNotFoundException { @@ -143,13 +145,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/luaj-test/src/test/java/org/luaj/luajc/SampleMainChunk.java b/luaj-test/src/test/java/org/luaj/luajc/SampleMainChunk.java index 87168ada..4d697f44 100644 --- a/luaj-test/src/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/luaj-test/src/test/java/org/luaj/luajc/TestLuaJ.java b/luaj-test/src/test/java/org/luaj/luajc/TestLuaJ.java index eee17c5c..cbd8d7b5 100644 --- a/luaj-test/src/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/vm2/AllTests.java b/luaj-test/src/test/java/org/luaj/vm2/AllTests.java index 0062371f..99a7bff7 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/AllTests.java +++ b/luaj-test/src/test/java/org/luaj/vm2/AllTests.java @@ -64,17 +64,17 @@ public class AllTests { table.addTestSuite(WeakKeyTableTest.class); table.addTestSuite(WeakKeyValueTableTest.class); suite.addTest(table); - + // bytecode compilers regression tests TestSuite bytecodetests = FragmentsTest.suite(); suite.addTest(bytecodetests); - + // I/O tests TestSuite io = new TestSuite("I/O Tests"); io.addTestSuite(BufferedStreamTest.class); io.addTestSuite(UTF8StreamTest.class); suite.addTest(io); - + // prototype compiler TestSuite compiler = new TestSuite("Lua Compiler Tests"); compiler.addTestSuite(CompilerUnitTests.class); @@ -83,7 +83,7 @@ public class AllTests { compiler.addTestSuite(RegressionTests.class); compiler.addTestSuite(SimpleTests.class); suite.addTest(compiler); - + // library tests TestSuite lib = new TestSuite("Library Tests"); lib.addTestSuite(JsePlatformTest.class); @@ -97,12 +97,12 @@ public class AllTests { // Script engine tests. TestSuite script = ScriptEngineTests.suite(); suite.addTest(script); - + // compatiblity tests TestSuite compat = CompatibiltyTest.suite(); suite.addTest(compat); compat.addTestSuite(ErrorsTest.class); - + return suite; } diff --git a/luaj-test/src/test/java/org/luaj/vm2/BufferedStreamTest.java b/luaj-test/src/test/java/org/luaj/vm2/BufferedStreamTest.java index 45161a2e..9e2a2934 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/BufferedStreamTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/BufferedStreamTest.java @@ -27,26 +27,25 @@ import junit.framework.TestCase; import org.luaj.vm2.Globals.BufferedStream; - public class BufferedStreamTest extends TestCase { public BufferedStreamTest() {} - + private BufferedStream NewBufferedStream(int buflen, String contents) { return new BufferedStream(buflen, new ByteArrayInputStream(contents.getBytes())); } - + protected void setUp() throws Exception { super.setUp(); } - + public void testReadEmptyStream() throws java.io.IOException { BufferedStream bs = NewBufferedStream(4, ""); assertEquals(-1, bs.read()); assertEquals(-1, bs.read(new byte[10])); assertEquals(-1, bs.read(new byte[10], 0, 10)); } - + public void testReadByte() throws java.io.IOException { BufferedStream bs = NewBufferedStream(2, "abc"); assertEquals('a', bs.read()); @@ -54,7 +53,7 @@ public class BufferedStreamTest extends TestCase { assertEquals('c', bs.read()); assertEquals(-1, bs.read()); } - + public void testReadByteArray() throws java.io.IOException { byte[] array = new byte[3]; BufferedStream bs = NewBufferedStream(4, "abcdef"); @@ -66,7 +65,7 @@ public class BufferedStreamTest extends TestCase { assertEquals("ef", new String(array, 0, 2)); assertEquals(-1, bs.read()); } - + public void testReadByteArrayOffsetLength() throws java.io.IOException { byte[] array = new byte[10]; BufferedStream bs = NewBufferedStream(8, "abcdefghijklmn"); @@ -78,7 +77,7 @@ public class BufferedStreamTest extends TestCase { assertEquals("ijklmn", new String(array, 0, 6)); assertEquals(-1, bs.read()); } - + public void testMarkOffsetBeginningOfStream() throws java.io.IOException { byte[] array = new byte[4]; BufferedStream bs = NewBufferedStream(8, "abcdefghijkl"); diff --git a/luaj-test/src/test/java/org/luaj/vm2/CompatibiltyTest.java b/luaj-test/src/test/java/org/luaj/vm2/CompatibiltyTest.java index 36ae746b..1e62d75e 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/CompatibiltyTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/CompatibiltyTest.java @@ -28,19 +28,20 @@ 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. + * Results are compared for exact match with the installed C-based lua + * environment. */ public class CompatibiltyTest extends TestSuite { private static final String dir = ""; - - abstract protected static class CompatibiltyTestSuite extends ScriptDrivenTest { + + abstract protected static class CompatibiltyTestSuite extends ScriptDrivenTest { LuaValue savedStringMetatable; + protected CompatibiltyTestSuite(PlatformType platform) { - super(platform,dir); + super(platform, dir); } - + protected void setUp() throws Exception { savedStringMetatable = LuaString.s_metatable; super.setUp(); @@ -56,60 +57,79 @@ public class CompatibiltyTest extends TestSuite { LuaString.s_metatable = savedStringMetatable; } - public void testBaseLib() { runTest("baselib"); } - public void testCoroutineLib() { runTest("coroutinelib"); } - public void testDebugLib() { runTest("debuglib"); } - public void testErrors() { runTest("errors"); } - public void testFunctions() { runTest("functions"); } - public void testIoLib() { runTest("iolib"); } - public void testManyUpvals() { runTest("manyupvals"); } - public void testMathLib() { runTest("mathlib"); } - public void testMetatags() { runTest("metatags"); } - public void testOsLib() { runTest("oslib"); } - public void testStringLib() { runTest("stringlib"); } - public void testTableLib() { runTest("tablelib"); } - public void testTailcalls() { runTest("tailcalls"); } - public void testUpvalues() { runTest("upvalues"); } - public void testVm() { runTest("vm"); } - } + public void testBaseLib() { runTest("baselib"); } + public void testCoroutineLib() { runTest("coroutinelib"); } + + public void testDebugLib() { runTest("debuglib"); } + + public void testErrors() { runTest("errors"); } + + public void testFunctions() { runTest("functions"); } + + public void testIoLib() { runTest("iolib"); } + + public void testManyUpvals() { runTest("manyupvals"); } + + public void testMathLib() { runTest("mathlib"); } + + public void testMetatags() { runTest("metatags"); } + + public void testOsLib() { runTest("oslib"); } + + public void testStringLib() { runTest("stringlib"); } + + public void testTableLib() { runTest("tablelib"); } + + public void testTailcalls() { runTest("tailcalls"); } + + public void testUpvalues() { runTest("upvalues"); } + + public void testVm() { runTest("vm"); } + } public static TestSuite suite() { TestSuite suite = new TestSuite("Compatibility Tests"); - suite.addTest( new TestSuite( JseCompatibilityTest.class, "JSE Compatibility Tests" ) ); - suite.addTest( new TestSuite( JmeCompatibilityTest.class, "JME Compatibility Tests" ) ); - suite.addTest( new TestSuite( LuaJCCompatibilityTest.class, "LuaJC Compatibility Tests" ) ); + suite.addTest(new TestSuite(JseCompatibilityTest.class, "JSE Compatibility Tests")); + suite.addTest(new TestSuite(JmeCompatibilityTest.class, "JME Compatibility Tests")); + suite.addTest(new TestSuite(LuaJCCompatibilityTest.class, "LuaJC Compatibility Tests")); return suite; } - + public static class JmeCompatibilityTest extends CompatibiltyTestSuite { public JmeCompatibilityTest() { super(ScriptDrivenTest.PlatformType.JME); } + protected void setUp() throws Exception { System.setProperty("JME", "true"); super.setUp(); } } + public static class JseCompatibilityTest extends CompatibiltyTestSuite { public JseCompatibilityTest() { super(ScriptDrivenTest.PlatformType.JSE); } + protected void setUp() throws Exception { super.setUp(); System.setProperty("JME", "false"); } } + public static class LuaJCCompatibilityTest extends CompatibiltyTestSuite { public LuaJCCompatibilityTest() { super(ScriptDrivenTest.PlatformType.LUAJIT); } + protected void setUp() throws Exception { super.setUp(); System.setProperty("JME", "false"); LuaJC.install(globals); } + // not supported on this platform - don't test - public void testDebugLib() {} + public void testDebugLib() {} } } diff --git a/luaj-test/src/test/java/org/luaj/vm2/ErrorsTest.java b/luaj-test/src/test/java/org/luaj/vm2/ErrorsTest.java index 264d3d4d..f0e13eaf 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/ErrorsTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/ErrorsTest.java @@ -24,12 +24,11 @@ package org.luaj.vm2; import java.io.IOException; import java.io.InputStream; - /** * 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 { @@ -38,26 +37,34 @@ public class ErrorsTest extends ScriptDrivenTest { public ErrorsTest() { super(ScriptDrivenTest.PlatformType.JSE, dir); } - + protected void setUp() throws Exception { super.setUp(); } - public void testBaseLibArgs() { + public void testBaseLibArgs() { globals.STDIN = new InputStream() { 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"); } - + + 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"); } + } diff --git a/luaj-test/src/test/java/org/luaj/vm2/FragmentsTest.java b/luaj-test/src/test/java/org/luaj/vm2/FragmentsTest.java index 822f92b4..d25edfeb 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/FragmentsTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/FragmentsTest.java @@ -30,44 +30,46 @@ import junit.framework.TestSuite; 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. +/** + * Test compilation of various fragments that have caused problems for jit + * compiling during development. * */ public class FragmentsTest extends TestSuite { - static final int TEST_TYPE_LUAC = 0; - static final int TEST_TYPE_LUAJC = 1; + static final int TEST_TYPE_LUAC = 0; + static final int TEST_TYPE_LUAJC = 1; public static class JseFragmentsTest extends FragmentsTestCase { - public JseFragmentsTest() { super( TEST_TYPE_LUAC ); } + public JseFragmentsTest() { super(TEST_TYPE_LUAC); } } + public static class LuaJCFragmentsTest extends FragmentsTestCase { - public LuaJCFragmentsTest() { super( TEST_TYPE_LUAJC ); } + public LuaJCFragmentsTest() { super(TEST_TYPE_LUAJC); } } + public static TestSuite suite() { TestSuite suite = new TestSuite("Compiler Fragments Tests"); - suite.addTest( new TestSuite( JseFragmentsTest.class, "JSE Fragments Tests" ) ); - suite.addTest( new TestSuite( LuaJCFragmentsTest.class, "LuaJC Fragments Tests" ) ); + suite.addTest(new TestSuite(JseFragmentsTest.class, "JSE Fragments Tests")); + suite.addTest(new TestSuite(LuaJCFragmentsTest.class, "LuaJC Fragments Tests")); return suite; } - - abstract protected static class FragmentsTestCase extends TestCase { - + + abstract protected static class FragmentsTestCase extends TestCase { + final int TEST_TYPE; protected FragmentsTestCase(int testType) { this.TEST_TYPE = testType; } - - public void runFragment( Varargs expected, String script ) { + + public void runFragment(Varargs expected, String script) { try { String name = getName(); Globals globals = JsePlatform.debugGlobals(); Reader reader = new StringReader(script); - LuaValue chunk ; - switch ( TEST_TYPE ) { + LuaValue chunk; + switch (TEST_TYPE) { case TEST_TYPE_LUAJC: LuaJC.install(globals); chunk = globals.load(reader, name); @@ -79,534 +81,321 @@ public class FragmentsTest extends TestSuite { 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) ); + 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()); - } + } } - + public void testFirstArgNilExtended() { - runFragment( LuaValue.NIL, - "function f1(a) print( 'f1:', a ) return a end\n" + - "b = f1()\n" + - "return b" ); + runFragment(LuaValue.NIL, "function f1(a) print( 'f1:', a ) return a end\n" + "b = f1()\n" + "return b"); } 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"); - + runFragment(LuaValue.valueOf(77), + "for n,p in ipairs({77}) do\n" + " print('n,p',n,p)\n" + " return p\n" + "end\n"); + } - + 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"); - + 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"); + } - + 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" ); + 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"); } - + public void testArgParamUseNone() { - runFragment( LuaValue.valueOf("string"), - "function v(arg,...)\n" + - " return type(arg)\n" + - "end\n" + - "return v('abc')\n" ); + runFragment(LuaValue.valueOf("string"), + "function v(arg,...)\n" + " return type(arg)\n" + "end\n" + "return v('abc')\n"); } public void testSetlistVarargs() { - runFragment( LuaValue.valueOf("abc"), - "local f = function() return 'abc' end\n" + - "local g = { f() }\n" + - "return g[1]\n" ); + runFragment(LuaValue.valueOf("abc"), + "local f = function() return 'abc' end\n" + "local g = { f() }\n" + "return g[1]\n"); } - + public void testSelfOp() { - runFragment( LuaValue.valueOf("bcd"), - "local s = 'abcde'\n"+ - "return s:sub(2,4)\n" ); + runFragment(LuaValue.valueOf("bcd"), "local s = 'abcde'\n" + "return s:sub(2,4)\n"); } - + public void testSetListWithOffsetAndVarargs() { - runFragment( LuaValue.valueOf(1003), - "local bar = {1000, math.sqrt(9)}\n"+ - "return bar[1]+bar[2]\n" ); + runFragment(LuaValue.valueOf(1003), "local bar = {1000, math.sqrt(9)}\n" + "return bar[1]+bar[2]\n"); } - + 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" ); + 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"); } - + 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" ); + 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"); } - + 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" ); + 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"); } - + 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" ); + 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"); } - + 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" ); - + 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"); + } - + 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" ); + 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"); } - + 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" ); + 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"); } - + 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" ); - + 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"); + } - + 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" ); - + 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"); + } + public void testVarargsWithParameters() { - runFragment( LuaValue.valueOf(222), - "local func = function(t,...)\n"+ - " return (...)\n"+ - "end\n"+ - "return func(111,222,333)\n" ); + runFragment(LuaValue.valueOf(222), + "local func = function(t,...)\n" + " return (...)\n" + "end\n" + "return func(111,222,333)\n"); } - + public void testNoReturnValuesPlainCall() { - runFragment( LuaValue.TRUE, - "local testtable = {}\n"+ - "return pcall( function() testtable[1]=2 end )\n" ); + runFragment(LuaValue.TRUE, "local testtable = {}\n" + "return pcall( function() testtable[1]=2 end )\n"); } - + 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" ); + 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"); } - + 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" ); + 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"); } - + 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" ); + runFragment(LuaValue.valueOf("b"), "local aliases = {a='b'}\n" + "local foo = function()\n" + + " return aliases\n" + "end\n" + "return foo().a\n"); } - - + public void testLoadNilUpvalue() { - runFragment( LuaValue.NIL, - "tostring = function() end\n" + - "local pc \n" + - "local pcall = function(...)\n" + - " pc(...)\n" + - "end\n" + - "return NIL\n" ); + runFragment(LuaValue.NIL, "tostring = function() end\n" + "local pc \n" + "local pcall = function(...)\n" + + " pc(...)\n" + "end\n" + "return NIL\n"); } - + 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" ); + runFragment(LuaValue.NIL, "print()\n" + "local function f2() end\n" + "local function f3()\n" + + " return f3\n" + "end\n" + "return NIL\n"); } - + public void testUninitializedUpvalue() { - runFragment( LuaValue.NIL, - "local f\n"+ - "do\n"+ - " function g()\n"+ - " print(f())\n"+ - " end\n"+ - "end\n" + - "return NIL\n" ); + runFragment(LuaValue.NIL, "local f\n" + "do\n" + " function g()\n" + " print(f())\n" + " end\n" + + "end\n" + "return NIL\n"); } - + 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" ); + 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"); } + 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" ); + 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"); } - + 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"); + 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"); } - + 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"); + 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"); } - + 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" ); + 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"); } - + public void testUninitializedAroundBranch() { - runFragment( LuaValue.valueOf(333), - "local state\n"+ - "if _G then\n"+ - " state = 333\n"+ - "end\n"+ - "return state\n" ); + runFragment(LuaValue.valueOf(333), + "local state\n" + "if _G then\n" + " state = 333\n" + "end\n" + "return state\n"); } - + 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" ); + 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"); } - + 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]"); + 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]"); } - + 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" ); + 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"); } - + 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" ); + 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"); } - + 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" ); + 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"); } - + 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" ); + 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"); } - + 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" ); + 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"); } - + 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" ); + 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"); } - + 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" ); + 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"); } - + 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" ); + runFragment(LuaValue.valueOf(5), + "local a\n" + "local w\n" + "repeat\n" + " a = w\n" + "until not a\n" + "return 5\n"); } - + 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"); + 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"); } - + 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"); + 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"); } - + 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"); + 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"); } - + public void testUpvalueInDoBlock() { - runFragment( LuaValue.NONE, "do\n"+ - " local x = 10\n"+ - " function g()\n"+ - " return x\n"+ - " end\n"+ - "end\n"+ - "g()\n"); + runFragment(LuaValue.NONE, + "do\n" + " local x = 10\n" + " function g()\n" + " return x\n" + " end\n" + "end\n" + "g()\n"); } - + public void testNullError() { - runFragment( LuaValue.varargsOf(LuaValue.FALSE, LuaValue.NIL), - "return pcall(error)\n"); + runFragment(LuaValue.varargsOf(LuaValue.FALSE, LuaValue.NIL), "return pcall(error)\n"); } 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"); + 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"); } public void testErrorArgIsString() { runFragment(LuaValue.varargsOf(LuaValue.valueOf("string"), LuaValue.valueOf("c")), - "a,b = pcall(error, 'c'); return type(b), b\n"); + "a,b = pcall(error, 'c'); return type(b), b\n"); } + public void testErrorArgIsNil() { runFragment(LuaValue.varargsOf(LuaValue.valueOf("nil"), LuaValue.NIL), - "a,b = pcall(error); return type(b), b\n"); + "a,b = pcall(error); return type(b), b\n"); } + public void testErrorArgIsTable() { runFragment(LuaValue.varargsOf(LuaValue.valueOf("table"), LuaValue.valueOf("d")), - "a,b = pcall(error, {c='d'}); return type(b), b.c\n"); + "a,b = pcall(error, {c='d'}); return type(b), b.c\n"); } + public void testErrorArgIsNumber() { runFragment(LuaValue.varargsOf(LuaValue.valueOf("string"), LuaValue.valueOf("1")), - "a,b = pcall(error, 1); return type(b), b\n"); + "a,b = pcall(error, 1); return type(b), b\n"); } + public void testErrorArgIsBool() { runFragment(LuaValue.varargsOf(LuaValue.valueOf("boolean"), LuaValue.TRUE), - "a,b = pcall(error, true); return type(b), b\n"); + "a,b = pcall(error, true); return type(b), b\n"); } + public void testBalancedMatchOnEmptyString() { runFragment(LuaValue.NIL, "return (\"\"):match(\"%b''\")\n"); } + public void testReturnValueForTableRemove() { runFragment(LuaValue.NONE, "return table.remove({ })"); } + public void testTypeOfTableRemoveReturnValue() { runFragment(LuaValue.valueOf("nil"), "local k = table.remove({ }) return type(k)"); } + 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"); - + 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/luaj-test/src/test/java/org/luaj/vm2/LoadOrderTest.java b/luaj-test/src/test/java/org/luaj/vm2/LoadOrderTest.java index de8ae6a0..35a8082e 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/LoadOrderTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/LoadOrderTest.java @@ -61,8 +61,7 @@ public class LoadOrderTest extends TestCase { } public void testClassLoadsStringFirst() throws Exception { - Launcher launcher = LuajClassLoader - .NewLauncher(TestLauncherLoadStringFirst.class); + Launcher launcher = LuajClassLoader.NewLauncher(TestLauncherLoadStringFirst.class); Object[] results = launcher.launch("foo", null); assertNotNull(results); } diff --git a/luaj-test/src/test/java/org/luaj/vm2/LuaOperationsTest.java b/luaj-test/src/test/java/org/luaj/vm2/LuaOperationsTest.java index 84231586..456869b6 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/LuaOperationsTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/LuaOperationsTest.java @@ -32,103 +32,106 @@ import org.luaj.vm2.compiler.LuaC; import org.luaj.vm2.lib.ZeroArgFunction; public class LuaOperationsTest extends TestCase { - - private final int sampleint = 77; - private final long samplelong = 123400000000L; - private final double sampledouble = 55.25; + + private final int sampleint = 77; + private final long samplelong = 123400000000L; + private final double sampledouble = 55.25; private final String samplestringstring = "abcdef"; - private final String samplestringint = String.valueOf(sampleint); - private final String samplestringlong = String.valueOf(samplelong); + private final String samplestringint = String.valueOf(sampleint); + private final String samplestringlong = String.valueOf(samplelong); private final String samplestringdouble = String.valueOf(sampledouble); - private final Object sampleobject = new Object(); - private final MyData sampledata = new MyData(); - - private final LuaValue somenil = LuaValue.NIL; - private final LuaValue sometrue = LuaValue.TRUE; - private final LuaValue somefalse = LuaValue.FALSE; - private final LuaValue zero = LuaValue.ZERO; - private final LuaValue intint = LuaValue.valueOf(sampleint); - private final LuaValue longdouble = LuaValue.valueOf(samplelong); - private final LuaValue doubledouble = LuaValue.valueOf(sampledouble); - private final LuaValue stringstring = LuaValue.valueOf(samplestringstring); - private final LuaValue stringint = LuaValue.valueOf(samplestringint); - private final LuaValue stringlong = LuaValue.valueOf(samplestringlong); - private final LuaValue stringdouble = LuaValue.valueOf(samplestringdouble); - private final LuaTable table = LuaValue.listOf( new LuaValue[] { LuaValue.valueOf("aaa"), LuaValue.valueOf("bbb") } ); - private final LuaValue somefunc = new ZeroArgFunction() { public LuaValue call() { return NONE;}}; - private final LuaThread thread = new LuaThread(new Globals(), somefunc); - private final Prototype proto = new Prototype(1); - private final LuaClosure someclosure = new LuaClosure(proto,table); - private final LuaUserdata userdataobj = LuaValue.userdataOf(sampleobject); - private final LuaUserdata userdatacls = LuaValue.userdataOf(sampledata); - + private final Object sampleobject = new Object(); + private final MyData sampledata = new MyData(); + + private final LuaValue somenil = LuaValue.NIL; + private final LuaValue sometrue = LuaValue.TRUE; + private final LuaValue somefalse = LuaValue.FALSE; + private final LuaValue zero = LuaValue.ZERO; + private final LuaValue intint = LuaValue.valueOf(sampleint); + private final LuaValue longdouble = LuaValue.valueOf(samplelong); + private final LuaValue doubledouble = LuaValue.valueOf(sampledouble); + private final LuaValue stringstring = LuaValue.valueOf(samplestringstring); + private final LuaValue stringint = LuaValue.valueOf(samplestringint); + private final LuaValue stringlong = LuaValue.valueOf(samplestringlong); + private final LuaValue stringdouble = LuaValue.valueOf(samplestringdouble); + private final LuaTable table = LuaValue + .listOf(new LuaValue[] { LuaValue.valueOf("aaa"), LuaValue.valueOf("bbb") }); + private final LuaValue somefunc = new ZeroArgFunction() { + public LuaValue call() { return NONE; } + }; + private final LuaThread thread = new LuaThread(new Globals(), somefunc); + private final Prototype proto = new Prototype(1); + private final LuaClosure someclosure = new LuaClosure(proto, table); + private final LuaUserdata userdataobj = LuaValue.userdataOf(sampleobject); + private final LuaUserdata userdatacls = LuaValue.userdataOf(sampledata); + private void throwsLuaError(String methodName, Object obj) { try { LuaValue.class.getMethod(methodName).invoke(obj); fail("failed to throw LuaError as required"); } catch (InvocationTargetException e) { - if ( ! (e.getTargetException() instanceof LuaError) ) - fail("not a LuaError: "+e.getTargetException()); + if (!(e.getTargetException() instanceof LuaError)) + fail("not a LuaError: " + e.getTargetException()); return; // pass - } catch ( Exception e ) { - fail( "bad exception: "+e ); + } catch (Exception e) { + fail("bad exception: " + e); } } - - private void throwsLuaError(String methodName, Object obj, Object arg) { - try { - LuaValue.class.getMethod(methodName,LuaValue.class).invoke(obj,arg); - fail("failed to throw LuaError as required"); - } catch (InvocationTargetException e) { - if ( ! (e.getTargetException() instanceof LuaError) ) - fail("not a LuaError: "+e.getTargetException()); - return; // pass - } catch ( Exception e ) { - fail( "bad exception: "+e ); - } - } - - public void testLen() { - throwsLuaError( "len", somenil ); - throwsLuaError( "len", sometrue ); - throwsLuaError( "len", somefalse ); - throwsLuaError( "len", zero ); - throwsLuaError( "len", intint ); - throwsLuaError( "len", longdouble ); - throwsLuaError( "len", doubledouble ); - assertEquals( LuaInteger.valueOf(samplestringstring.length()), stringstring.len() ); - assertEquals( LuaInteger.valueOf(samplestringint.length()), stringint.len() ); - assertEquals( LuaInteger.valueOf(samplestringlong.length()), stringlong.len() ); - assertEquals( LuaInteger.valueOf(samplestringdouble.length()), stringdouble.len() ); - assertEquals( LuaInteger.valueOf(2), table.len() ); - throwsLuaError( "len", somefunc ); - throwsLuaError( "len", thread ); - throwsLuaError( "len", someclosure ); - throwsLuaError( "len", userdataobj ); - throwsLuaError( "len", userdatacls ); - } - - public void testLength() { - throwsLuaError( "length", somenil ); - throwsLuaError( "length", sometrue ); - throwsLuaError( "length", somefalse ); - throwsLuaError( "length", zero ); - throwsLuaError( "length", intint ); - throwsLuaError( "length", longdouble ); - throwsLuaError( "length", doubledouble ); - assertEquals( samplestringstring.length(), stringstring.length() ); - assertEquals( samplestringint.length(), stringint.length() ); - assertEquals( samplestringlong.length(), stringlong.length() ); - assertEquals( samplestringdouble.length(), stringdouble.length() ); - assertEquals( 2, table.length() ); - throwsLuaError( "length", somefunc ); - throwsLuaError( "length", thread ); - throwsLuaError( "length", someclosure ); - throwsLuaError( "length", userdataobj ); - throwsLuaError( "length", userdatacls ); - } - public Prototype createPrototype( String script, String name ) { + private void throwsLuaError(String methodName, Object obj, Object arg) { + try { + LuaValue.class.getMethod(methodName, LuaValue.class).invoke(obj, arg); + fail("failed to throw LuaError as required"); + } catch (InvocationTargetException e) { + if (!(e.getTargetException() instanceof LuaError)) + fail("not a LuaError: " + e.getTargetException()); + return; // pass + } catch (Exception e) { + fail("bad exception: " + e); + } + } + + public void testLen() { + throwsLuaError("len", somenil); + throwsLuaError("len", sometrue); + throwsLuaError("len", somefalse); + throwsLuaError("len", zero); + throwsLuaError("len", intint); + throwsLuaError("len", longdouble); + throwsLuaError("len", doubledouble); + assertEquals(LuaInteger.valueOf(samplestringstring.length()), stringstring.len()); + assertEquals(LuaInteger.valueOf(samplestringint.length()), stringint.len()); + assertEquals(LuaInteger.valueOf(samplestringlong.length()), stringlong.len()); + assertEquals(LuaInteger.valueOf(samplestringdouble.length()), stringdouble.len()); + assertEquals(LuaInteger.valueOf(2), table.len()); + throwsLuaError("len", somefunc); + throwsLuaError("len", thread); + throwsLuaError("len", someclosure); + throwsLuaError("len", userdataobj); + throwsLuaError("len", userdatacls); + } + + public void testLength() { + throwsLuaError("length", somenil); + throwsLuaError("length", sometrue); + throwsLuaError("length", somefalse); + throwsLuaError("length", zero); + throwsLuaError("length", intint); + throwsLuaError("length", longdouble); + throwsLuaError("length", doubledouble); + assertEquals(samplestringstring.length(), stringstring.length()); + assertEquals(samplestringint.length(), stringint.length()); + assertEquals(samplestringlong.length(), stringlong.length()); + assertEquals(samplestringdouble.length(), stringdouble.length()); + assertEquals(2, table.length()); + throwsLuaError("length", somefunc); + throwsLuaError("length", thread); + throwsLuaError("length", someclosure); + throwsLuaError("length", userdataobj); + throwsLuaError("length", userdatacls); + } + + public Prototype createPrototype(String script, String name) { try { Globals globals = org.luaj.vm2.lib.jse.JsePlatform.standardGlobals(); Reader reader = new StringReader(script); @@ -138,7 +141,7 @@ public class LuaOperationsTest extends TestCase { e.printStackTrace(); fail(e.toString()); return null; - } + } } public void testFunctionClosureThreadEnv() { @@ -147,30 +150,31 @@ public class LuaOperationsTest extends TestCase { LuaValue aaa = LuaValue.valueOf("aaa"); LuaValue eee = LuaValue.valueOf("eee"); final Globals globals = org.luaj.vm2.lib.jse.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 } ); + 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() { public LuaValue call() { return globals.get("a");}}; - assertEquals( aaa, f.call() ); + LuaFunction f = new ZeroArgFunction() { + public LuaValue call() { return globals.get("a"); } + }; + assertEquals(aaa, f.call()); } - + // closure tests { - Prototype p = createPrototype( "return a\n", "closuretester" ); + 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() ); + assertEquals(aaa, c.call()); c = new LuaClosure(p, newenv); - assertEquals( newenv, c.upValues[0].getValue() ); - assertEquals( eee, c.call() ); + assertEquals(newenv, c.upValues[0].getValue()); + assertEquals(eee, c.call()); } } } diff --git a/luaj-test/src/test/java/org/luaj/vm2/MathLibTest.java b/luaj-test/src/test/java/org/luaj/vm2/MathLibTest.java index ba3b290b..c19daaad 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/MathLibTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/MathLibTest.java @@ -9,224 +9,224 @@ public class MathLibTest extends TestCase { private LuaValue j2se; private LuaValue j2me; - private boolean supportedOnJ2me; + private boolean supportedOnJ2me; public MathLibTest() { j2se = JsePlatform.standardGlobals().get("math"); j2me = JmePlatform.standardGlobals().get("math"); } - + protected void setUp() throws Exception { supportedOnJ2me = true; } public 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 ); + 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(); + return j2me.get("pow").call(LuaValue.valueOf(x), LuaValue.valueOf(y)).todouble(); } public void testAbs() { - tryMathOp( "abs", 23.45 ); - tryMathOp( "abs", -23.45 ); + tryMathOp("abs", 23.45); + tryMathOp("abs", -23.45); } public void testCos() { - tryTrigOps( "cos" ); + tryTrigOps("cos"); } - + public void testCosh() { supportedOnJ2me = false; - tryTrigOps( "cosh" ); + tryTrigOps("cosh"); } - + public void testDeg() { - tryTrigOps( "deg" ); + tryTrigOps("deg"); } - + public void testExp() { //supportedOnJ2me = false; - 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 ); + 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); } - + public 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 ); + 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); } - + public 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 ); + 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); } - + public void testSin() { - tryTrigOps( "sin" ); + tryTrigOps("sin"); } - + public void testSinh() { supportedOnJ2me = false; - tryTrigOps( "sinh" ); + tryTrigOps("sinh"); } - + public void testSqrt() { - tryMathOp( "sqrt", 0 ); - tryMathOp( "sqrt", 0.1 ); - tryMathOp( "sqrt", .9 ); - tryMathOp( "sqrt", 1. ); - tryMathOp( "sqrt", 9 ); - tryMathOp( "sqrt", 10 ); - tryMathOp( "sqrt", 100 ); + tryMathOp("sqrt", 0); + tryMathOp("sqrt", 0.1); + tryMathOp("sqrt", .9); + tryMathOp("sqrt", 1.); + tryMathOp("sqrt", 9); + tryMathOp("sqrt", 10); + tryMathOp("sqrt", 100); } + public void testTan() { - tryTrigOps( "tan" ); + tryTrigOps("tan"); } - + public void testTanh() { supportedOnJ2me = false; - tryTrigOps( "tanh" ); + tryTrigOps("tanh"); } - + public void testAtan2() { supportedOnJ2me = false; - tryDoubleOps( "atan2", false ); + tryDoubleOps("atan2", false); } - + public void testFmod() { - tryDoubleOps( "fmod", false ); + tryDoubleOps("fmod", false); } - + public void testPow() { - tryDoubleOps( "pow", true ); + tryDoubleOps("pow", true); } - - private void tryDoubleOps( String op, boolean positiveOnly ) { + + 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 ); - + 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 ) { + 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 ); - + 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 ); + 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 ); + 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 ); + 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) { + + 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 ); + 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 ) + 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 ); + 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 ) + 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/java/org/luaj/vm2/MetatableTest.java b/luaj-test/src/test/java/org/luaj/vm2/MetatableTest.java index 1dffff45..4187ad1d 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/MetatableTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/MetatableTest.java @@ -33,16 +33,18 @@ public class MetatableTest extends TestCase { private final String samplestring = "abcdef"; private final Object sampleobject = new Object(); - private final MyData sampledata = new MyData(); - - private final LuaValue string = LuaValue.valueOf(samplestring); - private final LuaTable table = LuaValue.tableOf(); - private final LuaFunction function = new ZeroArgFunction() { public LuaValue call() { return NONE;}}; - private final LuaThread thread = new LuaThread(new Globals(), function); - private final LuaClosure closure = new LuaClosure(new Prototype(), new LuaTable()); - private final LuaUserdata userdata = LuaValue.userdataOf(sampleobject); - private final LuaUserdata userdatamt = LuaValue.userdataOf(sampledata,table); - + private final MyData sampledata = new MyData(); + + private final LuaValue string = LuaValue.valueOf(samplestring); + private final LuaTable table = LuaValue.tableOf(); + private final LuaFunction function = new ZeroArgFunction() { + public LuaValue call() { return NONE; } + }; + private final LuaThread thread = new LuaThread(new Globals(), function); + private final LuaClosure closure = new LuaClosure(new Prototype(), new LuaTable()); + private final LuaUserdata userdata = LuaValue.userdataOf(sampleobject); + private final LuaUserdata userdatamt = LuaValue.userdataOf(sampledata, table); + protected void setUp() throws Exception { // needed for metatable ops to work on strings new StringLib(); @@ -59,223 +61,218 @@ public class MetatableTest extends TestCase { } public void testGetMetatable() { - assertEquals( null, LuaValue.NIL.getmetatable() ); - assertEquals( null, LuaValue.TRUE.getmetatable() ); - assertEquals( null, LuaValue.ONE.getmetatable() ); + assertEquals(null, LuaValue.NIL.getmetatable()); + assertEquals(null, LuaValue.TRUE.getmetatable()); + assertEquals(null, LuaValue.ONE.getmetatable()); // assertEquals( null, string.getmetatable() ); - assertEquals( null, table.getmetatable() ); - assertEquals( null, function.getmetatable() ); - assertEquals( null, thread.getmetatable() ); - assertEquals( null, closure.getmetatable() ); - assertEquals( null, userdata.getmetatable() ); - assertEquals( table, userdatamt.getmetatable() ); + assertEquals(null, table.getmetatable()); + assertEquals(null, function.getmetatable()); + assertEquals(null, thread.getmetatable()); + assertEquals(null, closure.getmetatable()); + assertEquals(null, userdata.getmetatable()); + assertEquals(table, userdatamt.getmetatable()); } public void testSetMetatable() { LuaValue mt = LuaValue.tableOf(); - assertEquals( null, table.getmetatable() ); - assertEquals( null, userdata.getmetatable() ); - assertEquals( table, userdatamt.getmetatable() ); - assertEquals( table, table.setmetatable(mt) ); - assertEquals( userdata, userdata.setmetatable(mt) ); - assertEquals( userdatamt, userdatamt.setmetatable(mt) ); - assertEquals( mt, table.getmetatable() ); - assertEquals( mt, userdata.getmetatable() ); - assertEquals( mt, userdatamt.getmetatable() ); - + assertEquals(null, table.getmetatable()); + assertEquals(null, userdata.getmetatable()); + assertEquals(table, userdatamt.getmetatable()); + assertEquals(table, table.setmetatable(mt)); + assertEquals(userdata, userdata.setmetatable(mt)); + assertEquals(userdatamt, userdatamt.setmetatable(mt)); + assertEquals(mt, table.getmetatable()); + assertEquals(mt, userdata.getmetatable()); + assertEquals(mt, userdatamt.getmetatable()); + // these all get metatable behind-the-scenes - assertEquals( null, LuaValue.NIL.getmetatable() ); - assertEquals( null, LuaValue.TRUE.getmetatable() ); - assertEquals( null, LuaValue.ONE.getmetatable() ); + assertEquals(null, LuaValue.NIL.getmetatable()); + assertEquals(null, LuaValue.TRUE.getmetatable()); + assertEquals(null, LuaValue.ONE.getmetatable()); // assertEquals( null, string.getmetatable() ); - assertEquals( null, function.getmetatable() ); - assertEquals( null, thread.getmetatable() ); - assertEquals( null, closure.getmetatable() ); + assertEquals(null, function.getmetatable()); + assertEquals(null, thread.getmetatable()); + assertEquals(null, closure.getmetatable()); LuaNil.s_metatable = mt; - assertEquals( mt, LuaValue.NIL.getmetatable() ); - assertEquals( null, LuaValue.TRUE.getmetatable() ); - assertEquals( null, LuaValue.ONE.getmetatable() ); + assertEquals(mt, LuaValue.NIL.getmetatable()); + assertEquals(null, LuaValue.TRUE.getmetatable()); + assertEquals(null, LuaValue.ONE.getmetatable()); // assertEquals( null, string.getmetatable() ); - assertEquals( null, function.getmetatable() ); - assertEquals( null, thread.getmetatable() ); - assertEquals( null, closure.getmetatable() ); + assertEquals(null, function.getmetatable()); + assertEquals(null, thread.getmetatable()); + assertEquals(null, closure.getmetatable()); LuaBoolean.s_metatable = mt; - assertEquals( mt, LuaValue.TRUE.getmetatable() ); - assertEquals( null, LuaValue.ONE.getmetatable() ); + assertEquals(mt, LuaValue.TRUE.getmetatable()); + assertEquals(null, LuaValue.ONE.getmetatable()); // assertEquals( null, string.getmetatable() ); - assertEquals( null, function.getmetatable() ); - assertEquals( null, thread.getmetatable() ); - assertEquals( null, closure.getmetatable() ); + assertEquals(null, function.getmetatable()); + assertEquals(null, thread.getmetatable()); + assertEquals(null, closure.getmetatable()); LuaNumber.s_metatable = mt; - assertEquals( mt, LuaValue.ONE.getmetatable() ); - assertEquals( mt, LuaValue.valueOf(1.25).getmetatable() ); + assertEquals(mt, LuaValue.ONE.getmetatable()); + assertEquals(mt, LuaValue.valueOf(1.25).getmetatable()); // assertEquals( null, string.getmetatable() ); - assertEquals( null, function.getmetatable() ); - assertEquals( null, thread.getmetatable() ); - assertEquals( null, closure.getmetatable() ); + assertEquals(null, function.getmetatable()); + assertEquals(null, thread.getmetatable()); + assertEquals(null, closure.getmetatable()); // LuaString.s_metatable = mt; // assertEquals( mt, string.getmetatable() ); - assertEquals( null, function.getmetatable() ); - assertEquals( null, thread.getmetatable() ); - assertEquals( null, closure.getmetatable() ); + assertEquals(null, function.getmetatable()); + assertEquals(null, thread.getmetatable()); + assertEquals(null, closure.getmetatable()); LuaFunction.s_metatable = mt; - assertEquals( mt, function.getmetatable() ); - assertEquals( null, thread.getmetatable() ); + assertEquals(mt, function.getmetatable()); + assertEquals(null, thread.getmetatable()); LuaThread.s_metatable = mt; - assertEquals( mt, thread.getmetatable() ); + assertEquals(mt, thread.getmetatable()); } - + public void testMetatableIndex() { - assertEquals( table, table.setmetatable(null) ); - assertEquals( userdata, userdata.setmetatable(null) ); - assertEquals( userdatamt, userdatamt.setmetatable(null) ); - assertEquals( LuaValue.NIL, table.get(1) ); - assertEquals( LuaValue.NIL, userdata.get(1) ); - assertEquals( LuaValue.NIL, userdatamt.get(1) ); - + assertEquals(table, table.setmetatable(null)); + assertEquals(userdata, userdata.setmetatable(null)); + assertEquals(userdatamt, userdatamt.setmetatable(null)); + assertEquals(LuaValue.NIL, table.get(1)); + assertEquals(LuaValue.NIL, userdata.get(1)); + assertEquals(LuaValue.NIL, userdatamt.get(1)); + // empty metatable LuaValue mt = LuaValue.tableOf(); - assertEquals( table, table.setmetatable(mt) ); - assertEquals( userdata, userdata.setmetatable(mt) ); + assertEquals(table, table.setmetatable(mt)); + assertEquals(userdata, userdata.setmetatable(mt)); LuaBoolean.s_metatable = mt; LuaFunction.s_metatable = mt; LuaNil.s_metatable = mt; LuaNumber.s_metatable = mt; // LuaString.s_metatable = mt; LuaThread.s_metatable = mt; - assertEquals( mt, table.getmetatable() ); - assertEquals( mt, userdata.getmetatable() ); - assertEquals( mt, LuaValue.NIL.getmetatable() ); - assertEquals( mt, LuaValue.TRUE.getmetatable() ); - assertEquals( mt, LuaValue.ONE.getmetatable() ); + assertEquals(mt, table.getmetatable()); + assertEquals(mt, userdata.getmetatable()); + assertEquals(mt, LuaValue.NIL.getmetatable()); + assertEquals(mt, LuaValue.TRUE.getmetatable()); + assertEquals(mt, LuaValue.ONE.getmetatable()); // assertEquals( StringLib.instance, string.getmetatable() ); - assertEquals( mt, function.getmetatable() ); - assertEquals( mt, thread.getmetatable() ); - + assertEquals(mt, function.getmetatable()); + assertEquals(mt, thread.getmetatable()); + // plain metatable LuaValue abc = LuaValue.valueOf("abc"); - mt.set( LuaValue.INDEX, LuaValue.listOf(new LuaValue[] { abc } ) ); - assertEquals( abc, table.get(1) ); - assertEquals( abc, userdata.get(1) ); - assertEquals( abc, LuaValue.NIL.get(1) ); - assertEquals( abc, LuaValue.TRUE.get(1) ); - assertEquals( abc, LuaValue.ONE.get(1) ); + mt.set(LuaValue.INDEX, LuaValue.listOf(new LuaValue[] { abc })); + assertEquals(abc, table.get(1)); + assertEquals(abc, userdata.get(1)); + assertEquals(abc, LuaValue.NIL.get(1)); + assertEquals(abc, LuaValue.TRUE.get(1)); + assertEquals(abc, LuaValue.ONE.get(1)); // assertEquals( abc, string.get(1) ); - assertEquals( abc, function.get(1) ); - assertEquals( abc, thread.get(1) ); - + assertEquals(abc, function.get(1)); + assertEquals(abc, thread.get(1)); + // plain metatable - mt.set( LuaValue.INDEX, new TwoArgFunction() { + mt.set(LuaValue.INDEX, new TwoArgFunction() { public LuaValue call(LuaValue arg1, LuaValue arg2) { - return LuaValue.valueOf( arg1.typename()+"["+arg2.tojstring()+"]=xyz" ); + return LuaValue.valueOf(arg1.typename() + "[" + arg2.tojstring() + "]=xyz"); } - + }); - assertEquals( "table[1]=xyz", table.get(1).tojstring() ); - assertEquals( "userdata[1]=xyz", userdata.get(1).tojstring() ); - assertEquals( "nil[1]=xyz", LuaValue.NIL.get(1).tojstring() ); - assertEquals( "boolean[1]=xyz", LuaValue.TRUE.get(1).tojstring() ); - assertEquals( "number[1]=xyz", LuaValue.ONE.get(1).tojstring() ); - // assertEquals( "string[1]=xyz", string.get(1).tojstring() ); - assertEquals( "function[1]=xyz", function.get(1).tojstring() ); - assertEquals( "thread[1]=xyz", thread.get(1).tojstring() ); + assertEquals("table[1]=xyz", table.get(1).tojstring()); + assertEquals("userdata[1]=xyz", userdata.get(1).tojstring()); + assertEquals("nil[1]=xyz", LuaValue.NIL.get(1).tojstring()); + assertEquals("boolean[1]=xyz", LuaValue.TRUE.get(1).tojstring()); + assertEquals("number[1]=xyz", LuaValue.ONE.get(1).tojstring()); + // assertEquals( "string[1]=xyz", string.get(1).tojstring() ); + assertEquals("function[1]=xyz", function.get(1).tojstring()); + assertEquals("thread[1]=xyz", thread.get(1).tojstring()); } - public void testMetatableNewIndex() { // empty metatable LuaValue mt = LuaValue.tableOf(); - assertEquals( table, table.setmetatable(mt) ); - assertEquals( userdata, userdata.setmetatable(mt) ); + assertEquals(table, table.setmetatable(mt)); + assertEquals(userdata, userdata.setmetatable(mt)); LuaBoolean.s_metatable = mt; LuaFunction.s_metatable = mt; LuaNil.s_metatable = mt; LuaNumber.s_metatable = mt; // LuaString.s_metatable = mt; LuaThread.s_metatable = mt; - + // plain metatable final LuaValue fallback = LuaValue.tableOf(); LuaValue abc = LuaValue.valueOf("abc"); - mt.set( LuaValue.NEWINDEX, fallback ); - table.set(2,abc); - userdata.set(3,abc); - LuaValue.NIL.set(4,abc); - LuaValue.TRUE.set(5,abc); - LuaValue.ONE.set(6,abc); + mt.set(LuaValue.NEWINDEX, fallback); + table.set(2, abc); + userdata.set(3, abc); + LuaValue.NIL.set(4, abc); + LuaValue.TRUE.set(5, abc); + LuaValue.ONE.set(6, abc); // string.set(7,abc); - function.set(8,abc); - thread.set(9,abc); - assertEquals( abc, fallback.get(2) ); - assertEquals( abc, fallback.get(3) ); - assertEquals( abc, fallback.get(4) ); - assertEquals( abc, fallback.get(5) ); - assertEquals( abc, fallback.get(6) ); + function.set(8, abc); + thread.set(9, abc); + assertEquals(abc, fallback.get(2)); + assertEquals(abc, fallback.get(3)); + assertEquals(abc, fallback.get(4)); + assertEquals(abc, fallback.get(5)); + assertEquals(abc, fallback.get(6)); // assertEquals( abc, StringLib.instance.get(7) ); - assertEquals( abc, fallback.get(8) ); - assertEquals( abc, fallback.get(9) ); - + assertEquals(abc, fallback.get(8)); + assertEquals(abc, fallback.get(9)); + // metatable with function call - mt.set( LuaValue.NEWINDEX, new ThreeArgFunction() { + mt.set(LuaValue.NEWINDEX, new ThreeArgFunction() { public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { - fallback.rawset(arg2, LuaValue.valueOf( "via-func-"+arg3 )); + fallback.rawset(arg2, LuaValue.valueOf("via-func-" + arg3)); return NONE; } - + }); - table.set(12,abc); - userdata.set(13,abc); - LuaValue.NIL.set(14,abc); - LuaValue.TRUE.set(15,abc); - LuaValue.ONE.set(16,abc); + table.set(12, abc); + userdata.set(13, abc); + LuaValue.NIL.set(14, abc); + LuaValue.TRUE.set(15, abc); + LuaValue.ONE.set(16, abc); // string.set(17,abc); - function.set(18,abc); - thread.set(19,abc); - LuaValue via = LuaValue.valueOf( "via-func-abc" ); - assertEquals( via, fallback.get(12) ); - assertEquals( via, fallback.get(13) ); - assertEquals( via, fallback.get(14) ); - assertEquals( via, fallback.get(15) ); - assertEquals( via, fallback.get(16) ); + function.set(18, abc); + thread.set(19, abc); + LuaValue via = LuaValue.valueOf("via-func-abc"); + assertEquals(via, fallback.get(12)); + assertEquals(via, fallback.get(13)); + assertEquals(via, fallback.get(14)); + assertEquals(via, fallback.get(15)); + assertEquals(via, fallback.get(16)); // assertEquals( via, StringLib.instance.get(17) ); - assertEquals( via, fallback.get(18) ); - assertEquals( via, fallback.get(19) ); + assertEquals(via, fallback.get(18)); + assertEquals(via, fallback.get(19)); } - - private void checkTable( LuaValue t, - LuaValue aa, LuaValue bb, LuaValue cc, LuaValue dd, LuaValue ee, LuaValue ff, LuaValue gg, - LuaValue ra, LuaValue rb, LuaValue rc, LuaValue rd, LuaValue re, LuaValue rf, LuaValue rg ) { - assertEquals( aa, t.get("aa") ); - assertEquals( bb, t.get("bb") ); - assertEquals( cc, t.get("cc") ); - assertEquals( dd, t.get("dd") ); - assertEquals( ee, t.get("ee") ); - assertEquals( ff, t.get("ff") ); - assertEquals( gg, t.get("gg") ); - assertEquals( ra, t.rawget("aa") ); - assertEquals( rb, t.rawget("bb") ); - assertEquals( rc, t.rawget("cc") ); - assertEquals( rd, t.rawget("dd") ); - assertEquals( re, t.rawget("ee") ); - assertEquals( rf, t.rawget("ff") ); - assertEquals( rg, t.rawget("gg") ); + private void checkTable(LuaValue t, LuaValue aa, LuaValue bb, LuaValue cc, LuaValue dd, LuaValue ee, LuaValue ff, + LuaValue gg, LuaValue ra, LuaValue rb, LuaValue rc, LuaValue rd, LuaValue re, LuaValue rf, LuaValue rg) { + assertEquals(aa, t.get("aa")); + assertEquals(bb, t.get("bb")); + assertEquals(cc, t.get("cc")); + assertEquals(dd, t.get("dd")); + assertEquals(ee, t.get("ee")); + assertEquals(ff, t.get("ff")); + assertEquals(gg, t.get("gg")); + assertEquals(ra, t.rawget("aa")); + assertEquals(rb, t.rawget("bb")); + assertEquals(rc, t.rawget("cc")); + assertEquals(rd, t.rawget("dd")); + assertEquals(re, t.rawget("ee")); + assertEquals(rf, t.rawget("ff")); + assertEquals(rg, t.rawget("gg")); } - private LuaValue makeTable( String key1, String val1, String key2, String val2 ) { - return LuaValue.tableOf( new LuaValue[] { - LuaValue.valueOf(key1), LuaValue.valueOf(val1), - LuaValue.valueOf(key2), LuaValue.valueOf(val2), - } ); + private LuaValue makeTable(String key1, String val1, String key2, String val2) { + return LuaValue.tableOf(new LuaValue[] { LuaValue.valueOf(key1), LuaValue.valueOf(val1), LuaValue.valueOf(key2), + LuaValue.valueOf(val2), }); } - + public void testRawsetMetatableSet() { // set up tables - LuaValue m = makeTable( "aa", "aaa", "bb", "bbb" ); + LuaValue m = makeTable("aa", "aaa", "bb", "bbb"); m.set(LuaValue.INDEX, m); m.set(LuaValue.NEWINDEX, m); - LuaValue s = makeTable( "cc", "ccc", "dd", "ddd" ); - LuaValue t = makeTable( "cc", "ccc", "dd", "ddd" ); + LuaValue s = makeTable("cc", "ccc", "dd", "ddd"); + LuaValue t = makeTable("cc", "ccc", "dd", "ddd"); t.setmetatable(m); LuaValue aaa = LuaValue.valueOf("aaa"); LuaValue bbb = LuaValue.valueOf("bbb"); @@ -291,76 +288,75 @@ public class MetatableTest extends TestCase { LuaValue yyy = LuaValue.valueOf("yyy"); LuaValue zzz = LuaValue.valueOf("zzz"); LuaValue nil = LuaValue.NIL; - + // check initial values // values via "bet()" values via "rawget()" - checkTable( s, nil,nil,ccc,ddd,nil,nil,nil, nil,nil,ccc,ddd,nil,nil,nil ); - checkTable( t, aaa,bbb,ccc,ddd,nil,nil,nil, nil,nil,ccc,ddd,nil,nil,nil ); - checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil ); + checkTable(s, nil, nil, ccc, ddd, nil, nil, nil, nil, nil, ccc, ddd, nil, nil, nil); + checkTable(t, aaa, bbb, ccc, ddd, nil, nil, nil, nil, nil, ccc, ddd, nil, nil, nil); + checkTable(m, aaa, bbb, nil, nil, nil, nil, nil, aaa, bbb, nil, nil, nil, nil, nil); // rawset() s.rawset("aa", www); - checkTable( s, www,nil,ccc,ddd,nil,nil,nil, www,nil,ccc,ddd,nil,nil,nil ); - checkTable( t, aaa,bbb,ccc,ddd,nil,nil,nil, nil,nil,ccc,ddd,nil,nil,nil ); - checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil ); + checkTable(s, www, nil, ccc, ddd, nil, nil, nil, www, nil, ccc, ddd, nil, nil, nil); + checkTable(t, aaa, bbb, ccc, ddd, nil, nil, nil, nil, nil, ccc, ddd, nil, nil, nil); + checkTable(m, aaa, bbb, nil, nil, nil, nil, nil, aaa, bbb, nil, nil, nil, nil, nil); s.rawset("cc", xxx); - checkTable( s, www,nil,xxx,ddd,nil,nil,nil, www,nil,xxx,ddd,nil,nil,nil ); - checkTable( t, aaa,bbb,ccc,ddd,nil,nil,nil, nil,nil,ccc,ddd,nil,nil,nil ); - checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil ); + checkTable(s, www, nil, xxx, ddd, nil, nil, nil, www, nil, xxx, ddd, nil, nil, nil); + checkTable(t, aaa, bbb, ccc, ddd, nil, nil, nil, nil, nil, ccc, ddd, nil, nil, nil); + checkTable(m, aaa, bbb, nil, nil, nil, nil, nil, aaa, bbb, nil, nil, nil, nil, nil); t.rawset("bb", yyy); - checkTable( s, www,nil,xxx,ddd,nil,nil,nil, www,nil,xxx,ddd,nil,nil,nil ); - checkTable( t, aaa,yyy,ccc,ddd,nil,nil,nil, nil,yyy,ccc,ddd,nil,nil,nil ); - checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil ); + checkTable(s, www, nil, xxx, ddd, nil, nil, nil, www, nil, xxx, ddd, nil, nil, nil); + checkTable(t, aaa, yyy, ccc, ddd, nil, nil, nil, nil, yyy, ccc, ddd, nil, nil, nil); + checkTable(m, aaa, bbb, nil, nil, nil, nil, nil, aaa, bbb, nil, nil, nil, nil, nil); t.rawset("dd", zzz); - checkTable( s, www,nil,xxx,ddd,nil,nil,nil, www,nil,xxx,ddd,nil,nil,nil ); - checkTable( t, aaa,yyy,ccc,zzz,nil,nil,nil, nil,yyy,ccc,zzz,nil,nil,nil ); - checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil ); + checkTable(s, www, nil, xxx, ddd, nil, nil, nil, www, nil, xxx, ddd, nil, nil, nil); + checkTable(t, aaa, yyy, ccc, zzz, nil, nil, nil, nil, yyy, ccc, zzz, nil, nil, nil); + checkTable(m, aaa, bbb, nil, nil, nil, nil, nil, aaa, bbb, nil, nil, nil, nil, nil); // set() invoking metatables s.set("ee", ppp); - checkTable( s, www,nil,xxx,ddd,ppp,nil,nil, www,nil,xxx,ddd,ppp,nil,nil ); - checkTable( t, aaa,yyy,ccc,zzz,nil,nil,nil, nil,yyy,ccc,zzz,nil,nil,nil ); - checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil ); + checkTable(s, www, nil, xxx, ddd, ppp, nil, nil, www, nil, xxx, ddd, ppp, nil, nil); + checkTable(t, aaa, yyy, ccc, zzz, nil, nil, nil, nil, yyy, ccc, zzz, nil, nil, nil); + checkTable(m, aaa, bbb, nil, nil, nil, nil, nil, aaa, bbb, nil, nil, nil, nil, nil); s.set("cc", qqq); - checkTable( s, www,nil,qqq,ddd,ppp,nil,nil, www,nil,qqq,ddd,ppp,nil,nil ); - checkTable( t, aaa,yyy,ccc,zzz,nil,nil,nil, nil,yyy,ccc,zzz,nil,nil,nil ); - checkTable( m, aaa,bbb,nil,nil,nil,nil,nil, aaa,bbb,nil,nil,nil,nil,nil ); + checkTable(s, www, nil, qqq, ddd, ppp, nil, nil, www, nil, qqq, ddd, ppp, nil, nil); + checkTable(t, aaa, yyy, ccc, zzz, nil, nil, nil, nil, yyy, ccc, zzz, nil, nil, nil); + checkTable(m, aaa, bbb, nil, nil, nil, nil, nil, aaa, bbb, nil, nil, nil, nil, nil); t.set("ff", rrr); - checkTable( s, www,nil,qqq,ddd,ppp,nil,nil, www,nil,qqq,ddd,ppp,nil,nil ); - checkTable( t, aaa,yyy,ccc,zzz,nil,rrr,nil, nil,yyy,ccc,zzz,nil,nil,nil ); - checkTable( m, aaa,bbb,nil,nil,nil,rrr,nil, aaa,bbb,nil,nil,nil,rrr,nil ); + checkTable(s, www, nil, qqq, ddd, ppp, nil, nil, www, nil, qqq, ddd, ppp, nil, nil); + checkTable(t, aaa, yyy, ccc, zzz, nil, rrr, nil, nil, yyy, ccc, zzz, nil, nil, nil); + checkTable(m, aaa, bbb, nil, nil, nil, rrr, nil, aaa, bbb, nil, nil, nil, rrr, nil); t.set("dd", sss); - checkTable( s, www,nil,qqq,ddd,ppp,nil,nil, www,nil,qqq,ddd,ppp,nil,nil ); - checkTable( t, aaa,yyy,ccc,sss,nil,rrr,nil, nil,yyy,ccc,sss,nil,nil,nil ); - checkTable( m, aaa,bbb,nil,nil,nil,rrr,nil, aaa,bbb,nil,nil,nil,rrr,nil ); + checkTable(s, www, nil, qqq, ddd, ppp, nil, nil, www, nil, qqq, ddd, ppp, nil, nil); + checkTable(t, aaa, yyy, ccc, sss, nil, rrr, nil, nil, yyy, ccc, sss, nil, nil, nil); + checkTable(m, aaa, bbb, nil, nil, nil, rrr, nil, aaa, bbb, nil, nil, nil, rrr, nil); m.set("gg", ttt); - checkTable( s, www,nil,qqq,ddd,ppp,nil,nil, www,nil,qqq,ddd,ppp,nil,nil ); - checkTable( t, aaa,yyy,ccc,sss,nil,rrr,ttt, nil,yyy,ccc,sss,nil,nil,nil ); - checkTable( m, aaa,bbb,nil,nil,nil,rrr,ttt, aaa,bbb,nil,nil,nil,rrr,ttt ); - - // make s fall back to t - s.setmetatable(LuaValue.tableOf(new LuaValue[] {LuaValue.INDEX,t,LuaValue.NEWINDEX,t})); - checkTable( s, www,yyy,qqq,ddd,ppp,rrr,ttt, www,nil,qqq,ddd,ppp,nil,nil ); - checkTable( t, aaa,yyy,ccc,sss,nil,rrr,ttt, nil,yyy,ccc,sss,nil,nil,nil ); - checkTable( m, aaa,bbb,nil,nil,nil,rrr,ttt, aaa,bbb,nil,nil,nil,rrr,ttt ); - s.set("aa", www); - checkTable( s, www,yyy,qqq,ddd,ppp,rrr,ttt, www,nil,qqq,ddd,ppp,nil,nil ); - checkTable( t, aaa,yyy,ccc,sss,nil,rrr,ttt, nil,yyy,ccc,sss,nil,nil,nil ); - checkTable( m, aaa,bbb,nil,nil,nil,rrr,ttt, aaa,bbb,nil,nil,nil,rrr,ttt ); - s.set("bb", zzz); - checkTable( s, www,zzz,qqq,ddd,ppp,rrr,ttt, www,nil,qqq,ddd,ppp,nil,nil ); - checkTable( t, aaa,zzz,ccc,sss,nil,rrr,ttt, nil,zzz,ccc,sss,nil,nil,nil ); - checkTable( m, aaa,bbb,nil,nil,nil,rrr,ttt, aaa,bbb,nil,nil,nil,rrr,ttt ); - s.set("ee", xxx); - checkTable( s, www,zzz,qqq,ddd,xxx,rrr,ttt, www,nil,qqq,ddd,xxx,nil,nil ); - checkTable( t, aaa,zzz,ccc,sss,nil,rrr,ttt, nil,zzz,ccc,sss,nil,nil,nil ); - checkTable( m, aaa,bbb,nil,nil,nil,rrr,ttt, aaa,bbb,nil,nil,nil,rrr,ttt ); - s.set("ff", yyy); - checkTable( s, www,zzz,qqq,ddd,xxx,yyy,ttt, www,nil,qqq,ddd,xxx,nil,nil ); - checkTable( t, aaa,zzz,ccc,sss,nil,yyy,ttt, nil,zzz,ccc,sss,nil,nil,nil ); - checkTable( m, aaa,bbb,nil,nil,nil,yyy,ttt, aaa,bbb,nil,nil,nil,yyy,ttt ); + checkTable(s, www, nil, qqq, ddd, ppp, nil, nil, www, nil, qqq, ddd, ppp, nil, nil); + checkTable(t, aaa, yyy, ccc, sss, nil, rrr, ttt, nil, yyy, ccc, sss, nil, nil, nil); + checkTable(m, aaa, bbb, nil, nil, nil, rrr, ttt, aaa, bbb, nil, nil, nil, rrr, ttt); + // make s fall back to t + s.setmetatable(LuaValue.tableOf(new LuaValue[] { LuaValue.INDEX, t, LuaValue.NEWINDEX, t })); + checkTable(s, www, yyy, qqq, ddd, ppp, rrr, ttt, www, nil, qqq, ddd, ppp, nil, nil); + checkTable(t, aaa, yyy, ccc, sss, nil, rrr, ttt, nil, yyy, ccc, sss, nil, nil, nil); + checkTable(m, aaa, bbb, nil, nil, nil, rrr, ttt, aaa, bbb, nil, nil, nil, rrr, ttt); + s.set("aa", www); + checkTable(s, www, yyy, qqq, ddd, ppp, rrr, ttt, www, nil, qqq, ddd, ppp, nil, nil); + checkTable(t, aaa, yyy, ccc, sss, nil, rrr, ttt, nil, yyy, ccc, sss, nil, nil, nil); + checkTable(m, aaa, bbb, nil, nil, nil, rrr, ttt, aaa, bbb, nil, nil, nil, rrr, ttt); + s.set("bb", zzz); + checkTable(s, www, zzz, qqq, ddd, ppp, rrr, ttt, www, nil, qqq, ddd, ppp, nil, nil); + checkTable(t, aaa, zzz, ccc, sss, nil, rrr, ttt, nil, zzz, ccc, sss, nil, nil, nil); + checkTable(m, aaa, bbb, nil, nil, nil, rrr, ttt, aaa, bbb, nil, nil, nil, rrr, ttt); + s.set("ee", xxx); + checkTable(s, www, zzz, qqq, ddd, xxx, rrr, ttt, www, nil, qqq, ddd, xxx, nil, nil); + checkTable(t, aaa, zzz, ccc, sss, nil, rrr, ttt, nil, zzz, ccc, sss, nil, nil, nil); + checkTable(m, aaa, bbb, nil, nil, nil, rrr, ttt, aaa, bbb, nil, nil, nil, rrr, ttt); + s.set("ff", yyy); + checkTable(s, www, zzz, qqq, ddd, xxx, yyy, ttt, www, nil, qqq, ddd, xxx, nil, nil); + checkTable(t, aaa, zzz, ccc, sss, nil, yyy, ttt, nil, zzz, ccc, sss, nil, nil, nil); + checkTable(m, aaa, bbb, nil, nil, nil, yyy, ttt, aaa, bbb, nil, nil, nil, yyy, ttt); } - + } diff --git a/luaj-test/src/test/java/org/luaj/vm2/OrphanedThreadTest.java b/luaj-test/src/test/java/org/luaj/vm2/OrphanedThreadTest.java index 14cecb4c..4b208f54 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/OrphanedThreadTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/OrphanedThreadTest.java @@ -28,78 +28,59 @@ import junit.framework.TestCase; import org.luaj.vm2.lib.OneArgFunction; import org.luaj.vm2.lib.jse.JsePlatform; - public class OrphanedThreadTest extends TestCase { - Globals globals; - LuaThread luathread; + Globals globals; + LuaThread luathread; WeakReference luathr_ref; - LuaValue function; + LuaValue function; WeakReference func_ref; - + protected void setUp() throws Exception { LuaThread.thread_orphan_check_interval = 5; globals = JsePlatform.standardGlobals(); } - + protected void tearDown() { LuaThread.thread_orphan_check_interval = 30000; } - + public void testCollectOrphanedNormalThread() throws Exception { function = new NormalFunction(globals); doTest(LuaValue.TRUE, LuaValue.ZERO); } - + public void testCollectOrphanedEarlyCompletionThread() throws Exception { function = new EarlyCompletionFunction(globals); doTest(LuaValue.TRUE, LuaValue.ZERO); } - + public 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"; + 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"; + 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"; + 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); } @@ -108,8 +89,8 @@ public class OrphanedThreadTest extends TestCase { luathread = new LuaThread(globals, function); luathr_ref = new WeakReference(luathread); func_ref = new WeakReference(function); - assertNotNull(luathr_ref.get()); - + assertNotNull(luathr_ref.get()); + // resume two times Varargs a = luathread.resume(LuaValue.valueOf("foo")); assertEquals(LuaValue.ONE, a.arg(2)); @@ -117,62 +98,67 @@ 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; } + 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; } + 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; } + 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-test/src/test/java/org/luaj/vm2/RequireClassTest.java b/luaj-test/src/test/java/org/luaj/vm2/RequireClassTest.java index e617a5c4..eff98557 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/RequireClassTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/RequireClassTest.java @@ -11,7 +11,7 @@ public class RequireClassTest extends TestCase { private LuaTable globals; private LuaValue require; - + public void setUp() { globals = JsePlatform.standardGlobals(); require = globals.get("require"); @@ -19,71 +19,65 @@ public class RequireClassTest extends TestCase { public void testLoadClass() { LuaValue result = globals.load(new org.luaj.vm2.require.RequireSampleSuccess()); - assertEquals( "require-sample-success-", result.tojstring() ); + assertEquals("require-sample-success-", result.tojstring()); } - + public void testRequireClassSuccess() { - LuaValue result = require.call( LuaValue.valueOf("org.luaj.vm2.require.RequireSampleSuccess") ); - assertEquals( "require-sample-success-org.luaj.vm2.require.RequireSampleSuccess", result.tojstring() ); - result = require.call( LuaValue.valueOf("org.luaj.vm2.require.RequireSampleSuccess") ); - assertEquals( "require-sample-success-org.luaj.vm2.require.RequireSampleSuccess", result.tojstring() ); + LuaValue result = require.call(LuaValue.valueOf("org.luaj.vm2.require.RequireSampleSuccess")); + assertEquals("require-sample-success-org.luaj.vm2.require.RequireSampleSuccess", result.tojstring()); + result = require.call(LuaValue.valueOf("org.luaj.vm2.require.RequireSampleSuccess")); + assertEquals("require-sample-success-org.luaj.vm2.require.RequireSampleSuccess", result.tojstring()); } - + public 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() ); + 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() ); + 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()); } } - + public 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() ); + 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() ); + 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()); } } - - + public void testRequireClassClassCastException() { try { - LuaValue result = require.call( LuaValue.valueOf(RequireSampleClassCastExcep.class.getName()) ); - fail( "incorrectly loaded class that threw class cast exception"); - } catch ( LuaError le ) { + 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 ); + 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 ) { + 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 ); + if (msg.indexOf("not found") < 0) + fail("expected 'not found' message but got " + msg); } } } diff --git a/luaj-test/src/test/java/org/luaj/vm2/ScriptDrivenTest.java b/luaj-test/src/test/java/org/luaj/vm2/ScriptDrivenTest.java index 98ec7d18..d91bf74b 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/ScriptDrivenTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/ScriptDrivenTest.java @@ -38,29 +38,28 @@ import org.luaj.vm2.lib.ResourceFinder; import org.luaj.vm2.lib.jse.JseProcess; import org.luaj.vm2.luajc.LuaJC; -abstract -public class ScriptDrivenTest extends TestCase implements ResourceFinder { +abstract public class ScriptDrivenTest extends TestCase implements ResourceFinder { public static final boolean nocompile = "true".equals(System.getProperty("nocompile")); public enum PlatformType { JME, JSE, LUAJIT, } - + private final PlatformType platform; - private final String subdir; - protected Globals globals; - - static final String zipdir = "test/lua/"; + private final String subdir; + protected Globals globals; + + static final String zipdir = "test/lua/"; static final String zipfile = "luaj3.0-tests.zip"; - protected ScriptDrivenTest( PlatformType platform, String subdir ) { + protected ScriptDrivenTest(PlatformType platform, String subdir) { this.platform = platform; this.subdir = subdir; initGlobals(); } - + private void initGlobals() { - switch ( platform ) { + switch (platform) { default: case JSE: case LUAJIT: @@ -71,8 +70,7 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder { break; } } - - + protected void setUp() throws Exception { super.setUp(); initGlobals(); @@ -82,21 +80,26 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder { // ResourceFinder implementation. public InputStream findResource(String filename) { InputStream is = findInPlainFile(filename); - if (is != null) return is; - is = findInPlainFileAsResource("",filename); - if (is != null) return is; - is = findInPlainFileAsResource("/",filename); - if (is != null) return is; + if (is != null) + return is; + is = findInPlainFileAsResource("", filename); + if (is != null) + return is; + is = findInPlainFileAsResource("/", filename); + if (is != null) + return is; is = findInZipFileAsPlainFile(filename); - if (is != null) return is; - is = findInZipFileAsResource("",filename); - if (is != null) return is; - is = findInZipFileAsResource("/",filename); + if (is != null) + return is; + is = findInZipFileAsResource("", filename); + if (is != null) + return is; + is = findInZipFileAsResource("/", filename); return is; } private InputStream findInPlainFileAsResource(String prefix, String filename) { - return getClass().getResourceAsStream(prefix + subdir + filename); + return getClass().getResourceAsStream(prefix+subdir+filename); } private InputStream findInPlainFile(String filename) { @@ -104,7 +107,7 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder { File f = new File(zipdir+subdir+filename); if (f.exists()) return new FileInputStream(f); - } catch ( IOException ioe ) { + } catch (IOException ioe) { ioe.printStackTrace(); } return null; @@ -112,14 +115,14 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder { private InputStream findInZipFileAsPlainFile(String filename) { URL zip; - File file = new File(zipdir+zipfile); + File file = new File(zipdir+zipfile); try { - if ( file.exists() ) { + if (file.exists()) { zip = file.toURI().toURL(); - String path = "jar:"+zip.toExternalForm()+ "!/"+subdir+filename; + String path = "jar:" + zip.toExternalForm() + "!/" + subdir + filename; URL url = new URL(path); return url.openStream(); - } + } } catch (MalformedURLException e) { e.printStackTrace(); } catch (FileNotFoundException e) { @@ -130,13 +133,12 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder { return null; } - private InputStream findInZipFileAsResource(String prefix, String filename) { - URL zip = null; + URL zip = null; zip = getClass().getResource(zipfile); - if ( zip != null ) + if (zip != null) try { - String path = "jar:"+zip.toExternalForm()+ "!/"+subdir+filename; + String path = "jar:" + zip.toExternalForm() + "!/" + subdir + filename; URL url = new URL(path); return url.openStream(); } catch (IOException ioe) { @@ -144,47 +146,47 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder { } return null; } - + // */ protected void runTest(String testName) { try { // override print() final ByteArrayOutputStream output = new ByteArrayOutputStream(); final PrintStream oldps = globals.STDOUT; - final PrintStream ps = new PrintStream( output ); + 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"); - + assertEquals(expectedOutput, actualOutput); } finally { globals.STDOUT = oldps; ps.close(); } - } catch ( IOException ioe ) { + } catch (IOException ioe) { throw new RuntimeException(ioe.toString()); - } catch ( InterruptedException ie ) { + } catch (InterruptedException ie) { throw new RuntimeException(ie.toString()); } } protected LuaValue loadScript(String name, Globals globals) throws IOException { - InputStream script = this.findResource(name+".lua"); - if ( script == null ) + InputStream script = this.findResource(name + ".lua"); + if (script == null) fail("Could not load script for test case: " + name); try { - switch ( this.platform ) { + switch (this.platform) { case LUAJIT: - if ( nocompile ) { + if (nocompile) { LuaValue c = (LuaValue) Class.forName(name).newInstance(); return c; } else { @@ -192,48 +194,47 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder { return globals.load(script, name, "bt", globals); } default: - return globals.load(script, "@"+name+".lua", "bt", globals); + return globals.load(script, "@" + name + ".lua", "bt", globals); } - } catch ( Exception e ) { + } catch (Exception e) { e.printStackTrace(); - throw new IOException( e.toString() ); + throw new IOException(e.toString()); } finally { script.close(); } } - private String getExpectedOutput(final String name) throws IOException, - InterruptedException { - InputStream output = this.findResource(name+".out"); + private String getExpectedOutput(final String name) throws IOException, InterruptedException { + InputStream output = this.findResource(name + ".out"); 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; + 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 = findResource(name+".lua"); - if ( script == null ) - throw new IOException("Failed to find source file "+script); + InputStream script = findResource(name + ".lua"); + 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() }; + 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(); } } - + public static String collectProcessOutput(String[] cmd, final InputStream input) - throws IOException, InterruptedException { + throws IOException, InterruptedException { Runtime r = Runtime.getRuntime(); final ByteArrayOutputStream baos = new ByteArrayOutputStream(); new JseProcess(cmd, input, baos, System.err).waitFor(); @@ -249,7 +250,7 @@ public class ScriptDrivenTest extends TestCase implements ResourceFinder { private static void copy(InputStream is, OutputStream os) throws IOException { byte[] buf = new byte[1024]; int r; - while ((r = is.read(buf)) >= 0) { + while ( (r = is.read(buf)) >= 0 ) { os.write(buf, 0, r); } } diff --git a/luaj-test/src/test/java/org/luaj/vm2/StringTest.java b/luaj-test/src/test/java/org/luaj/vm2/StringTest.java index ff01d0d6..fba65726 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/StringTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/StringTest.java @@ -16,52 +16,51 @@ public class StringTest extends TestCase { public void testToInputStream() throws IOException { LuaString str = LuaString.valueOf("Hello"); - + InputStream is = str.toInputStream(); - - assertEquals( 'H', is.read() ); - assertEquals( 'e', is.read() ); - assertEquals( 2, is.skip( 2 ) ); - assertEquals( 'o', is.read() ); - assertEquals( -1, is.read() ); - - assertTrue( is.markSupported() ); - + + assertEquals('H', is.read()); + assertEquals('e', is.read()); + assertEquals(2, is.skip(2)); + assertEquals('o', is.read()); + assertEquals(-1, is.read()); + + assertTrue(is.markSupported()); + is.reset(); - - assertEquals( 'H', is.read() ); - is.mark( 4 ); - - assertEquals( 'e', is.read() ); + + assertEquals('H', is.read()); + is.mark(4); + + assertEquals('e', is.read()); is.reset(); - assertEquals( 'e', is.read() ); - - LuaString substr = str.substring( 1, 4 ); - assertEquals( 3, substr.length() ); - + assertEquals('e', is.read()); + + LuaString substr = str.substring(1, 4); + assertEquals(3, substr.length()); + is.close(); is = substr.toInputStream(); - - assertEquals( 'e', is.read() ); - assertEquals( 'l', is.read() ); - assertEquals( 'l', is.read() ); - assertEquals( -1, is.read() ); - + + assertEquals('e', is.read()); + assertEquals('l', is.read()); + assertEquals('l', is.read()); + assertEquals(-1, is.read()); + is = substr.toInputStream(); is.reset(); - - assertEquals( 'e', is.read() ); + + assertEquals('e', is.read()); } - - - private static final String userFriendly( String s ) { + + private static final String userFriendly(String s) { StringBuffer sb = new StringBuffer(); - for ( int i=0, n=s.length(); i= 0x80 ) { - sb.append( "\\u"+Integer.toHexString(0x10000+c).substring(1) ); + if (c < ' ' || c >= 0x80) { + sb.append("\\u" + Integer.toHexString(0x10000+c).substring(1)); } else { - sb.append( (char) c ); + sb.append((char) c); } } return sb.toString(); @@ -70,29 +69,30 @@ public class StringTest extends TestCase { public void testUtf820482051() throws UnsupportedEncodingException { int i = 2048; char[] c = { (char) (i+0), (char) (i+1), (char) (i+2), (char) (i+3) }; - String before = new String(c)+" "+i+"-"+(i+4); + String before = new String(c) + " " + i + "-" + (i+4); LuaString ls = LuaString.valueOf(before); String after = ls.tojstring(); - assertEquals( userFriendly( before ), userFriendly( after ) ); + assertEquals(userFriendly(before), userFriendly(after)); } - - public void testUtf8() { - for ( int i=4; i<0xffff; i+=4 ) { + + public void testUtf8() { + for (int i = 4; i < 0xffff; i += 4) { char[] c = { (char) (i+0), (char) (i+1), (char) (i+2), (char) (i+3) }; - String before = new String(c)+" "+i+"-"+(i+4); + String before = new String(c) + " " + i + "-" + (i+4); LuaString ls = LuaString.valueOf(before); String after = ls.tojstring(); - assertEquals( userFriendly( before ), userFriendly( after ) ); + assertEquals(userFriendly(before), userFriendly(after)); } char[] c = { (char) (1), (char) (2), (char) (3) }; - String before = new String(c)+" 1-3"; + String before = new String(c) + " 1-3"; LuaString ls = LuaString.valueOf(before); String after = ls.tojstring(); - assertEquals( userFriendly( before ), userFriendly( after ) ); + assertEquals(userFriendly(before), userFriendly(after)); } public void testSpotCheckUtf8() throws UnsupportedEncodingException { - byte[] bytes = {(byte)194,(byte)160,(byte)194,(byte)161,(byte)194,(byte)162,(byte)194,(byte)163,(byte)194,(byte)164}; + byte[] bytes = { (byte) 194, (byte) 160, (byte) 194, (byte) 161, (byte) 194, (byte) 162, (byte) 194, (byte) 163, + (byte) 194, (byte) 164 }; String expected = new String(bytes, "UTF8"); String actual = LuaString.valueOf(bytes).tojstring(); char[] d = actual.toCharArray(); @@ -103,37 +103,37 @@ public class StringTest extends TestCase { assertEquals(164, d[4]); assertEquals(expected, actual); } - - public void testNullTerminated() { + + public void testNullTerminated() { char[] c = { 'a', 'b', 'c', '\0', 'd', 'e', 'f' }; String before = new String(c); LuaString ls = LuaString.valueOf(before); String after = ls.tojstring(); - assertEquals( userFriendly( "abc\0def" ), userFriendly( after ) ); + assertEquals(userFriendly("abc\0def"), userFriendly(after)); } public void testRecentStringsCacheDifferentHashcodes() { - final byte[] abc = {'a', 'b', 'c' }; - final byte[] xyz = {'x', 'y', 'z' }; + final byte[] abc = { 'a', 'b', 'c' }; + final byte[] xyz = { 'x', 'y', 'z' }; final LuaString abc1 = LuaString.valueOf(abc); final LuaString xyz1 = LuaString.valueOf(xyz); final LuaString abc2 = LuaString.valueOf(abc); final LuaString xyz2 = LuaString.valueOf(xyz); final int mod = LuaString.RECENT_STRINGS_CACHE_SIZE; - assertTrue(abc1.hashCode() % mod != xyz1.hashCode() % mod); + assertTrue(abc1.hashCode()%mod != xyz1.hashCode()%mod); assertSame(abc1, abc2); assertSame(xyz1, xyz2); } public void testRecentStringsCacheHashCollisionCacheHit() { - final byte[] abc = {'a', 'b', 'c' }; - final byte[] lyz = {'l', 'y', 'z' }; // chosen to have hash collision with 'abc' + final byte[] abc = { 'a', 'b', 'c' }; + final byte[] lyz = { 'l', 'y', 'z' }; // chosen to have hash collision with 'abc' final LuaString abc1 = LuaString.valueOf(abc); final LuaString abc2 = LuaString.valueOf(abc); // in cache: 'abc' final LuaString lyz1 = LuaString.valueOf(lyz); final LuaString lyz2 = LuaString.valueOf(lyz); // in cache: 'lyz' final int mod = LuaString.RECENT_STRINGS_CACHE_SIZE; - assertEquals(abc1.hashCode() % mod, lyz1.hashCode() % mod); + assertEquals(abc1.hashCode()%mod, lyz1.hashCode()%mod); assertNotSame(abc1, lyz1); assertFalse(abc1.equals(lyz1)); assertSame(abc1, abc2); @@ -141,14 +141,14 @@ public class StringTest extends TestCase { } public void testRecentStringsCacheHashCollisionCacheMiss() { - final byte[] abc = {'a', 'b', 'c' }; - final byte[] lyz = {'l', 'y', 'z' }; // chosen to have hash collision with 'abc' + final byte[] abc = { 'a', 'b', 'c' }; + final byte[] lyz = { 'l', 'y', 'z' }; // chosen to have hash collision with 'abc' final LuaString abc1 = LuaString.valueOf(abc); final LuaString lyz1 = LuaString.valueOf(lyz); // in cache: 'abc' final LuaString abc2 = LuaString.valueOf(abc); // in cache: 'lyz' final LuaString lyz2 = LuaString.valueOf(lyz); // in cache: 'abc' final int mod = LuaString.RECENT_STRINGS_CACHE_SIZE; - assertEquals(abc1.hashCode() % mod, lyz1.hashCode() % mod); + assertEquals(abc1.hashCode()%mod, lyz1.hashCode()%mod); assertNotSame(abc1, lyz1); assertFalse(abc1.equals(lyz1)); assertNotSame(abc1, abc2); @@ -165,7 +165,7 @@ public class StringTest extends TestCase { public void testRecentStringsUsingJavaStrings() { final String abc = "abc"; - final String lyz = "lyz"; // chosen to have hash collision with 'abc' + final String lyz = "lyz"; // chosen to have hash collision with 'abc' final String xyz = "xyz"; final LuaString abc1 = LuaString.valueOf(abc); @@ -175,8 +175,8 @@ public class StringTest extends TestCase { final LuaString xyz1 = LuaString.valueOf(xyz); final LuaString xyz2 = LuaString.valueOf(xyz); final int mod = LuaString.RECENT_STRINGS_CACHE_SIZE; - assertEquals(abc1.hashCode() % mod, lyz1.hashCode() % mod); - assertFalse(abc1.hashCode() % mod == xyz1.hashCode() % mod); + assertEquals(abc1.hashCode()%mod, lyz1.hashCode()%mod); + assertFalse(abc1.hashCode()%mod == xyz1.hashCode()%mod); assertSame(abc1, abc2); assertSame(lyz1, lyz2); assertSame(xyz1, xyz2); @@ -188,11 +188,11 @@ public class StringTest extends TestCase { final LuaString abc4 = LuaString.valueOf(abc); final LuaString lyz4 = LuaString.valueOf(lyz); final LuaString xyz4 = LuaString.valueOf(xyz); - assertNotSame(abc3, abc4); // because of hash collision - assertNotSame(lyz3, lyz4); // because of hash collision - assertSame(xyz3, xyz4); // because hashes do not collide + assertNotSame(abc3, abc4); // because of hash collision + assertNotSame(lyz3, lyz4); // because of hash collision + assertSame(xyz3, xyz4); // because hashes do not collide } - + public void testLongSubstringGetsOldBacking() { LuaString src = LuaString.valueOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); LuaString sub1 = src.substring(10, 40); @@ -200,7 +200,7 @@ public class StringTest extends TestCase { assertEquals(sub1.m_offset, 10); assertEquals(sub1.m_length, 30); } - + public void testShortSubstringGetsNewBacking() { LuaString src = LuaString.valueOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); LuaString sub1 = src.substring(10, 20); @@ -210,11 +210,10 @@ public class StringTest extends TestCase { assertSame(sub1, sub2); assertFalse(src.m_bytes == sub1.m_bytes); } - + public void testShortSubstringOfVeryLongStringGetsNewBacking() { - LuaString src = LuaString.valueOf( - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ); + LuaString src = LuaString.valueOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); LuaString sub1 = src.substring(10, 50); LuaString sub2 = src.substring(10, 50); assertEquals(sub1.m_offset, 0); @@ -230,7 +229,7 @@ public class StringTest extends TestCase { assertEquals(8, sub.m_length); assertEquals(0, str.m_offset); assertEquals(2, sub.m_offset); - + assertEquals(6, str.indexOf((byte) ':', 0)); assertEquals(6, str.indexOf((byte) ':', 2)); assertEquals(6, str.indexOf((byte) ':', 6)); @@ -267,7 +266,7 @@ public class StringTest extends TestCase { LuaString pat = LuaString.valueOf(":"); LuaString i = LuaString.valueOf("i"); LuaString xyz = LuaString.valueOf("xyz"); - + assertEquals(6, str.indexOf(pat, 0)); assertEquals(6, str.indexOf(pat, 2)); assertEquals(6, str.indexOf(pat, 6)); @@ -304,7 +303,7 @@ public class StringTest extends TestCase { LuaString pat = LuaString.valueOf(":"); LuaString i = LuaString.valueOf("i"); LuaString xyz = LuaString.valueOf("xyz"); - + assertEquals(6, str.lastIndexOf(pat)); assertEquals(9, str.lastIndexOf(i)); assertEquals(-1, str.lastIndexOf(xyz)); @@ -325,14 +324,14 @@ public class StringTest extends TestCase { LuaString ghi = LuaString.valueOf("ghi"); LuaString ihg = LuaString.valueOf("ihg"); LuaString ijk = LuaString.valueOf("ijk"); - LuaString kji= LuaString.valueOf("kji"); + LuaString kji = LuaString.valueOf("kji"); LuaString xyz = LuaString.valueOf("xyz"); LuaString ABCdEFGHIJKL = LuaString.valueOf("ABCdEFGHIJKL"); LuaString EFGHIJKL = ABCdEFGHIJKL.substring(4, 12); LuaString CdEFGHIJ = ABCdEFGHIJKL.substring(2, 10); assertEquals(4, EFGHIJKL.m_offset); assertEquals(2, CdEFGHIJ.m_offset); - + assertEquals(7, str.indexOfAny(ghi)); assertEquals(7, str.indexOfAny(ihg)); assertEquals(9, str.indexOfAny(ijk)); @@ -349,7 +348,7 @@ public class StringTest extends TestCase { assertEquals(1, sub.indexOfAny(CdEFGHIJ)); assertEquals(-1, sub.indexOfAny(EFGHIJKL)); } - + public void testMatchShortPatterns() { LuaValue[] args = { LuaString.valueOf("%bxy") }; LuaString _ = LuaString.valueOf(""); @@ -363,7 +362,7 @@ public class StringTest extends TestCase { LuaString xby = LuaString.valueOf("xby"); LuaString axbya = LuaString.valueOf("axbya"); LuaValue nil = LuaValue.NIL; - + assertEquals(nil, _.invokemethod("match", args)); assertEquals(nil, a.invokemethod("match", args)); assertEquals(nil, ax.invokemethod("match", args)); @@ -373,9 +372,9 @@ public class StringTest extends TestCase { 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)); + 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/luaj-test/src/test/java/org/luaj/vm2/TableHashTest.java b/luaj-test/src/test/java/org/luaj/vm2/TableHashTest.java index b36b84cc..67b92743 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/TableHashTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/TableHashTest.java @@ -29,239 +29,238 @@ import org.luaj.vm2.LuaValue; import org.luaj.vm2.lib.TwoArgFunction; /** - * Tests for tables used as lists. + * Tests for tables used as lists. */ public class TableHashTest extends TestCase { - + protected LuaTable new_Table() { return new LuaTable(); } - - protected LuaTable new_Table(int n,int m) { - return new LuaTable(n,m); + + protected LuaTable new_Table(int n, int m) { + return new LuaTable(n, m); } - + public void testSetRemove() { LuaTable t = new_Table(); - - assertEquals( 0, t.getHashLength() ); - assertEquals( 0, t.length() ); - assertEquals( 0, t.keyCount() ); - - String[] keys = { "abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "wxy", "z01", - "cd", "ef", "g", "hi", "jk", "lm", "no", "pq", "rs", }; + + assertEquals(0, t.getHashLength()); + assertEquals(0, t.length()); + assertEquals(0, t.keyCount()); + + String[] keys = { "abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "wxy", "z01", "cd", "ef", "g", "hi", "jk", + "lm", "no", "pq", "rs", }; int[] capacities = { 0, 2, 2, 4, 4, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 32, 32, 32 }; - for ( int i = 0; i < keys.length; ++i ) { - assertEquals( capacities[i], t.getHashLength() ); - String si = "Test Value! "+i; - t.set( keys[i], si ); - assertEquals( 0, t.length() ); - assertEquals( i+1, t.keyCount() ); + for (int i = 0; i < keys.length; ++i) { + assertEquals(capacities[i], t.getHashLength()); + String si = "Test Value! " + i; + t.set(keys[i], si); + assertEquals(0, t.length()); + assertEquals(i+1, t.keyCount()); } - assertEquals( capacities[keys.length], t.getHashLength() ); - for ( int i = 0; i < keys.length; ++i ) { - LuaValue vi = LuaString.valueOf( "Test Value! "+i ); - assertEquals( vi, t.get( keys[i] ) ); - assertEquals( vi, t.get( LuaString.valueOf(keys[i]) ) ); - assertEquals( vi, t.rawget( keys[i] ) ); - assertEquals( vi, t.rawget( keys[i] ) ); + assertEquals(capacities[keys.length], t.getHashLength()); + for (int i = 0; i < keys.length; ++i) { + LuaValue vi = LuaString.valueOf("Test Value! " + i); + assertEquals(vi, t.get(keys[i])); + assertEquals(vi, t.get(LuaString.valueOf(keys[i]))); + assertEquals(vi, t.rawget(keys[i])); + assertEquals(vi, t.rawget(keys[i])); } // replace with new values - for ( int i = 0; i < keys.length; ++i ) { - t.set( keys[i], LuaString.valueOf( "Replacement Value! "+i ) ); - assertEquals( 0, t.length() ); - assertEquals( keys.length, t.keyCount() ); - assertEquals( capacities[keys.length], t.getHashLength() ); + for (int i = 0; i < keys.length; ++i) { + t.set(keys[i], LuaString.valueOf("Replacement Value! " + i)); + assertEquals(0, t.length()); + assertEquals(keys.length, t.keyCount()); + assertEquals(capacities[keys.length], t.getHashLength()); } - for ( int i = 0; i < keys.length; ++i ) { - LuaValue vi = LuaString.valueOf( "Replacement Value! "+i ); - assertEquals( vi, t.get( keys[i] ) ); + for (int i = 0; i < keys.length; ++i) { + LuaValue vi = LuaString.valueOf("Replacement Value! " + i); + assertEquals(vi, t.get(keys[i])); } // remove - for ( int i = 0; i < keys.length; ++i ) { - t.set( keys[i], LuaValue.NIL ); - assertEquals( 0, t.length() ); - assertEquals( keys.length-i-1, t.keyCount() ); - if ( i l = new ArrayList(); LuaValue k = LuaValue.NIL; while ( true ) { Varargs n = t.next(k); - if ( (k = n.arg1()).isnil() ) + if ((k = n.arg1()).isnil()) break; - l.add( k ); + l.add(k); } return l.toArray(new LuaValue[t.length()]); } - - + public void testInOrderIntegerKeyInsertion() { LuaTable t = new_Table(); - - for ( int i = 1; i <= 32; ++i ) { - t.set( i, LuaValue.valueOf( "Test Value! "+i ) ); + + for (int i = 1; i <= 32; ++i) { + t.set(i, LuaValue.valueOf("Test Value! " + i)); } // Ensure all keys are still there. - for ( int i = 1; i <= 32; ++i ) { - assertEquals( "Test Value! " + i, t.get( i ).tojstring() ); + for (int i = 1; i <= 32; ++i) { + assertEquals("Test Value! " + i, t.get(i).tojstring()); } - + // Ensure capacities make sense - assertEquals( 0, t.getHashLength() ); - - assertTrue( t.getArrayLength() >= 32 ); - assertTrue( t.getArrayLength() <= 64 ); - + assertEquals(0, t.getHashLength()); + + assertTrue(t.getArrayLength() >= 32); + assertTrue(t.getArrayLength() <= 64); + } - + public void testRekeyCount() { LuaTable t = new_Table(); - + // NOTE: This order of insertion is important. t.set(3, LuaInteger.valueOf(3)); t.set(1, LuaInteger.valueOf(1)); @@ -83,142 +82,142 @@ public class TableTest extends TestCase { t.set(4, LuaInteger.valueOf(4)); t.set(6, LuaInteger.valueOf(6)); t.set(2, LuaInteger.valueOf(2)); - - for ( int i = 1; i < 6; ++i ) { + + for (int i = 1; i < 6; ++i) { assertEquals(LuaInteger.valueOf(i), t.get(i)); } - - assertTrue( t.getArrayLength() >= 3 ); - assertTrue( t.getArrayLength() <= 12 ); - assertTrue( t.getHashLength() <= 3 ); + + assertTrue(t.getArrayLength() >= 3); + assertTrue(t.getArrayLength() <= 12); + assertTrue(t.getHashLength() <= 3); } - + public void testOutOfOrderIntegerKeyInsertion() { LuaTable t = new_Table(); - - for ( int i = 32; i > 0; --i ) { - t.set( i, LuaValue.valueOf( "Test Value! "+i ) ); + + for (int i = 32; i > 0; --i) { + t.set(i, LuaValue.valueOf("Test Value! " + i)); } // Ensure all keys are still there. - for ( int i = 1; i <= 32; ++i ) { - assertEquals( "Test Value! "+i, t.get( i ).tojstring() ); + for (int i = 1; i <= 32; ++i) { + assertEquals("Test Value! " + i, t.get(i).tojstring()); } - + // Ensure capacities make sense - assertEquals( 32, t.getArrayLength() ); - assertEquals( 0, t.getHashLength() ); + assertEquals(32, t.getArrayLength()); + assertEquals(0, t.getHashLength()); } - + public void testStringAndIntegerKeys() { LuaTable t = new_Table(); - - for ( int i = 0; i < 10; ++i ) { - LuaString str = LuaValue.valueOf( String.valueOf( i ) ); - t.set( i, str ); - t.set( str, LuaInteger.valueOf( i ) ); + + for (int i = 0; i < 10; ++i) { + LuaString str = LuaValue.valueOf(String.valueOf(i)); + t.set(i, str); + t.set(str, LuaInteger.valueOf(i)); } - - assertTrue( t.getArrayLength() >= 8 ); // 1, 2, ..., 9 - assertTrue( t.getArrayLength() <= 16 ); - assertTrue( t.getHashLength() >= 11 ); // 0, "0", "1", ..., "9" - assertTrue( t.getHashLength() <= 33 ); - + + assertTrue(t.getArrayLength() >= 8); // 1, 2, ..., 9 + assertTrue(t.getArrayLength() <= 16); + assertTrue(t.getHashLength() >= 11); // 0, "0", "1", ..., "9" + assertTrue(t.getHashLength() <= 33); + LuaValue[] keys = keys(t); - + int intKeys = 0; int stringKeys = 0; - - assertEquals( 20, keys.length ); - for ( int i = 0; i < keys.length; ++i ) { + + assertEquals(20, keys.length); + for (int i = 0; i < keys.length; ++i) { LuaValue k = keys[i]; - - if ( k instanceof LuaInteger ) { + + if (k instanceof LuaInteger) { final int ik = k.toint(); - assertTrue( ik >= 0 && ik < 10 ); - final int mask = 1 << ik; - assertTrue( ( intKeys & mask ) == 0 ); + assertTrue(ik >= 0 && ik < 10); + final int mask = 1<= 0 && ik < 10 ); - final int mask = 1 << ik; - assertTrue( "Key \""+ik+"\" found more than once", ( stringKeys & mask ) == 0 ); + } else if (k instanceof LuaString) { + final int ik = Integer.parseInt(k.strvalue().tojstring()); + assertEquals(String.valueOf(ik), k.strvalue().tojstring()); + assertTrue(ik >= 0 && ik < 10); + final int mask = 1< 0; --i ) { - t.set( i, LuaValue.valueOf( "Test Value! "+i ) ); + for (int j = 8; j < 32; j += 8) { + for (int i = j; i > 0; --i) { + t.set(i, LuaValue.valueOf("Test Value! " + i)); } - assertEquals( j, t.length() ); + assertEquals(j, t.length()); } } - + public void testStringKeysLuaLength() { LuaTable t = new_Table(); - - for ( int i = 1; i <= 32; ++i ) { - t.set( "str-"+i, LuaValue.valueOf( "String Key Test Value! "+i ) ); - assertEquals( 0, t.length() ); + + for (int i = 1; i <= 32; ++i) { + t.set("str-" + i, LuaValue.valueOf("String Key Test Value! " + i)); + assertEquals(0, t.length()); } } public void testMixedKeysLuaLength() { LuaTable t = new_Table(); - - for ( int i = 1; i <= 32; ++i ) { - t.set( "str-"+i, LuaValue.valueOf( "String Key Test Value! "+i ) ); - t.set( i, LuaValue.valueOf( "Int Key Test Value! "+i ) ); - assertEquals( i, t.length() ); + + for (int i = 1; i <= 32; ++i) { + t.set("str-" + i, LuaValue.valueOf("String Key Test Value! " + i)); + t.set(i, LuaValue.valueOf("Int Key Test Value! " + i)); + assertEquals(i, t.length()); } } - private static final void compareLists(LuaTable t,Vector v) { + private static final void compareLists(LuaTable t, Vector v) { int n = v.size(); - assertEquals(v.size(),t.length()); - for ( int j=0; j expected = new java.util.ArrayList(); Varargs n; int i; for (n = t.next(LuaValue.NIL), i = 0; !n.arg1().isnil(); n = t.next(n.arg1()), ++i) { - if (i % 2 == 0) + if (i%2 == 0) expected.add(n.arg1() + "=" + n.arg(2)); } // Remove every other key while iterating over the table. for (n = t.next(LuaValue.NIL), i = 0; !n.arg1().isnil(); n = t.next(n.arg1()), ++i) { - if (i % 2 != 0) + if (i%2 != 0) t.set(n.arg1(), LuaValue.NIL); } // Iterate over remaining table, and form list of entries still in table. @@ -415,5 +408,5 @@ public class TableTest extends TestCase { actual.add(n.arg1() + "=" + n.arg(2)); } assertEquals(expected, actual); - } + } } diff --git a/luaj-test/src/test/java/org/luaj/vm2/TypeTest.java b/luaj-test/src/test/java/org/luaj/vm2/TypeTest.java index 74535e43..e0d583b1 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/TypeTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/TypeTest.java @@ -32,1215 +32,1208 @@ public class TypeTest extends TestCase { static { JsePlatform.debugGlobals(); } - - private final int sampleint = 77; - private final long samplelong = 123400000000L; - private final double sampledouble = 55.25; + + private final int sampleint = 77; + private final long samplelong = 123400000000L; + private final double sampledouble = 55.25; private final String samplestringstring = "abcdef"; - private final String samplestringint = String.valueOf(sampleint); - private final String samplestringlong = String.valueOf(samplelong); + private final String samplestringint = String.valueOf(sampleint); + private final String samplestringlong = String.valueOf(samplelong); private final String samplestringdouble = String.valueOf(sampledouble); - private final Object sampleobject = new Object(); - private final MyData sampledata = new MyData(); - - private final LuaValue somenil = LuaValue.NIL; - private final LuaValue sometrue = LuaValue.TRUE; - private final LuaValue somefalse = LuaValue.FALSE; - private final LuaValue zero = LuaValue.ZERO; - private final LuaValue intint = LuaValue.valueOf(sampleint); - private final LuaValue longdouble = LuaValue.valueOf(samplelong); - private final LuaValue doubledouble = LuaValue.valueOf(sampledouble); - private final LuaValue stringstring = LuaValue.valueOf(samplestringstring); - private final LuaValue stringint = LuaValue.valueOf(samplestringint); - private final LuaValue stringlong = LuaValue.valueOf(samplestringlong); - private final LuaValue stringdouble = LuaValue.valueOf(samplestringdouble); - private final LuaTable table = LuaValue.tableOf(); - private final LuaFunction somefunc = new ZeroArgFunction() { public LuaValue call() { return NONE;}}; - private final LuaThread thread = new LuaThread(new Globals(), somefunc); - private final LuaClosure someclosure = new LuaClosure(new Prototype(), new LuaTable()); - private final LuaUserdata userdataobj = LuaValue.userdataOf(sampleobject); - private final LuaUserdata userdatacls = LuaValue.userdataOf(sampledata); - + private final Object sampleobject = new Object(); + private final MyData sampledata = new MyData(); + + private final LuaValue somenil = LuaValue.NIL; + private final LuaValue sometrue = LuaValue.TRUE; + private final LuaValue somefalse = LuaValue.FALSE; + private final LuaValue zero = LuaValue.ZERO; + private final LuaValue intint = LuaValue.valueOf(sampleint); + private final LuaValue longdouble = LuaValue.valueOf(samplelong); + private final LuaValue doubledouble = LuaValue.valueOf(sampledouble); + private final LuaValue stringstring = LuaValue.valueOf(samplestringstring); + private final LuaValue stringint = LuaValue.valueOf(samplestringint); + private final LuaValue stringlong = LuaValue.valueOf(samplestringlong); + private final LuaValue stringdouble = LuaValue.valueOf(samplestringdouble); + private final LuaTable table = LuaValue.tableOf(); + private final LuaFunction somefunc = new ZeroArgFunction() { + public LuaValue call() { return NONE; } + }; + private final LuaThread thread = new LuaThread(new Globals(), somefunc); + private final LuaClosure someclosure = new LuaClosure(new Prototype(), new LuaTable()); + private final LuaUserdata userdataobj = LuaValue.userdataOf(sampleobject); + private final LuaUserdata userdatacls = LuaValue.userdataOf(sampledata); + public static final class MyData { - public MyData() { + public MyData() { } } - + // ===================== type checks ======================= - + public void testIsBoolean() { - assertEquals( false, somenil.isboolean() ); - assertEquals( true, sometrue.isboolean() ); - assertEquals( true, somefalse.isboolean() ); - assertEquals( false, zero.isboolean() ); - assertEquals( false, intint.isboolean() ); - assertEquals( false, longdouble.isboolean() ); - assertEquals( false, doubledouble.isboolean() ); - assertEquals( false, stringstring.isboolean() ); - assertEquals( false, stringint.isboolean() ); - assertEquals( false, stringlong.isboolean() ); - assertEquals( false, stringdouble.isboolean() ); - assertEquals( false, thread.isboolean() ); - assertEquals( false, table.isboolean() ); - assertEquals( false, userdataobj.isboolean() ); - assertEquals( false, userdatacls.isboolean() ); - assertEquals( false, somefunc.isboolean() ); - assertEquals( false, someclosure.isboolean() ); + assertEquals(false, somenil.isboolean()); + assertEquals(true, sometrue.isboolean()); + assertEquals(true, somefalse.isboolean()); + assertEquals(false, zero.isboolean()); + assertEquals(false, intint.isboolean()); + assertEquals(false, longdouble.isboolean()); + assertEquals(false, doubledouble.isboolean()); + assertEquals(false, stringstring.isboolean()); + assertEquals(false, stringint.isboolean()); + assertEquals(false, stringlong.isboolean()); + assertEquals(false, stringdouble.isboolean()); + assertEquals(false, thread.isboolean()); + assertEquals(false, table.isboolean()); + assertEquals(false, userdataobj.isboolean()); + assertEquals(false, userdatacls.isboolean()); + assertEquals(false, somefunc.isboolean()); + assertEquals(false, someclosure.isboolean()); } - + public void testIsClosure() { - assertEquals( false, somenil.isclosure() ); - assertEquals( false, sometrue.isclosure() ); - assertEquals( false, somefalse.isclosure() ); - assertEquals( false, zero.isclosure() ); - assertEquals( false, intint.isclosure() ); - assertEquals( false, longdouble.isclosure() ); - assertEquals( false, doubledouble.isclosure() ); - assertEquals( false, stringstring.isclosure() ); - assertEquals( false, stringint.isclosure() ); - assertEquals( false, stringlong.isclosure() ); - assertEquals( false, stringdouble.isclosure() ); - assertEquals( false, thread.isclosure() ); - assertEquals( false, table.isclosure() ); - assertEquals( false, userdataobj.isclosure() ); - assertEquals( false, userdatacls.isclosure() ); - assertEquals( false, somefunc.isclosure() ); - assertEquals( true, someclosure.isclosure() ); + assertEquals(false, somenil.isclosure()); + assertEquals(false, sometrue.isclosure()); + assertEquals(false, somefalse.isclosure()); + assertEquals(false, zero.isclosure()); + assertEquals(false, intint.isclosure()); + assertEquals(false, longdouble.isclosure()); + assertEquals(false, doubledouble.isclosure()); + assertEquals(false, stringstring.isclosure()); + assertEquals(false, stringint.isclosure()); + assertEquals(false, stringlong.isclosure()); + assertEquals(false, stringdouble.isclosure()); + assertEquals(false, thread.isclosure()); + assertEquals(false, table.isclosure()); + assertEquals(false, userdataobj.isclosure()); + assertEquals(false, userdatacls.isclosure()); + assertEquals(false, somefunc.isclosure()); + assertEquals(true, someclosure.isclosure()); } - public void testIsFunction() { - assertEquals( false, somenil.isfunction() ); - assertEquals( false, sometrue.isfunction() ); - assertEquals( false, somefalse.isfunction() ); - assertEquals( false, zero.isfunction() ); - assertEquals( false, intint.isfunction() ); - assertEquals( false, longdouble.isfunction() ); - assertEquals( false, doubledouble.isfunction() ); - assertEquals( false, stringstring.isfunction() ); - assertEquals( false, stringint.isfunction() ); - assertEquals( false, stringlong.isfunction() ); - assertEquals( false, stringdouble.isfunction() ); - assertEquals( false, thread.isfunction() ); - assertEquals( false, table.isfunction() ); - assertEquals( false, userdataobj.isfunction() ); - assertEquals( false, userdatacls.isfunction() ); - assertEquals( true, somefunc.isfunction() ); - assertEquals( true, someclosure.isfunction() ); + assertEquals(false, somenil.isfunction()); + assertEquals(false, sometrue.isfunction()); + assertEquals(false, somefalse.isfunction()); + assertEquals(false, zero.isfunction()); + assertEquals(false, intint.isfunction()); + assertEquals(false, longdouble.isfunction()); + assertEquals(false, doubledouble.isfunction()); + assertEquals(false, stringstring.isfunction()); + assertEquals(false, stringint.isfunction()); + assertEquals(false, stringlong.isfunction()); + assertEquals(false, stringdouble.isfunction()); + assertEquals(false, thread.isfunction()); + assertEquals(false, table.isfunction()); + assertEquals(false, userdataobj.isfunction()); + assertEquals(false, userdatacls.isfunction()); + assertEquals(true, somefunc.isfunction()); + assertEquals(true, someclosure.isfunction()); } - public void testIsInt() { - assertEquals( false, somenil.isint() ); - assertEquals( false, sometrue.isint() ); - assertEquals( false, somefalse.isint() ); - assertEquals( true, zero.isint() ); - assertEquals( true, intint.isint() ); - assertEquals( false, longdouble.isint() ); - assertEquals( false, doubledouble.isint() ); - assertEquals( false, stringstring.isint() ); - assertEquals( true, stringint.isint() ); - assertEquals( false, stringdouble.isint() ); - assertEquals( false, thread.isint() ); - assertEquals( false, table.isint() ); - assertEquals( false, userdataobj.isint() ); - assertEquals( false, userdatacls.isint() ); - assertEquals( false, somefunc.isint() ); - assertEquals( false, someclosure.isint() ); + assertEquals(false, somenil.isint()); + assertEquals(false, sometrue.isint()); + assertEquals(false, somefalse.isint()); + assertEquals(true, zero.isint()); + assertEquals(true, intint.isint()); + assertEquals(false, longdouble.isint()); + assertEquals(false, doubledouble.isint()); + assertEquals(false, stringstring.isint()); + assertEquals(true, stringint.isint()); + assertEquals(false, stringdouble.isint()); + assertEquals(false, thread.isint()); + assertEquals(false, table.isint()); + assertEquals(false, userdataobj.isint()); + assertEquals(false, userdatacls.isint()); + assertEquals(false, somefunc.isint()); + assertEquals(false, someclosure.isint()); } public void testIsIntType() { - assertEquals( false, somenil.isinttype() ); - assertEquals( false, sometrue.isinttype() ); - assertEquals( false, somefalse.isinttype() ); - assertEquals( true, zero.isinttype() ); - assertEquals( true, intint.isinttype() ); - assertEquals( false, longdouble.isinttype() ); - assertEquals( false, doubledouble.isinttype() ); - assertEquals( false, stringstring.isinttype() ); - assertEquals( false, stringint.isinttype() ); - assertEquals( false, stringlong.isinttype() ); - assertEquals( false, stringdouble.isinttype() ); - assertEquals( false, thread.isinttype() ); - assertEquals( false, table.isinttype() ); - assertEquals( false, userdataobj.isinttype() ); - assertEquals( false, userdatacls.isinttype() ); - assertEquals( false, somefunc.isinttype() ); - assertEquals( false, someclosure.isinttype() ); + assertEquals(false, somenil.isinttype()); + assertEquals(false, sometrue.isinttype()); + assertEquals(false, somefalse.isinttype()); + assertEquals(true, zero.isinttype()); + assertEquals(true, intint.isinttype()); + assertEquals(false, longdouble.isinttype()); + assertEquals(false, doubledouble.isinttype()); + assertEquals(false, stringstring.isinttype()); + assertEquals(false, stringint.isinttype()); + assertEquals(false, stringlong.isinttype()); + assertEquals(false, stringdouble.isinttype()); + assertEquals(false, thread.isinttype()); + assertEquals(false, table.isinttype()); + assertEquals(false, userdataobj.isinttype()); + assertEquals(false, userdatacls.isinttype()); + assertEquals(false, somefunc.isinttype()); + assertEquals(false, someclosure.isinttype()); } public void testIsLong() { - assertEquals( false, somenil.islong() ); - assertEquals( false, sometrue.islong() ); - assertEquals( false, somefalse.islong() ); - assertEquals( true, intint.isint() ); - assertEquals( true, longdouble.islong() ); - assertEquals( false, doubledouble.islong() ); - assertEquals( false, stringstring.islong() ); - assertEquals( true, stringint.islong() ); - assertEquals( true, stringlong.islong() ); - assertEquals( false, stringdouble.islong() ); - assertEquals( false, thread.islong() ); - assertEquals( false, table.islong() ); - assertEquals( false, userdataobj.islong() ); - assertEquals( false, userdatacls.islong() ); - assertEquals( false, somefunc.islong() ); - assertEquals( false, someclosure.islong() ); + assertEquals(false, somenil.islong()); + assertEquals(false, sometrue.islong()); + assertEquals(false, somefalse.islong()); + assertEquals(true, intint.isint()); + assertEquals(true, longdouble.islong()); + assertEquals(false, doubledouble.islong()); + assertEquals(false, stringstring.islong()); + assertEquals(true, stringint.islong()); + assertEquals(true, stringlong.islong()); + assertEquals(false, stringdouble.islong()); + assertEquals(false, thread.islong()); + assertEquals(false, table.islong()); + assertEquals(false, userdataobj.islong()); + assertEquals(false, userdatacls.islong()); + assertEquals(false, somefunc.islong()); + assertEquals(false, someclosure.islong()); } public void testIsNil() { - assertEquals( true, somenil.isnil() ); - assertEquals( false, sometrue.isnil() ); - assertEquals( false, somefalse.isnil() ); - assertEquals( false, zero.isnil() ); - assertEquals( false, intint.isnil() ); - assertEquals( false, longdouble.isnil() ); - assertEquals( false, doubledouble.isnil() ); - assertEquals( false, stringstring.isnil() ); - assertEquals( false, stringint.isnil() ); - assertEquals( false, stringlong.isnil() ); - assertEquals( false, stringdouble.isnil() ); - assertEquals( false, thread.isnil() ); - assertEquals( false, table.isnil() ); - assertEquals( false, userdataobj.isnil() ); - assertEquals( false, userdatacls.isnil() ); - assertEquals( false, somefunc.isnil() ); - assertEquals( false, someclosure.isnil() ); + assertEquals(true, somenil.isnil()); + assertEquals(false, sometrue.isnil()); + assertEquals(false, somefalse.isnil()); + assertEquals(false, zero.isnil()); + assertEquals(false, intint.isnil()); + assertEquals(false, longdouble.isnil()); + assertEquals(false, doubledouble.isnil()); + assertEquals(false, stringstring.isnil()); + assertEquals(false, stringint.isnil()); + assertEquals(false, stringlong.isnil()); + assertEquals(false, stringdouble.isnil()); + assertEquals(false, thread.isnil()); + assertEquals(false, table.isnil()); + assertEquals(false, userdataobj.isnil()); + assertEquals(false, userdatacls.isnil()); + assertEquals(false, somefunc.isnil()); + assertEquals(false, someclosure.isnil()); } public void testIsNumber() { - assertEquals( false, somenil.isnumber() ); - assertEquals( false, sometrue.isnumber() ); - assertEquals( false, somefalse.isnumber() ); - assertEquals( true, zero.isnumber() ); - assertEquals( true, intint.isnumber() ); - assertEquals( true, longdouble.isnumber() ); - assertEquals( true, doubledouble.isnumber() ); - assertEquals( false, stringstring.isnumber() ); - assertEquals( true, stringint.isnumber() ); - assertEquals( true, stringlong.isnumber() ); - assertEquals( true, stringdouble.isnumber() ); - assertEquals( false, thread.isnumber() ); - assertEquals( false, table.isnumber() ); - assertEquals( false, userdataobj.isnumber() ); - assertEquals( false, userdatacls.isnumber() ); - assertEquals( false, somefunc.isnumber() ); - assertEquals( false, someclosure.isnumber() ); + assertEquals(false, somenil.isnumber()); + assertEquals(false, sometrue.isnumber()); + assertEquals(false, somefalse.isnumber()); + assertEquals(true, zero.isnumber()); + assertEquals(true, intint.isnumber()); + assertEquals(true, longdouble.isnumber()); + assertEquals(true, doubledouble.isnumber()); + assertEquals(false, stringstring.isnumber()); + assertEquals(true, stringint.isnumber()); + assertEquals(true, stringlong.isnumber()); + assertEquals(true, stringdouble.isnumber()); + assertEquals(false, thread.isnumber()); + assertEquals(false, table.isnumber()); + assertEquals(false, userdataobj.isnumber()); + assertEquals(false, userdatacls.isnumber()); + assertEquals(false, somefunc.isnumber()); + assertEquals(false, someclosure.isnumber()); } public void testIsString() { - assertEquals( false, somenil.isstring() ); - assertEquals( false, sometrue.isstring() ); - assertEquals( false, somefalse.isstring() ); - assertEquals( true, zero.isstring() ); - assertEquals( true, longdouble.isstring() ); - assertEquals( true, doubledouble.isstring() ); - assertEquals( true, stringstring.isstring() ); - assertEquals( true, stringint.isstring() ); - assertEquals( true, stringlong.isstring() ); - assertEquals( true, stringdouble.isstring() ); - assertEquals( false, thread.isstring() ); - assertEquals( false, table.isstring() ); - assertEquals( false, userdataobj.isstring() ); - assertEquals( false, userdatacls.isstring() ); - assertEquals( false, somefunc.isstring() ); - assertEquals( false, someclosure.isstring() ); + assertEquals(false, somenil.isstring()); + assertEquals(false, sometrue.isstring()); + assertEquals(false, somefalse.isstring()); + assertEquals(true, zero.isstring()); + assertEquals(true, longdouble.isstring()); + assertEquals(true, doubledouble.isstring()); + assertEquals(true, stringstring.isstring()); + assertEquals(true, stringint.isstring()); + assertEquals(true, stringlong.isstring()); + assertEquals(true, stringdouble.isstring()); + assertEquals(false, thread.isstring()); + assertEquals(false, table.isstring()); + assertEquals(false, userdataobj.isstring()); + assertEquals(false, userdatacls.isstring()); + assertEquals(false, somefunc.isstring()); + assertEquals(false, someclosure.isstring()); } public void testIsThread() { - assertEquals( false, somenil.isthread() ); - assertEquals( false, sometrue.isthread() ); - assertEquals( false, somefalse.isthread() ); - assertEquals( false, intint.isthread() ); - assertEquals( false, longdouble.isthread() ); - assertEquals( false, doubledouble.isthread() ); - assertEquals( false, stringstring.isthread() ); - assertEquals( false, stringint.isthread() ); - assertEquals( false, stringdouble.isthread() ); - assertEquals( true, thread.isthread() ); - assertEquals( false, table.isthread() ); - assertEquals( false, userdataobj.isthread() ); - assertEquals( false, userdatacls.isthread() ); - assertEquals( false, somefunc.isthread() ); - assertEquals( false, someclosure.isthread() ); + assertEquals(false, somenil.isthread()); + assertEquals(false, sometrue.isthread()); + assertEquals(false, somefalse.isthread()); + assertEquals(false, intint.isthread()); + assertEquals(false, longdouble.isthread()); + assertEquals(false, doubledouble.isthread()); + assertEquals(false, stringstring.isthread()); + assertEquals(false, stringint.isthread()); + assertEquals(false, stringdouble.isthread()); + assertEquals(true, thread.isthread()); + assertEquals(false, table.isthread()); + assertEquals(false, userdataobj.isthread()); + assertEquals(false, userdatacls.isthread()); + assertEquals(false, somefunc.isthread()); + assertEquals(false, someclosure.isthread()); } public void testIsTable() { - assertEquals( false, somenil.istable() ); - assertEquals( false, sometrue.istable() ); - assertEquals( false, somefalse.istable() ); - assertEquals( false, intint.istable() ); - assertEquals( false, longdouble.istable() ); - assertEquals( false, doubledouble.istable() ); - assertEquals( false, stringstring.istable() ); - assertEquals( false, stringint.istable() ); - assertEquals( false, stringdouble.istable() ); - assertEquals( false, thread.istable() ); - assertEquals( true, table.istable() ); - assertEquals( false, userdataobj.istable() ); - assertEquals( false, userdatacls.istable() ); - assertEquals( false, somefunc.istable() ); - assertEquals( false, someclosure.istable() ); + assertEquals(false, somenil.istable()); + assertEquals(false, sometrue.istable()); + assertEquals(false, somefalse.istable()); + assertEquals(false, intint.istable()); + assertEquals(false, longdouble.istable()); + assertEquals(false, doubledouble.istable()); + assertEquals(false, stringstring.istable()); + assertEquals(false, stringint.istable()); + assertEquals(false, stringdouble.istable()); + assertEquals(false, thread.istable()); + assertEquals(true, table.istable()); + assertEquals(false, userdataobj.istable()); + assertEquals(false, userdatacls.istable()); + assertEquals(false, somefunc.istable()); + assertEquals(false, someclosure.istable()); } public void testIsUserdata() { - assertEquals( false, somenil.isuserdata() ); - assertEquals( false, sometrue.isuserdata() ); - assertEquals( false, somefalse.isuserdata() ); - assertEquals( false, intint.isuserdata() ); - assertEquals( false, longdouble.isuserdata() ); - assertEquals( false, doubledouble.isuserdata() ); - assertEquals( false, stringstring.isuserdata() ); - assertEquals( false, stringint.isuserdata() ); - assertEquals( false, stringdouble.isuserdata() ); - assertEquals( false, thread.isuserdata() ); - assertEquals( false, table.isuserdata() ); - assertEquals( true, userdataobj.isuserdata() ); - assertEquals( true, userdatacls.isuserdata() ); - assertEquals( false, somefunc.isuserdata() ); - assertEquals( false, someclosure.isuserdata() ); - } - - public void testIsUserdataObject() { - assertEquals( false, somenil.isuserdata(Object.class) ); - assertEquals( false, sometrue.isuserdata(Object.class) ); - assertEquals( false, somefalse.isuserdata(Object.class) ); - assertEquals( false, longdouble.isuserdata(Object.class) ); - assertEquals( false, doubledouble.isuserdata(Object.class) ); - assertEquals( false, stringstring.isuserdata(Object.class) ); - assertEquals( false, stringint.isuserdata(Object.class) ); - assertEquals( false, stringdouble.isuserdata(Object.class) ); - assertEquals( false, thread.isuserdata(Object.class) ); - assertEquals( false, table.isuserdata(Object.class) ); - assertEquals( true, userdataobj.isuserdata(Object.class) ); - assertEquals( true, userdatacls.isuserdata(Object.class) ); - assertEquals( false, somefunc.isuserdata(Object.class) ); - assertEquals( false, someclosure.isuserdata(Object.class) ); - } - - public void testIsUserdataMyData() { - assertEquals( false, somenil.isuserdata(MyData.class) ); - assertEquals( false, sometrue.isuserdata(MyData.class) ); - assertEquals( false, somefalse.isuserdata(MyData.class) ); - assertEquals( false, longdouble.isuserdata(MyData.class) ); - assertEquals( false, doubledouble.isuserdata(MyData.class) ); - assertEquals( false, stringstring.isuserdata(MyData.class) ); - assertEquals( false, stringint.isuserdata(MyData.class) ); - assertEquals( false, stringdouble.isuserdata(MyData.class) ); - assertEquals( false, thread.isuserdata(MyData.class) ); - assertEquals( false, table.isuserdata(MyData.class) ); - assertEquals( false, userdataobj.isuserdata(MyData.class) ); - assertEquals( true, userdatacls.isuserdata(MyData.class) ); - assertEquals( false, somefunc.isuserdata(MyData.class) ); - assertEquals( false, someclosure.isuserdata(MyData.class) ); - } - - - // ===================== Coerce to Java ======================= - - public void testToBoolean() { - assertEquals( false, somenil.toboolean() ); - assertEquals( true, sometrue.toboolean() ); - assertEquals( false, somefalse.toboolean() ); - assertEquals( true, zero.toboolean() ); - assertEquals( true, intint.toboolean() ); - assertEquals( true, longdouble.toboolean() ); - assertEquals( true, doubledouble.toboolean() ); - assertEquals( true, stringstring.toboolean() ); - assertEquals( true, stringint.toboolean() ); - assertEquals( true, stringlong.toboolean() ); - assertEquals( true, stringdouble.toboolean() ); - assertEquals( true, thread.toboolean() ); - assertEquals( true, table.toboolean() ); - assertEquals( true, userdataobj.toboolean() ); - assertEquals( true, userdatacls.toboolean() ); - assertEquals( true, somefunc.toboolean() ); - assertEquals( true, someclosure.toboolean() ); - } - - public void testToByte() { - assertEquals( (byte) 0, somenil.tobyte() ); - assertEquals( (byte) 0, somefalse.tobyte() ); - assertEquals( (byte) 0, sometrue.tobyte() ); - assertEquals( (byte) 0, zero.tobyte() ); - assertEquals( (byte) sampleint, intint.tobyte() ); - assertEquals( (byte) samplelong, longdouble.tobyte() ); - assertEquals( (byte) sampledouble, doubledouble.tobyte() ); - assertEquals( (byte) 0, stringstring.tobyte() ); - assertEquals( (byte) sampleint, stringint.tobyte() ); - assertEquals( (byte) samplelong, stringlong.tobyte() ); - assertEquals( (byte) sampledouble, stringdouble.tobyte() ); - assertEquals( (byte) 0, thread.tobyte() ); - assertEquals( (byte) 0, table.tobyte() ); - assertEquals( (byte) 0, userdataobj.tobyte() ); - assertEquals( (byte) 0, userdatacls.tobyte() ); - assertEquals( (byte) 0, somefunc.tobyte() ); - assertEquals( (byte) 0, someclosure.tobyte() ); - } - - public void testToChar() { - assertEquals( (char) 0, somenil.tochar() ); - assertEquals( (char) 0, somefalse.tochar() ); - assertEquals( (char) 0, sometrue.tochar() ); - assertEquals( (char) 0, zero.tochar() ); - assertEquals( (int) (char) sampleint, (int) intint.tochar() ); - assertEquals( (int) (char) samplelong, (int) longdouble.tochar() ); - assertEquals( (int) (char) sampledouble, (int) doubledouble.tochar() ); - assertEquals( (char) 0, stringstring.tochar() ); - assertEquals( (int) (char) sampleint, (int) stringint.tochar() ); - assertEquals( (int) (char) samplelong, (int) stringlong.tochar() ); - assertEquals( (int) (char) sampledouble, (int) stringdouble.tochar() ); - assertEquals( (char) 0, thread.tochar() ); - assertEquals( (char) 0, table.tochar() ); - assertEquals( (char) 0, userdataobj.tochar() ); - assertEquals( (char) 0, userdatacls.tochar() ); - assertEquals( (char) 0, somefunc.tochar() ); - assertEquals( (char) 0, someclosure.tochar() ); - } - - public void testToDouble() { - assertEquals( 0., somenil.todouble() ); - assertEquals( 0., somefalse.todouble() ); - assertEquals( 0., sometrue.todouble() ); - assertEquals( 0., zero.todouble() ); - assertEquals( (double) sampleint, intint.todouble() ); - assertEquals( (double) samplelong, longdouble.todouble() ); - assertEquals( (double) sampledouble, doubledouble.todouble() ); - assertEquals( (double) 0, stringstring.todouble() ); - assertEquals( (double) sampleint, stringint.todouble() ); - assertEquals( (double) samplelong, stringlong.todouble() ); - assertEquals( (double) sampledouble, stringdouble.todouble() ); - assertEquals( 0., thread.todouble() ); - assertEquals( 0., table.todouble() ); - assertEquals( 0., userdataobj.todouble() ); - assertEquals( 0., userdatacls.todouble() ); - assertEquals( 0., somefunc.todouble() ); - assertEquals( 0., someclosure.todouble() ); - } - - public void testToFloat() { - assertEquals( 0.f, somenil.tofloat() ); - assertEquals( 0.f, somefalse.tofloat() ); - assertEquals( 0.f, sometrue.tofloat() ); - assertEquals( 0.f, zero.tofloat() ); - assertEquals( (float) sampleint, intint.tofloat() ); - assertEquals( (float) samplelong, longdouble.tofloat() ); - assertEquals( (float) sampledouble, doubledouble.tofloat() ); - assertEquals( (float) 0, stringstring.tofloat() ); - assertEquals( (float) sampleint, stringint.tofloat() ); - assertEquals( (float) samplelong, stringlong.tofloat() ); - assertEquals( (float) sampledouble, stringdouble.tofloat() ); - assertEquals( 0.f, thread.tofloat() ); - assertEquals( 0.f, table.tofloat() ); - assertEquals( 0.f, userdataobj.tofloat() ); - assertEquals( 0.f, userdatacls.tofloat() ); - assertEquals( 0.f, somefunc.tofloat() ); - assertEquals( 0.f, someclosure.tofloat() ); - } - - public void testToInt() { - assertEquals( 0, somenil.toint() ); - assertEquals( 0, somefalse.toint() ); - assertEquals( 0, sometrue.toint() ); - assertEquals( 0, zero.toint() ); - assertEquals( (int) sampleint, intint.toint() ); - assertEquals( (int) samplelong, longdouble.toint() ); - assertEquals( (int) sampledouble, doubledouble.toint() ); - assertEquals( (int) 0, stringstring.toint() ); - assertEquals( (int) sampleint, stringint.toint() ); - assertEquals( (int) samplelong, stringlong.toint() ); - assertEquals( (int) sampledouble, stringdouble.toint() ); - assertEquals( 0, thread.toint() ); - assertEquals( 0, table.toint() ); - assertEquals( 0, userdataobj.toint() ); - assertEquals( 0, userdatacls.toint() ); - assertEquals( 0, somefunc.toint() ); - assertEquals( 0, someclosure.toint() ); - } - - public void testToLong() { - assertEquals( 0L, somenil.tolong() ); - assertEquals( 0L, somefalse.tolong() ); - assertEquals( 0L, sometrue.tolong() ); - assertEquals( 0L, zero.tolong() ); - assertEquals( (long) sampleint, intint.tolong() ); - assertEquals( (long) samplelong, longdouble.tolong() ); - assertEquals( (long) sampledouble, doubledouble.tolong() ); - assertEquals( (long) 0, stringstring.tolong() ); - assertEquals( (long) sampleint, stringint.tolong() ); - assertEquals( (long) samplelong, stringlong.tolong() ); - assertEquals( (long) sampledouble, stringdouble.tolong() ); - assertEquals( 0L, thread.tolong() ); - assertEquals( 0L, table.tolong() ); - assertEquals( 0L, userdataobj.tolong() ); - assertEquals( 0L, userdatacls.tolong() ); - assertEquals( 0L, somefunc.tolong() ); - assertEquals( 0L, someclosure.tolong() ); - } - - public void testToShort() { - assertEquals( (short) 0, somenil.toshort() ); - assertEquals( (short) 0, somefalse.toshort() ); - assertEquals( (short) 0, sometrue.toshort() ); - assertEquals( (short) 0, zero.toshort() ); - assertEquals( (short) sampleint, intint.toshort() ); - assertEquals( (short) samplelong, longdouble.toshort() ); - assertEquals( (short) sampledouble, doubledouble.toshort() ); - assertEquals( (short) 0, stringstring.toshort() ); - assertEquals( (short) sampleint, stringint.toshort() ); - assertEquals( (short) samplelong, stringlong.toshort() ); - assertEquals( (short) sampledouble, stringdouble.toshort() ); - assertEquals( (short) 0, thread.toshort() ); - assertEquals( (short) 0, table.toshort() ); - assertEquals( (short) 0, userdataobj.toshort() ); - assertEquals( (short) 0, userdatacls.toshort() ); - assertEquals( (short) 0, somefunc.toshort() ); - assertEquals( (short) 0, someclosure.toshort() ); - } - - public void testToString() { - assertEquals( "nil", somenil.tojstring() ); - assertEquals( "false", somefalse.tojstring() ); - assertEquals( "true", sometrue.tojstring() ); - assertEquals( "0", zero.tojstring() ); - assertEquals( String.valueOf(sampleint), intint.tojstring() ); - assertEquals( String.valueOf(samplelong), longdouble.tojstring() ); - assertEquals( String.valueOf(sampledouble), doubledouble.tojstring() ); - assertEquals( samplestringstring, stringstring.tojstring() ); - assertEquals( String.valueOf(sampleint), stringint.tojstring() ); - assertEquals( String.valueOf(samplelong), stringlong.tojstring() ); - assertEquals( String.valueOf(sampledouble), stringdouble.tojstring() ); - assertEquals( "thread: ", thread.tojstring().substring(0,8) ); - assertEquals( "table: ", table.tojstring().substring(0,7) ); - assertEquals( sampleobject.toString(), userdataobj.tojstring() ); - assertEquals( sampledata.toString(), userdatacls.tojstring() ); - assertEquals( "function: ", somefunc.tojstring().substring(0,10) ); - assertEquals( "function: ", someclosure.tojstring().substring(0,10) ); - } - - public void testToUserdata() { - assertEquals( null, somenil.touserdata() ); - assertEquals( null, somefalse.touserdata() ); - assertEquals( null, sometrue.touserdata() ); - assertEquals( null, zero.touserdata() ); - assertEquals( null, intint.touserdata() ); - assertEquals( null, longdouble.touserdata() ); - assertEquals( null, doubledouble.touserdata() ); - assertEquals( null, stringstring.touserdata() ); - assertEquals( null, stringint.touserdata() ); - assertEquals( null, stringlong.touserdata() ); - assertEquals( null, stringdouble.touserdata() ); - assertEquals( null, thread.touserdata() ); - assertEquals( null, table.touserdata() ); - assertEquals( sampleobject, userdataobj.touserdata() ); - assertEquals( sampledata, userdatacls.touserdata() ); - assertEquals( null, somefunc.touserdata() ); - assertEquals( null, someclosure.touserdata() ); + assertEquals(false, somenil.isuserdata()); + assertEquals(false, sometrue.isuserdata()); + assertEquals(false, somefalse.isuserdata()); + assertEquals(false, intint.isuserdata()); + assertEquals(false, longdouble.isuserdata()); + assertEquals(false, doubledouble.isuserdata()); + assertEquals(false, stringstring.isuserdata()); + assertEquals(false, stringint.isuserdata()); + assertEquals(false, stringdouble.isuserdata()); + assertEquals(false, thread.isuserdata()); + assertEquals(false, table.isuserdata()); + assertEquals(true, userdataobj.isuserdata()); + assertEquals(true, userdatacls.isuserdata()); + assertEquals(false, somefunc.isuserdata()); + assertEquals(false, someclosure.isuserdata()); + } + + public void testIsUserdataObject() { + assertEquals(false, somenil.isuserdata(Object.class)); + assertEquals(false, sometrue.isuserdata(Object.class)); + assertEquals(false, somefalse.isuserdata(Object.class)); + assertEquals(false, longdouble.isuserdata(Object.class)); + assertEquals(false, doubledouble.isuserdata(Object.class)); + assertEquals(false, stringstring.isuserdata(Object.class)); + assertEquals(false, stringint.isuserdata(Object.class)); + assertEquals(false, stringdouble.isuserdata(Object.class)); + assertEquals(false, thread.isuserdata(Object.class)); + assertEquals(false, table.isuserdata(Object.class)); + assertEquals(true, userdataobj.isuserdata(Object.class)); + assertEquals(true, userdatacls.isuserdata(Object.class)); + assertEquals(false, somefunc.isuserdata(Object.class)); + assertEquals(false, someclosure.isuserdata(Object.class)); + } + + public void testIsUserdataMyData() { + assertEquals(false, somenil.isuserdata(MyData.class)); + assertEquals(false, sometrue.isuserdata(MyData.class)); + assertEquals(false, somefalse.isuserdata(MyData.class)); + assertEquals(false, longdouble.isuserdata(MyData.class)); + assertEquals(false, doubledouble.isuserdata(MyData.class)); + assertEquals(false, stringstring.isuserdata(MyData.class)); + assertEquals(false, stringint.isuserdata(MyData.class)); + assertEquals(false, stringdouble.isuserdata(MyData.class)); + assertEquals(false, thread.isuserdata(MyData.class)); + assertEquals(false, table.isuserdata(MyData.class)); + assertEquals(false, userdataobj.isuserdata(MyData.class)); + assertEquals(true, userdatacls.isuserdata(MyData.class)); + assertEquals(false, somefunc.isuserdata(MyData.class)); + assertEquals(false, someclosure.isuserdata(MyData.class)); + } + + // ===================== Coerce to Java ======================= + + public void testToBoolean() { + assertEquals(false, somenil.toboolean()); + assertEquals(true, sometrue.toboolean()); + assertEquals(false, somefalse.toboolean()); + assertEquals(true, zero.toboolean()); + assertEquals(true, intint.toboolean()); + assertEquals(true, longdouble.toboolean()); + assertEquals(true, doubledouble.toboolean()); + assertEquals(true, stringstring.toboolean()); + assertEquals(true, stringint.toboolean()); + assertEquals(true, stringlong.toboolean()); + assertEquals(true, stringdouble.toboolean()); + assertEquals(true, thread.toboolean()); + assertEquals(true, table.toboolean()); + assertEquals(true, userdataobj.toboolean()); + assertEquals(true, userdatacls.toboolean()); + assertEquals(true, somefunc.toboolean()); + assertEquals(true, someclosure.toboolean()); + } + + public void testToByte() { + assertEquals((byte) 0, somenil.tobyte()); + assertEquals((byte) 0, somefalse.tobyte()); + assertEquals((byte) 0, sometrue.tobyte()); + assertEquals((byte) 0, zero.tobyte()); + assertEquals((byte) sampleint, intint.tobyte()); + assertEquals((byte) samplelong, longdouble.tobyte()); + assertEquals((byte) sampledouble, doubledouble.tobyte()); + assertEquals((byte) 0, stringstring.tobyte()); + assertEquals((byte) sampleint, stringint.tobyte()); + assertEquals((byte) samplelong, stringlong.tobyte()); + assertEquals((byte) sampledouble, stringdouble.tobyte()); + assertEquals((byte) 0, thread.tobyte()); + assertEquals((byte) 0, table.tobyte()); + assertEquals((byte) 0, userdataobj.tobyte()); + assertEquals((byte) 0, userdatacls.tobyte()); + assertEquals((byte) 0, somefunc.tobyte()); + assertEquals((byte) 0, someclosure.tobyte()); + } + + public void testToChar() { + assertEquals((char) 0, somenil.tochar()); + assertEquals((char) 0, somefalse.tochar()); + assertEquals((char) 0, sometrue.tochar()); + assertEquals((char) 0, zero.tochar()); + assertEquals((int) (char) sampleint, (int) intint.tochar()); + assertEquals((int) (char) samplelong, (int) longdouble.tochar()); + assertEquals((int) (char) sampledouble, (int) doubledouble.tochar()); + assertEquals((char) 0, stringstring.tochar()); + assertEquals((int) (char) sampleint, (int) stringint.tochar()); + assertEquals((int) (char) samplelong, (int) stringlong.tochar()); + assertEquals((int) (char) sampledouble, (int) stringdouble.tochar()); + assertEquals((char) 0, thread.tochar()); + assertEquals((char) 0, table.tochar()); + assertEquals((char) 0, userdataobj.tochar()); + assertEquals((char) 0, userdatacls.tochar()); + assertEquals((char) 0, somefunc.tochar()); + assertEquals((char) 0, someclosure.tochar()); + } + + public void testToDouble() { + assertEquals(0., somenil.todouble()); + assertEquals(0., somefalse.todouble()); + assertEquals(0., sometrue.todouble()); + assertEquals(0., zero.todouble()); + assertEquals((double) sampleint, intint.todouble()); + assertEquals((double) samplelong, longdouble.todouble()); + assertEquals((double) sampledouble, doubledouble.todouble()); + assertEquals((double) 0, stringstring.todouble()); + assertEquals((double) sampleint, stringint.todouble()); + assertEquals((double) samplelong, stringlong.todouble()); + assertEquals((double) sampledouble, stringdouble.todouble()); + assertEquals(0., thread.todouble()); + assertEquals(0., table.todouble()); + assertEquals(0., userdataobj.todouble()); + assertEquals(0., userdatacls.todouble()); + assertEquals(0., somefunc.todouble()); + assertEquals(0., someclosure.todouble()); + } + + public void testToFloat() { + assertEquals(0.f, somenil.tofloat()); + assertEquals(0.f, somefalse.tofloat()); + assertEquals(0.f, sometrue.tofloat()); + assertEquals(0.f, zero.tofloat()); + assertEquals((float) sampleint, intint.tofloat()); + assertEquals((float) samplelong, longdouble.tofloat()); + assertEquals((float) sampledouble, doubledouble.tofloat()); + assertEquals((float) 0, stringstring.tofloat()); + assertEquals((float) sampleint, stringint.tofloat()); + assertEquals((float) samplelong, stringlong.tofloat()); + assertEquals((float) sampledouble, stringdouble.tofloat()); + assertEquals(0.f, thread.tofloat()); + assertEquals(0.f, table.tofloat()); + assertEquals(0.f, userdataobj.tofloat()); + assertEquals(0.f, userdatacls.tofloat()); + assertEquals(0.f, somefunc.tofloat()); + assertEquals(0.f, someclosure.tofloat()); + } + + public void testToInt() { + assertEquals(0, somenil.toint()); + assertEquals(0, somefalse.toint()); + assertEquals(0, sometrue.toint()); + assertEquals(0, zero.toint()); + assertEquals((int) sampleint, intint.toint()); + assertEquals((int) samplelong, longdouble.toint()); + assertEquals((int) sampledouble, doubledouble.toint()); + assertEquals((int) 0, stringstring.toint()); + assertEquals((int) sampleint, stringint.toint()); + assertEquals((int) samplelong, stringlong.toint()); + assertEquals((int) sampledouble, stringdouble.toint()); + assertEquals(0, thread.toint()); + assertEquals(0, table.toint()); + assertEquals(0, userdataobj.toint()); + assertEquals(0, userdatacls.toint()); + assertEquals(0, somefunc.toint()); + assertEquals(0, someclosure.toint()); + } + + public void testToLong() { + assertEquals(0L, somenil.tolong()); + assertEquals(0L, somefalse.tolong()); + assertEquals(0L, sometrue.tolong()); + assertEquals(0L, zero.tolong()); + assertEquals((long) sampleint, intint.tolong()); + assertEquals((long) samplelong, longdouble.tolong()); + assertEquals((long) sampledouble, doubledouble.tolong()); + assertEquals((long) 0, stringstring.tolong()); + assertEquals((long) sampleint, stringint.tolong()); + assertEquals((long) samplelong, stringlong.tolong()); + assertEquals((long) sampledouble, stringdouble.tolong()); + assertEquals(0L, thread.tolong()); + assertEquals(0L, table.tolong()); + assertEquals(0L, userdataobj.tolong()); + assertEquals(0L, userdatacls.tolong()); + assertEquals(0L, somefunc.tolong()); + assertEquals(0L, someclosure.tolong()); + } + + public void testToShort() { + assertEquals((short) 0, somenil.toshort()); + assertEquals((short) 0, somefalse.toshort()); + assertEquals((short) 0, sometrue.toshort()); + assertEquals((short) 0, zero.toshort()); + assertEquals((short) sampleint, intint.toshort()); + assertEquals((short) samplelong, longdouble.toshort()); + assertEquals((short) sampledouble, doubledouble.toshort()); + assertEquals((short) 0, stringstring.toshort()); + assertEquals((short) sampleint, stringint.toshort()); + assertEquals((short) samplelong, stringlong.toshort()); + assertEquals((short) sampledouble, stringdouble.toshort()); + assertEquals((short) 0, thread.toshort()); + assertEquals((short) 0, table.toshort()); + assertEquals((short) 0, userdataobj.toshort()); + assertEquals((short) 0, userdatacls.toshort()); + assertEquals((short) 0, somefunc.toshort()); + assertEquals((short) 0, someclosure.toshort()); + } + + public void testToString() { + assertEquals("nil", somenil.tojstring()); + assertEquals("false", somefalse.tojstring()); + assertEquals("true", sometrue.tojstring()); + assertEquals("0", zero.tojstring()); + assertEquals(String.valueOf(sampleint), intint.tojstring()); + assertEquals(String.valueOf(samplelong), longdouble.tojstring()); + assertEquals(String.valueOf(sampledouble), doubledouble.tojstring()); + assertEquals(samplestringstring, stringstring.tojstring()); + assertEquals(String.valueOf(sampleint), stringint.tojstring()); + assertEquals(String.valueOf(samplelong), stringlong.tojstring()); + assertEquals(String.valueOf(sampledouble), stringdouble.tojstring()); + assertEquals("thread: ", thread.tojstring().substring(0, 8)); + assertEquals("table: ", table.tojstring().substring(0, 7)); + assertEquals(sampleobject.toString(), userdataobj.tojstring()); + assertEquals(sampledata.toString(), userdatacls.tojstring()); + assertEquals("function: ", somefunc.tojstring().substring(0, 10)); + assertEquals("function: ", someclosure.tojstring().substring(0, 10)); + } + + public void testToUserdata() { + assertEquals(null, somenil.touserdata()); + assertEquals(null, somefalse.touserdata()); + assertEquals(null, sometrue.touserdata()); + assertEquals(null, zero.touserdata()); + assertEquals(null, intint.touserdata()); + assertEquals(null, longdouble.touserdata()); + assertEquals(null, doubledouble.touserdata()); + assertEquals(null, stringstring.touserdata()); + assertEquals(null, stringint.touserdata()); + assertEquals(null, stringlong.touserdata()); + assertEquals(null, stringdouble.touserdata()); + assertEquals(null, thread.touserdata()); + assertEquals(null, table.touserdata()); + assertEquals(sampleobject, userdataobj.touserdata()); + assertEquals(sampledata, userdatacls.touserdata()); + assertEquals(null, somefunc.touserdata()); + assertEquals(null, someclosure.touserdata()); } - - // ===================== Optional argument conversion ======================= - - private void throwsError(LuaValue obj, String method, Class argtype, Object argument ) { + private void throwsError(LuaValue obj, String method, Class argtype, Object argument) { try { - obj.getClass().getMethod(method,argtype).invoke(obj, argument ); + obj.getClass().getMethod(method, argtype).invoke(obj, argument); } catch (InvocationTargetException e) { - if ( ! (e.getTargetException() instanceof LuaError) ) - fail("not a LuaError: "+e.getTargetException()); + if (!(e.getTargetException() instanceof LuaError)) + fail("not a LuaError: " + e.getTargetException()); return; // pass - } catch ( Exception e ) { - fail( "bad exception: "+e ); + } catch (Exception e) { + fail("bad exception: " + e); } fail("failed to throw LuaError as required"); } public void testOptBoolean() { - assertEquals( true, somenil.optboolean(true) ); - assertEquals( false, somenil.optboolean(false) ); - assertEquals( true, sometrue.optboolean(false) ); - assertEquals( false, somefalse.optboolean(true) ); - throwsError( zero, "optboolean", boolean.class, Boolean.FALSE ); - throwsError( intint, "optboolean", boolean.class, Boolean.FALSE ); - throwsError( longdouble, "optboolean", boolean.class, Boolean.FALSE ); - throwsError( doubledouble, "optboolean", boolean.class, Boolean.FALSE ); - throwsError( somefunc, "optboolean", boolean.class, Boolean.FALSE ); - throwsError( someclosure, "optboolean", boolean.class, Boolean.FALSE ); - throwsError( stringstring, "optboolean", boolean.class, Boolean.FALSE ); - throwsError( stringint, "optboolean", boolean.class, Boolean.FALSE ); - throwsError( stringlong, "optboolean", boolean.class, Boolean.FALSE ); - throwsError( stringdouble, "optboolean", boolean.class, Boolean.FALSE ); - throwsError( thread, "optboolean", boolean.class, Boolean.FALSE ); - throwsError( table, "optboolean", boolean.class, Boolean.FALSE ); - throwsError( userdataobj, "optboolean", boolean.class, Boolean.FALSE ); - throwsError( userdatacls, "optboolean", boolean.class, Boolean.FALSE ); + assertEquals(true, somenil.optboolean(true)); + assertEquals(false, somenil.optboolean(false)); + assertEquals(true, sometrue.optboolean(false)); + assertEquals(false, somefalse.optboolean(true)); + throwsError(zero, "optboolean", boolean.class, Boolean.FALSE); + throwsError(intint, "optboolean", boolean.class, Boolean.FALSE); + throwsError(longdouble, "optboolean", boolean.class, Boolean.FALSE); + throwsError(doubledouble, "optboolean", boolean.class, Boolean.FALSE); + throwsError(somefunc, "optboolean", boolean.class, Boolean.FALSE); + throwsError(someclosure, "optboolean", boolean.class, Boolean.FALSE); + throwsError(stringstring, "optboolean", boolean.class, Boolean.FALSE); + throwsError(stringint, "optboolean", boolean.class, Boolean.FALSE); + throwsError(stringlong, "optboolean", boolean.class, Boolean.FALSE); + throwsError(stringdouble, "optboolean", boolean.class, Boolean.FALSE); + throwsError(thread, "optboolean", boolean.class, Boolean.FALSE); + throwsError(table, "optboolean", boolean.class, Boolean.FALSE); + throwsError(userdataobj, "optboolean", boolean.class, Boolean.FALSE); + throwsError(userdatacls, "optboolean", boolean.class, Boolean.FALSE); } public void testOptClosure() { - assertEquals( someclosure, somenil.optclosure(someclosure) ); - assertEquals( null, somenil.optclosure(null) ); - throwsError( sometrue, "optclosure", LuaClosure.class, someclosure ); - throwsError( somefalse, "optclosure", LuaClosure.class, someclosure ); - throwsError( zero, "optclosure", LuaClosure.class, someclosure ); - throwsError( intint, "optclosure", LuaClosure.class, someclosure ); - throwsError( longdouble, "optclosure", LuaClosure.class, someclosure ); - throwsError( doubledouble, "optclosure", LuaClosure.class, someclosure ); - throwsError( somefunc, "optclosure", LuaClosure.class, someclosure ); - assertEquals( someclosure, someclosure.optclosure(someclosure) ); - assertEquals( someclosure, someclosure.optclosure(null) ); - throwsError( stringstring, "optclosure", LuaClosure.class, someclosure ); - throwsError( stringint, "optclosure", LuaClosure.class, someclosure ); - throwsError( stringlong, "optclosure", LuaClosure.class, someclosure ); - throwsError( stringdouble, "optclosure", LuaClosure.class, someclosure ); - throwsError( thread, "optclosure", LuaClosure.class, someclosure ); - throwsError( table, "optclosure", LuaClosure.class, someclosure ); - throwsError( userdataobj, "optclosure", LuaClosure.class, someclosure ); - throwsError( userdatacls, "optclosure", LuaClosure.class, someclosure ); + assertEquals(someclosure, somenil.optclosure(someclosure)); + assertEquals(null, somenil.optclosure(null)); + throwsError(sometrue, "optclosure", LuaClosure.class, someclosure); + throwsError(somefalse, "optclosure", LuaClosure.class, someclosure); + throwsError(zero, "optclosure", LuaClosure.class, someclosure); + throwsError(intint, "optclosure", LuaClosure.class, someclosure); + throwsError(longdouble, "optclosure", LuaClosure.class, someclosure); + throwsError(doubledouble, "optclosure", LuaClosure.class, someclosure); + throwsError(somefunc, "optclosure", LuaClosure.class, someclosure); + assertEquals(someclosure, someclosure.optclosure(someclosure)); + assertEquals(someclosure, someclosure.optclosure(null)); + throwsError(stringstring, "optclosure", LuaClosure.class, someclosure); + throwsError(stringint, "optclosure", LuaClosure.class, someclosure); + throwsError(stringlong, "optclosure", LuaClosure.class, someclosure); + throwsError(stringdouble, "optclosure", LuaClosure.class, someclosure); + throwsError(thread, "optclosure", LuaClosure.class, someclosure); + throwsError(table, "optclosure", LuaClosure.class, someclosure); + throwsError(userdataobj, "optclosure", LuaClosure.class, someclosure); + throwsError(userdatacls, "optclosure", LuaClosure.class, someclosure); } public void testOptDouble() { - assertEquals( 33., somenil.optdouble(33.) ); - throwsError( sometrue, "optdouble", double.class, 33. ); - throwsError( somefalse, "optdouble", double.class, 33. ); - assertEquals( 0., zero.optdouble(33.) ); - assertEquals( (double) sampleint, intint.optdouble(33.) ); - assertEquals( (double) samplelong, longdouble.optdouble(33.) ); - assertEquals( sampledouble, doubledouble.optdouble(33.) ); - throwsError( somefunc, "optdouble", double.class, 33. ); - throwsError( someclosure, "optdouble", double.class, 33. ); - throwsError( stringstring, "optdouble", double.class, 33. ); - assertEquals( (double) sampleint, stringint.optdouble(33.) ); - assertEquals( (double) samplelong, stringlong.optdouble(33.) ); - assertEquals( sampledouble, stringdouble.optdouble(33.) ); - throwsError( thread, "optdouble", double.class, 33. ); - throwsError( table, "optdouble", double.class, 33. ); - throwsError( userdataobj, "optdouble", double.class, 33. ); - throwsError( userdatacls, "optdouble", double.class, 33. ); + assertEquals(33., somenil.optdouble(33.)); + throwsError(sometrue, "optdouble", double.class, 33.); + throwsError(somefalse, "optdouble", double.class, 33.); + assertEquals(0., zero.optdouble(33.)); + assertEquals((double) sampleint, intint.optdouble(33.)); + assertEquals((double) samplelong, longdouble.optdouble(33.)); + assertEquals(sampledouble, doubledouble.optdouble(33.)); + throwsError(somefunc, "optdouble", double.class, 33.); + throwsError(someclosure, "optdouble", double.class, 33.); + throwsError(stringstring, "optdouble", double.class, 33.); + assertEquals((double) sampleint, stringint.optdouble(33.)); + assertEquals((double) samplelong, stringlong.optdouble(33.)); + assertEquals(sampledouble, stringdouble.optdouble(33.)); + throwsError(thread, "optdouble", double.class, 33.); + throwsError(table, "optdouble", double.class, 33.); + throwsError(userdataobj, "optdouble", double.class, 33.); + throwsError(userdatacls, "optdouble", double.class, 33.); } public void testOptFunction() { - assertEquals( somefunc, somenil.optfunction(somefunc) ); - assertEquals( null, somenil.optfunction(null) ); - throwsError( sometrue, "optfunction", LuaFunction.class, somefunc ); - throwsError( somefalse, "optfunction", LuaFunction.class, somefunc ); - throwsError( zero, "optfunction", LuaFunction.class, somefunc ); - throwsError( intint, "optfunction", LuaFunction.class, somefunc ); - throwsError( longdouble, "optfunction", LuaFunction.class, somefunc ); - throwsError( doubledouble, "optfunction", LuaFunction.class, somefunc ); - assertEquals( somefunc, somefunc.optfunction(null) ); - assertEquals( someclosure, someclosure.optfunction(null) ); - assertEquals( somefunc, somefunc.optfunction(somefunc) ); - assertEquals( someclosure, someclosure.optfunction(somefunc) ); - throwsError( stringstring, "optfunction", LuaFunction.class, somefunc ); - throwsError( stringint, "optfunction", LuaFunction.class, somefunc ); - throwsError( stringlong, "optfunction", LuaFunction.class, somefunc ); - throwsError( stringdouble, "optfunction", LuaFunction.class, somefunc ); - throwsError( thread, "optfunction", LuaFunction.class, somefunc ); - throwsError( table, "optfunction", LuaFunction.class, somefunc ); - throwsError( userdataobj, "optfunction", LuaFunction.class, somefunc ); - throwsError( userdatacls, "optfunction", LuaFunction.class, somefunc ); + assertEquals(somefunc, somenil.optfunction(somefunc)); + assertEquals(null, somenil.optfunction(null)); + throwsError(sometrue, "optfunction", LuaFunction.class, somefunc); + throwsError(somefalse, "optfunction", LuaFunction.class, somefunc); + throwsError(zero, "optfunction", LuaFunction.class, somefunc); + throwsError(intint, "optfunction", LuaFunction.class, somefunc); + throwsError(longdouble, "optfunction", LuaFunction.class, somefunc); + throwsError(doubledouble, "optfunction", LuaFunction.class, somefunc); + assertEquals(somefunc, somefunc.optfunction(null)); + assertEquals(someclosure, someclosure.optfunction(null)); + assertEquals(somefunc, somefunc.optfunction(somefunc)); + assertEquals(someclosure, someclosure.optfunction(somefunc)); + throwsError(stringstring, "optfunction", LuaFunction.class, somefunc); + throwsError(stringint, "optfunction", LuaFunction.class, somefunc); + throwsError(stringlong, "optfunction", LuaFunction.class, somefunc); + throwsError(stringdouble, "optfunction", LuaFunction.class, somefunc); + throwsError(thread, "optfunction", LuaFunction.class, somefunc); + throwsError(table, "optfunction", LuaFunction.class, somefunc); + throwsError(userdataobj, "optfunction", LuaFunction.class, somefunc); + throwsError(userdatacls, "optfunction", LuaFunction.class, somefunc); } public void testOptInt() { - assertEquals( 33, somenil.optint(33) ); - throwsError( sometrue, "optint", int.class, new Integer(33) ); - throwsError( somefalse, "optint", int.class, new Integer(33) ); - assertEquals( 0, zero.optint(33) ); - assertEquals( sampleint, intint.optint(33) ); - assertEquals( (int) samplelong, longdouble.optint(33) ); - assertEquals( (int) sampledouble, doubledouble.optint(33) ); - throwsError( somefunc, "optint", int.class, new Integer(33) ); - throwsError( someclosure, "optint", int.class, new Integer(33) ); - throwsError( stringstring, "optint", int.class, new Integer(33) ); - assertEquals( sampleint, stringint.optint(33) ); - assertEquals( (int) samplelong, stringlong.optint(33) ); - assertEquals( (int) sampledouble, stringdouble.optint(33) ); - throwsError( thread, "optint", int.class, new Integer(33) ); - throwsError( table, "optint", int.class, new Integer(33) ); - throwsError( userdataobj, "optint", int.class, new Integer(33) ); - throwsError( userdatacls, "optint", int.class, new Integer(33) ); + assertEquals(33, somenil.optint(33)); + throwsError(sometrue, "optint", int.class, new Integer(33)); + throwsError(somefalse, "optint", int.class, new Integer(33)); + assertEquals(0, zero.optint(33)); + assertEquals(sampleint, intint.optint(33)); + assertEquals((int) samplelong, longdouble.optint(33)); + assertEquals((int) sampledouble, doubledouble.optint(33)); + throwsError(somefunc, "optint", int.class, new Integer(33)); + throwsError(someclosure, "optint", int.class, new Integer(33)); + throwsError(stringstring, "optint", int.class, new Integer(33)); + assertEquals(sampleint, stringint.optint(33)); + assertEquals((int) samplelong, stringlong.optint(33)); + assertEquals((int) sampledouble, stringdouble.optint(33)); + throwsError(thread, "optint", int.class, new Integer(33)); + throwsError(table, "optint", int.class, new Integer(33)); + throwsError(userdataobj, "optint", int.class, new Integer(33)); + throwsError(userdatacls, "optint", int.class, new Integer(33)); } - + public void testOptInteger() { - assertEquals( LuaValue.valueOf(33), somenil.optinteger(LuaValue.valueOf(33)) ); - throwsError( sometrue, "optinteger", LuaInteger.class, LuaValue.valueOf(33) ); - throwsError( somefalse, "optinteger", LuaInteger.class, LuaValue.valueOf(33) ); - assertEquals( zero, zero.optinteger(LuaValue.valueOf(33)) ); - assertEquals( LuaValue.valueOf( sampleint ), intint.optinteger(LuaValue.valueOf(33)) ); - assertEquals( LuaValue.valueOf( (int) samplelong ), longdouble.optinteger(LuaValue.valueOf(33)) ); - assertEquals( LuaValue.valueOf( (int) sampledouble ), doubledouble.optinteger(LuaValue.valueOf(33)) ); - throwsError( somefunc, "optinteger", LuaInteger.class, LuaValue.valueOf(33) ); - throwsError( someclosure, "optinteger", LuaInteger.class, LuaValue.valueOf(33) ); - throwsError( stringstring, "optinteger", LuaInteger.class, LuaValue.valueOf(33) ); - assertEquals( LuaValue.valueOf( sampleint), stringint.optinteger(LuaValue.valueOf(33)) ); - assertEquals( LuaValue.valueOf( (int) samplelong), stringlong.optinteger(LuaValue.valueOf(33)) ); - assertEquals( LuaValue.valueOf( (int) sampledouble), stringdouble.optinteger(LuaValue.valueOf(33)) ); - throwsError( thread, "optinteger", LuaInteger.class, LuaValue.valueOf(33) ); - throwsError( table, "optinteger", LuaInteger.class, LuaValue.valueOf(33) ); - throwsError( userdataobj, "optinteger", LuaInteger.class, LuaValue.valueOf(33) ); - throwsError( userdatacls, "optinteger", LuaInteger.class, LuaValue.valueOf(33) ); + assertEquals(LuaValue.valueOf(33), somenil.optinteger(LuaValue.valueOf(33))); + throwsError(sometrue, "optinteger", LuaInteger.class, LuaValue.valueOf(33)); + throwsError(somefalse, "optinteger", LuaInteger.class, LuaValue.valueOf(33)); + assertEquals(zero, zero.optinteger(LuaValue.valueOf(33))); + assertEquals(LuaValue.valueOf(sampleint), intint.optinteger(LuaValue.valueOf(33))); + assertEquals(LuaValue.valueOf((int) samplelong), longdouble.optinteger(LuaValue.valueOf(33))); + assertEquals(LuaValue.valueOf((int) sampledouble), doubledouble.optinteger(LuaValue.valueOf(33))); + throwsError(somefunc, "optinteger", LuaInteger.class, LuaValue.valueOf(33)); + throwsError(someclosure, "optinteger", LuaInteger.class, LuaValue.valueOf(33)); + throwsError(stringstring, "optinteger", LuaInteger.class, LuaValue.valueOf(33)); + assertEquals(LuaValue.valueOf(sampleint), stringint.optinteger(LuaValue.valueOf(33))); + assertEquals(LuaValue.valueOf((int) samplelong), stringlong.optinteger(LuaValue.valueOf(33))); + assertEquals(LuaValue.valueOf((int) sampledouble), stringdouble.optinteger(LuaValue.valueOf(33))); + throwsError(thread, "optinteger", LuaInteger.class, LuaValue.valueOf(33)); + throwsError(table, "optinteger", LuaInteger.class, LuaValue.valueOf(33)); + throwsError(userdataobj, "optinteger", LuaInteger.class, LuaValue.valueOf(33)); + throwsError(userdatacls, "optinteger", LuaInteger.class, LuaValue.valueOf(33)); } public void testOptLong() { - assertEquals( 33L, somenil.optlong(33) ); - throwsError( sometrue, "optlong", long.class, new Long(33) ); - throwsError( somefalse, "optlong", long.class, new Long(33) ); - assertEquals( 0L, zero.optlong(33) ); - assertEquals( sampleint, intint.optlong(33) ); - assertEquals( (long) samplelong, longdouble.optlong(33) ); - assertEquals( (long) sampledouble, doubledouble.optlong(33) ); - throwsError( somefunc, "optlong", long.class, new Long(33) ); - throwsError( someclosure, "optlong", long.class, new Long(33) ); - throwsError( stringstring, "optlong", long.class, new Long(33) ); - assertEquals( sampleint, stringint.optlong(33) ); - assertEquals( (long) samplelong, stringlong.optlong(33) ); - assertEquals( (long) sampledouble, stringdouble.optlong(33) ); - throwsError( thread, "optlong", long.class, new Long(33) ); - throwsError( table, "optlong", long.class, new Long(33) ); - throwsError( userdataobj, "optlong", long.class, new Long(33) ); - throwsError( userdatacls, "optlong", long.class, new Long(33) ); - } - - public void testOptNumber() { - assertEquals( LuaValue.valueOf(33), somenil.optnumber(LuaValue.valueOf(33)) ); - throwsError( sometrue, "optnumber", LuaNumber.class, LuaValue.valueOf(33) ); - throwsError( somefalse, "optnumber", LuaNumber.class, LuaValue.valueOf(33) ); - assertEquals( zero, zero.optnumber(LuaValue.valueOf(33)) ); - assertEquals( LuaValue.valueOf( sampleint ), intint.optnumber(LuaValue.valueOf(33)) ); - assertEquals( LuaValue.valueOf( samplelong ), longdouble.optnumber(LuaValue.valueOf(33)) ); - assertEquals( LuaValue.valueOf( sampledouble ), doubledouble.optnumber(LuaValue.valueOf(33)) ); - throwsError( somefunc, "optnumber", LuaNumber.class, LuaValue.valueOf(33) ); - throwsError( someclosure, "optnumber", LuaNumber.class, LuaValue.valueOf(33) ); - throwsError( stringstring, "optnumber", LuaNumber.class, LuaValue.valueOf(33) ); - assertEquals( LuaValue.valueOf( sampleint), stringint.optnumber(LuaValue.valueOf(33)) ); - assertEquals( LuaValue.valueOf( samplelong), stringlong.optnumber(LuaValue.valueOf(33)) ); - assertEquals( LuaValue.valueOf( sampledouble), stringdouble.optnumber(LuaValue.valueOf(33)) ); - throwsError( thread, "optnumber", LuaNumber.class, LuaValue.valueOf(33) ); - throwsError( table, "optnumber", LuaNumber.class, LuaValue.valueOf(33) ); - throwsError( userdataobj, "optnumber", LuaNumber.class, LuaValue.valueOf(33) ); - throwsError( userdatacls, "optnumber", LuaNumber.class, LuaValue.valueOf(33) ); - } - - public void testOptTable() { - assertEquals( table, somenil.opttable(table) ); - assertEquals( null, somenil.opttable(null) ); - throwsError( sometrue, "opttable", LuaTable.class, table ); - throwsError( somefalse, "opttable", LuaTable.class, table ); - throwsError( zero, "opttable", LuaTable.class, table ); - throwsError( intint, "opttable", LuaTable.class, table ); - throwsError( longdouble, "opttable", LuaTable.class, table ); - throwsError( doubledouble, "opttable", LuaTable.class, table ); - throwsError( somefunc, "opttable", LuaTable.class, table ); - throwsError( someclosure, "opttable", LuaTable.class, table ); - throwsError( stringstring, "opttable", LuaTable.class, table ); - throwsError( stringint, "opttable", LuaTable.class, table ); - throwsError( stringlong, "opttable", LuaTable.class, table ); - throwsError( stringdouble, "opttable", LuaTable.class, table ); - throwsError( thread, "opttable", LuaTable.class, table ); - assertEquals( table, table.opttable(table) ); - assertEquals( table, table.opttable(null) ); - throwsError( userdataobj, "opttable", LuaTable.class, table ); - throwsError( userdatacls, "opttable", LuaTable.class, table ); - } - - public void testOptThread() { - assertEquals( thread, somenil.optthread(thread) ); - assertEquals( null, somenil.optthread(null) ); - throwsError( sometrue, "optthread", LuaThread.class, thread ); - throwsError( somefalse, "optthread", LuaThread.class, thread ); - throwsError( zero, "optthread", LuaThread.class, thread ); - throwsError( intint, "optthread", LuaThread.class, thread ); - throwsError( longdouble, "optthread", LuaThread.class, thread ); - throwsError( doubledouble, "optthread", LuaThread.class, thread ); - throwsError( somefunc, "optthread", LuaThread.class, thread ); - throwsError( someclosure, "optthread", LuaThread.class, thread ); - throwsError( stringstring, "optthread", LuaThread.class, thread ); - throwsError( stringint, "optthread", LuaThread.class, thread ); - throwsError( stringlong, "optthread", LuaThread.class, thread ); - throwsError( stringdouble, "optthread", LuaThread.class, thread ); - throwsError( table, "optthread", LuaThread.class, thread ); - assertEquals( thread, thread.optthread(thread) ); - assertEquals( thread, thread.optthread(null) ); - throwsError( userdataobj, "optthread", LuaThread.class, thread ); - throwsError( userdatacls, "optthread", LuaThread.class, thread ); - } - - public void testOptJavaString() { - assertEquals( "xyz", somenil.optjstring("xyz") ); - assertEquals( null, somenil.optjstring(null) ); - throwsError( sometrue, "optjstring", String.class, "xyz" ); - throwsError( somefalse, "optjstring", String.class, "xyz" ); - assertEquals( String.valueOf(zero), zero.optjstring("xyz") ); - assertEquals( String.valueOf(intint), intint.optjstring("xyz") ); - assertEquals( String.valueOf(longdouble), longdouble.optjstring("xyz") ); - assertEquals( String.valueOf(doubledouble), doubledouble.optjstring("xyz") ); - throwsError( somefunc, "optjstring", String.class, "xyz" ); - throwsError( someclosure, "optjstring", String.class, "xyz" ); - assertEquals( samplestringstring, stringstring.optjstring("xyz") ); - assertEquals( samplestringint, stringint.optjstring("xyz") ); - assertEquals( samplestringlong, stringlong.optjstring("xyz") ); - assertEquals( samplestringdouble, stringdouble.optjstring("xyz") ); - throwsError( thread, "optjstring", String.class, "xyz" ); - throwsError( table, "optjstring", String.class, "xyz" ); - throwsError( userdataobj, "optjstring", String.class, "xyz" ); - throwsError( userdatacls, "optjstring", String.class, "xyz" ); - } - - public void testOptLuaString() { - assertEquals( LuaValue.valueOf("xyz"), somenil.optstring(LuaValue.valueOf("xyz")) ); - assertEquals( null, somenil.optstring(null) ); - throwsError( sometrue, "optstring", LuaString.class, LuaValue.valueOf("xyz") ); - throwsError( somefalse, "optstring", LuaString.class, LuaValue.valueOf("xyz") ); - assertEquals( LuaValue.valueOf("0"), zero.optstring(LuaValue.valueOf("xyz")) ); - assertEquals( stringint, intint.optstring(LuaValue.valueOf("xyz")) ); - assertEquals( stringlong, longdouble.optstring(LuaValue.valueOf("xyz")) ); - assertEquals( stringdouble, doubledouble.optstring(LuaValue.valueOf("xyz")) ); - throwsError( somefunc, "optstring", LuaString.class, LuaValue.valueOf("xyz") ); - throwsError( someclosure, "optstring", LuaString.class, LuaValue.valueOf("xyz") ); - assertEquals( stringstring, stringstring.optstring(LuaValue.valueOf("xyz")) ); - assertEquals( stringint, stringint.optstring(LuaValue.valueOf("xyz")) ); - assertEquals( stringlong, stringlong.optstring(LuaValue.valueOf("xyz")) ); - assertEquals( stringdouble, stringdouble.optstring(LuaValue.valueOf("xyz")) ); - throwsError( thread, "optstring", LuaString.class, LuaValue.valueOf("xyz") ); - throwsError( table, "optstring", LuaString.class, LuaValue.valueOf("xyz") ); - throwsError( userdataobj, "optstring", LuaString.class, LuaValue.valueOf("xyz") ); - throwsError( userdatacls, "optstring", LuaString.class, LuaValue.valueOf("xyz") ); - } - - public void testOptUserdata() { - assertEquals( sampleobject, somenil.optuserdata(sampleobject) ); - assertEquals( sampledata, somenil.optuserdata(sampledata) ); - assertEquals( null, somenil.optuserdata(null) ); - throwsError( sometrue, "optuserdata", Object.class, sampledata ); - throwsError( somefalse, "optuserdata", Object.class, sampledata ); - throwsError( zero, "optuserdata", Object.class, sampledata ); - throwsError( intint, "optuserdata", Object.class, sampledata ); - throwsError( longdouble, "optuserdata", Object.class, sampledata ); - throwsError( doubledouble, "optuserdata", Object.class, sampledata ); - throwsError( somefunc, "optuserdata", Object.class, sampledata ); - throwsError( someclosure, "optuserdata", Object.class, sampledata ); - throwsError( stringstring, "optuserdata", Object.class, sampledata ); - throwsError( stringint, "optuserdata", Object.class, sampledata ); - throwsError( stringlong, "optuserdata", Object.class, sampledata ); - throwsError( stringdouble, "optuserdata", Object.class, sampledata ); - throwsError( table, "optuserdata", Object.class, sampledata ); - assertEquals( sampleobject, userdataobj.optuserdata(sampledata) ); - assertEquals( sampleobject, userdataobj.optuserdata(null) ); - assertEquals( sampledata, userdatacls.optuserdata(sampleobject) ); - assertEquals( sampledata, userdatacls.optuserdata(null) ); + assertEquals(33L, somenil.optlong(33)); + throwsError(sometrue, "optlong", long.class, new Long(33)); + throwsError(somefalse, "optlong", long.class, new Long(33)); + assertEquals(0L, zero.optlong(33)); + assertEquals(sampleint, intint.optlong(33)); + assertEquals((long) samplelong, longdouble.optlong(33)); + assertEquals((long) sampledouble, doubledouble.optlong(33)); + throwsError(somefunc, "optlong", long.class, new Long(33)); + throwsError(someclosure, "optlong", long.class, new Long(33)); + throwsError(stringstring, "optlong", long.class, new Long(33)); + assertEquals(sampleint, stringint.optlong(33)); + assertEquals((long) samplelong, stringlong.optlong(33)); + assertEquals((long) sampledouble, stringdouble.optlong(33)); + throwsError(thread, "optlong", long.class, new Long(33)); + throwsError(table, "optlong", long.class, new Long(33)); + throwsError(userdataobj, "optlong", long.class, new Long(33)); + throwsError(userdatacls, "optlong", long.class, new Long(33)); } - private void throwsErrorOptUserdataClass(LuaValue obj, Class arg1, Object arg2 ) { + public void testOptNumber() { + assertEquals(LuaValue.valueOf(33), somenil.optnumber(LuaValue.valueOf(33))); + throwsError(sometrue, "optnumber", LuaNumber.class, LuaValue.valueOf(33)); + throwsError(somefalse, "optnumber", LuaNumber.class, LuaValue.valueOf(33)); + assertEquals(zero, zero.optnumber(LuaValue.valueOf(33))); + assertEquals(LuaValue.valueOf(sampleint), intint.optnumber(LuaValue.valueOf(33))); + assertEquals(LuaValue.valueOf(samplelong), longdouble.optnumber(LuaValue.valueOf(33))); + assertEquals(LuaValue.valueOf(sampledouble), doubledouble.optnumber(LuaValue.valueOf(33))); + throwsError(somefunc, "optnumber", LuaNumber.class, LuaValue.valueOf(33)); + throwsError(someclosure, "optnumber", LuaNumber.class, LuaValue.valueOf(33)); + throwsError(stringstring, "optnumber", LuaNumber.class, LuaValue.valueOf(33)); + assertEquals(LuaValue.valueOf(sampleint), stringint.optnumber(LuaValue.valueOf(33))); + assertEquals(LuaValue.valueOf(samplelong), stringlong.optnumber(LuaValue.valueOf(33))); + assertEquals(LuaValue.valueOf(sampledouble), stringdouble.optnumber(LuaValue.valueOf(33))); + throwsError(thread, "optnumber", LuaNumber.class, LuaValue.valueOf(33)); + throwsError(table, "optnumber", LuaNumber.class, LuaValue.valueOf(33)); + throwsError(userdataobj, "optnumber", LuaNumber.class, LuaValue.valueOf(33)); + throwsError(userdatacls, "optnumber", LuaNumber.class, LuaValue.valueOf(33)); + } + + public void testOptTable() { + assertEquals(table, somenil.opttable(table)); + assertEquals(null, somenil.opttable(null)); + throwsError(sometrue, "opttable", LuaTable.class, table); + throwsError(somefalse, "opttable", LuaTable.class, table); + throwsError(zero, "opttable", LuaTable.class, table); + throwsError(intint, "opttable", LuaTable.class, table); + throwsError(longdouble, "opttable", LuaTable.class, table); + throwsError(doubledouble, "opttable", LuaTable.class, table); + throwsError(somefunc, "opttable", LuaTable.class, table); + throwsError(someclosure, "opttable", LuaTable.class, table); + throwsError(stringstring, "opttable", LuaTable.class, table); + throwsError(stringint, "opttable", LuaTable.class, table); + throwsError(stringlong, "opttable", LuaTable.class, table); + throwsError(stringdouble, "opttable", LuaTable.class, table); + throwsError(thread, "opttable", LuaTable.class, table); + assertEquals(table, table.opttable(table)); + assertEquals(table, table.opttable(null)); + throwsError(userdataobj, "opttable", LuaTable.class, table); + throwsError(userdatacls, "opttable", LuaTable.class, table); + } + + public void testOptThread() { + assertEquals(thread, somenil.optthread(thread)); + assertEquals(null, somenil.optthread(null)); + throwsError(sometrue, "optthread", LuaThread.class, thread); + throwsError(somefalse, "optthread", LuaThread.class, thread); + throwsError(zero, "optthread", LuaThread.class, thread); + throwsError(intint, "optthread", LuaThread.class, thread); + throwsError(longdouble, "optthread", LuaThread.class, thread); + throwsError(doubledouble, "optthread", LuaThread.class, thread); + throwsError(somefunc, "optthread", LuaThread.class, thread); + throwsError(someclosure, "optthread", LuaThread.class, thread); + throwsError(stringstring, "optthread", LuaThread.class, thread); + throwsError(stringint, "optthread", LuaThread.class, thread); + throwsError(stringlong, "optthread", LuaThread.class, thread); + throwsError(stringdouble, "optthread", LuaThread.class, thread); + throwsError(table, "optthread", LuaThread.class, thread); + assertEquals(thread, thread.optthread(thread)); + assertEquals(thread, thread.optthread(null)); + throwsError(userdataobj, "optthread", LuaThread.class, thread); + throwsError(userdatacls, "optthread", LuaThread.class, thread); + } + + public void testOptJavaString() { + assertEquals("xyz", somenil.optjstring("xyz")); + assertEquals(null, somenil.optjstring(null)); + throwsError(sometrue, "optjstring", String.class, "xyz"); + throwsError(somefalse, "optjstring", String.class, "xyz"); + assertEquals(String.valueOf(zero), zero.optjstring("xyz")); + assertEquals(String.valueOf(intint), intint.optjstring("xyz")); + assertEquals(String.valueOf(longdouble), longdouble.optjstring("xyz")); + assertEquals(String.valueOf(doubledouble), doubledouble.optjstring("xyz")); + throwsError(somefunc, "optjstring", String.class, "xyz"); + throwsError(someclosure, "optjstring", String.class, "xyz"); + assertEquals(samplestringstring, stringstring.optjstring("xyz")); + assertEquals(samplestringint, stringint.optjstring("xyz")); + assertEquals(samplestringlong, stringlong.optjstring("xyz")); + assertEquals(samplestringdouble, stringdouble.optjstring("xyz")); + throwsError(thread, "optjstring", String.class, "xyz"); + throwsError(table, "optjstring", String.class, "xyz"); + throwsError(userdataobj, "optjstring", String.class, "xyz"); + throwsError(userdatacls, "optjstring", String.class, "xyz"); + } + + public void testOptLuaString() { + assertEquals(LuaValue.valueOf("xyz"), somenil.optstring(LuaValue.valueOf("xyz"))); + assertEquals(null, somenil.optstring(null)); + throwsError(sometrue, "optstring", LuaString.class, LuaValue.valueOf("xyz")); + throwsError(somefalse, "optstring", LuaString.class, LuaValue.valueOf("xyz")); + assertEquals(LuaValue.valueOf("0"), zero.optstring(LuaValue.valueOf("xyz"))); + assertEquals(stringint, intint.optstring(LuaValue.valueOf("xyz"))); + assertEquals(stringlong, longdouble.optstring(LuaValue.valueOf("xyz"))); + assertEquals(stringdouble, doubledouble.optstring(LuaValue.valueOf("xyz"))); + throwsError(somefunc, "optstring", LuaString.class, LuaValue.valueOf("xyz")); + throwsError(someclosure, "optstring", LuaString.class, LuaValue.valueOf("xyz")); + assertEquals(stringstring, stringstring.optstring(LuaValue.valueOf("xyz"))); + assertEquals(stringint, stringint.optstring(LuaValue.valueOf("xyz"))); + assertEquals(stringlong, stringlong.optstring(LuaValue.valueOf("xyz"))); + assertEquals(stringdouble, stringdouble.optstring(LuaValue.valueOf("xyz"))); + throwsError(thread, "optstring", LuaString.class, LuaValue.valueOf("xyz")); + throwsError(table, "optstring", LuaString.class, LuaValue.valueOf("xyz")); + throwsError(userdataobj, "optstring", LuaString.class, LuaValue.valueOf("xyz")); + throwsError(userdatacls, "optstring", LuaString.class, LuaValue.valueOf("xyz")); + } + + public void testOptUserdata() { + assertEquals(sampleobject, somenil.optuserdata(sampleobject)); + assertEquals(sampledata, somenil.optuserdata(sampledata)); + assertEquals(null, somenil.optuserdata(null)); + throwsError(sometrue, "optuserdata", Object.class, sampledata); + throwsError(somefalse, "optuserdata", Object.class, sampledata); + throwsError(zero, "optuserdata", Object.class, sampledata); + throwsError(intint, "optuserdata", Object.class, sampledata); + throwsError(longdouble, "optuserdata", Object.class, sampledata); + throwsError(doubledouble, "optuserdata", Object.class, sampledata); + throwsError(somefunc, "optuserdata", Object.class, sampledata); + throwsError(someclosure, "optuserdata", Object.class, sampledata); + throwsError(stringstring, "optuserdata", Object.class, sampledata); + throwsError(stringint, "optuserdata", Object.class, sampledata); + throwsError(stringlong, "optuserdata", Object.class, sampledata); + throwsError(stringdouble, "optuserdata", Object.class, sampledata); + throwsError(table, "optuserdata", Object.class, sampledata); + assertEquals(sampleobject, userdataobj.optuserdata(sampledata)); + assertEquals(sampleobject, userdataobj.optuserdata(null)); + assertEquals(sampledata, userdatacls.optuserdata(sampleobject)); + assertEquals(sampledata, userdatacls.optuserdata(null)); + } + + private void throwsErrorOptUserdataClass(LuaValue obj, Class arg1, Object arg2) { try { - obj.getClass().getMethod("optuserdata", Class.class, Object.class ).invoke(obj, arg1, arg2); + obj.getClass().getMethod("optuserdata", Class.class, Object.class).invoke(obj, arg1, arg2); } catch (InvocationTargetException e) { - if ( ! (e.getTargetException() instanceof LuaError) ) - fail("not a LuaError: "+e.getTargetException()); + if (!(e.getTargetException() instanceof LuaError)) + fail("not a LuaError: " + e.getTargetException()); return; // pass - } catch ( Exception e ) { - fail( "bad exception: "+e ); + } catch (Exception e) { + fail("bad exception: " + e); } fail("failed to throw LuaError as required"); } - + public void testOptUserdataClass() { - assertEquals( sampledata, somenil.optuserdata(MyData.class, sampledata) ); - assertEquals( sampleobject, somenil.optuserdata(Object.class, sampleobject) ); - assertEquals( null, somenil.optuserdata(null) ); - throwsErrorOptUserdataClass( sometrue, Object.class, sampledata ); - throwsErrorOptUserdataClass( zero, MyData.class, sampledata); - throwsErrorOptUserdataClass( intint, MyData.class, sampledata); - throwsErrorOptUserdataClass( longdouble, MyData.class, sampledata); - throwsErrorOptUserdataClass( somefunc, MyData.class, sampledata); - throwsErrorOptUserdataClass( someclosure, MyData.class, sampledata); - throwsErrorOptUserdataClass( stringstring, MyData.class, sampledata); - throwsErrorOptUserdataClass( stringint, MyData.class, sampledata); - throwsErrorOptUserdataClass( stringlong, MyData.class, sampledata); - throwsErrorOptUserdataClass( stringlong, MyData.class, sampledata); - throwsErrorOptUserdataClass( stringdouble, MyData.class, sampledata); - throwsErrorOptUserdataClass( table, MyData.class, sampledata); - throwsErrorOptUserdataClass( thread, MyData.class, sampledata); - assertEquals( sampleobject, userdataobj.optuserdata(Object.class, sampleobject) ); - assertEquals( sampleobject, userdataobj.optuserdata(null) ); - assertEquals( sampledata, userdatacls.optuserdata(MyData.class, sampledata) ); - assertEquals( sampledata, userdatacls.optuserdata(Object.class, sampleobject) ); - assertEquals( sampledata, userdatacls.optuserdata(null) ); + assertEquals(sampledata, somenil.optuserdata(MyData.class, sampledata)); + assertEquals(sampleobject, somenil.optuserdata(Object.class, sampleobject)); + assertEquals(null, somenil.optuserdata(null)); + throwsErrorOptUserdataClass(sometrue, Object.class, sampledata); + throwsErrorOptUserdataClass(zero, MyData.class, sampledata); + throwsErrorOptUserdataClass(intint, MyData.class, sampledata); + throwsErrorOptUserdataClass(longdouble, MyData.class, sampledata); + throwsErrorOptUserdataClass(somefunc, MyData.class, sampledata); + throwsErrorOptUserdataClass(someclosure, MyData.class, sampledata); + throwsErrorOptUserdataClass(stringstring, MyData.class, sampledata); + throwsErrorOptUserdataClass(stringint, MyData.class, sampledata); + throwsErrorOptUserdataClass(stringlong, MyData.class, sampledata); + throwsErrorOptUserdataClass(stringlong, MyData.class, sampledata); + throwsErrorOptUserdataClass(stringdouble, MyData.class, sampledata); + throwsErrorOptUserdataClass(table, MyData.class, sampledata); + throwsErrorOptUserdataClass(thread, MyData.class, sampledata); + assertEquals(sampleobject, userdataobj.optuserdata(Object.class, sampleobject)); + assertEquals(sampleobject, userdataobj.optuserdata(null)); + assertEquals(sampledata, userdatacls.optuserdata(MyData.class, sampledata)); + assertEquals(sampledata, userdatacls.optuserdata(Object.class, sampleobject)); + assertEquals(sampledata, userdatacls.optuserdata(null)); // should fail due to wrong class try { Object o = userdataobj.optuserdata(MyData.class, sampledata); - fail( "did not throw bad type error" ); - assertTrue( o instanceof MyData ); - } catch ( LuaError le ) { - assertEquals( "org.luaj.vm2.TypeTest$MyData expected, got userdata", le.getMessage() ); + fail("did not throw bad type error"); + assertTrue(o instanceof MyData); + } catch (LuaError le) { + assertEquals("org.luaj.vm2.TypeTest$MyData expected, got userdata", le.getMessage()); } } - + public void testOptValue() { - assertEquals( zero, somenil.optvalue(zero) ); - assertEquals( stringstring, somenil.optvalue(stringstring) ); - assertEquals( sometrue, sometrue.optvalue(LuaValue.TRUE) ); - assertEquals( somefalse, somefalse.optvalue(LuaValue.TRUE) ); - assertEquals( zero, zero.optvalue(LuaValue.TRUE) ); - assertEquals( intint, intint.optvalue(LuaValue.TRUE) ); - assertEquals( longdouble, longdouble.optvalue(LuaValue.TRUE) ); - assertEquals( somefunc, somefunc.optvalue(LuaValue.TRUE) ); - assertEquals( someclosure, someclosure.optvalue(LuaValue.TRUE) ); - assertEquals( stringstring, stringstring.optvalue(LuaValue.TRUE) ); - assertEquals( stringint, stringint.optvalue(LuaValue.TRUE) ); - assertEquals( stringlong, stringlong.optvalue(LuaValue.TRUE) ); - assertEquals( stringdouble, stringdouble.optvalue(LuaValue.TRUE) ); - assertEquals( thread, thread.optvalue(LuaValue.TRUE) ); - assertEquals( table, table.optvalue(LuaValue.TRUE) ); - assertEquals( userdataobj, userdataobj.optvalue(LuaValue.TRUE) ); - assertEquals( userdatacls, userdatacls.optvalue(LuaValue.TRUE) ); + assertEquals(zero, somenil.optvalue(zero)); + assertEquals(stringstring, somenil.optvalue(stringstring)); + assertEquals(sometrue, sometrue.optvalue(LuaValue.TRUE)); + assertEquals(somefalse, somefalse.optvalue(LuaValue.TRUE)); + assertEquals(zero, zero.optvalue(LuaValue.TRUE)); + assertEquals(intint, intint.optvalue(LuaValue.TRUE)); + assertEquals(longdouble, longdouble.optvalue(LuaValue.TRUE)); + assertEquals(somefunc, somefunc.optvalue(LuaValue.TRUE)); + assertEquals(someclosure, someclosure.optvalue(LuaValue.TRUE)); + assertEquals(stringstring, stringstring.optvalue(LuaValue.TRUE)); + assertEquals(stringint, stringint.optvalue(LuaValue.TRUE)); + assertEquals(stringlong, stringlong.optvalue(LuaValue.TRUE)); + assertEquals(stringdouble, stringdouble.optvalue(LuaValue.TRUE)); + assertEquals(thread, thread.optvalue(LuaValue.TRUE)); + assertEquals(table, table.optvalue(LuaValue.TRUE)); + assertEquals(userdataobj, userdataobj.optvalue(LuaValue.TRUE)); + assertEquals(userdatacls, userdatacls.optvalue(LuaValue.TRUE)); } - - - + // ===================== Required argument conversion ======================= - - private void throwsErrorReq(LuaValue obj, String method ) { + private void throwsErrorReq(LuaValue obj, String method) { try { obj.getClass().getMethod(method).invoke(obj); } catch (InvocationTargetException e) { - if ( ! (e.getTargetException() instanceof LuaError) ) - fail("not a LuaError: "+e.getTargetException()); + if (!(e.getTargetException() instanceof LuaError)) + fail("not a LuaError: " + e.getTargetException()); return; // pass - } catch ( Exception e ) { - fail( "bad exception: "+e ); + } catch (Exception e) { + fail("bad exception: " + e); } fail("failed to throw LuaError as required"); } public void testCheckBoolean() { - throwsErrorReq( somenil, "checkboolean" ); - assertEquals( true, sometrue.checkboolean() ); - assertEquals( false, somefalse.checkboolean() ); - throwsErrorReq( zero, "checkboolean" ); - throwsErrorReq( intint, "checkboolean" ); - throwsErrorReq( longdouble, "checkboolean" ); - throwsErrorReq( doubledouble, "checkboolean" ); - throwsErrorReq( somefunc, "checkboolean" ); - throwsErrorReq( someclosure, "checkboolean" ); - throwsErrorReq( stringstring, "checkboolean" ); - throwsErrorReq( stringint, "checkboolean" ); - throwsErrorReq( stringlong, "checkboolean" ); - throwsErrorReq( stringdouble, "checkboolean" ); - throwsErrorReq( thread, "checkboolean" ); - throwsErrorReq( table, "checkboolean" ); - throwsErrorReq( userdataobj, "checkboolean" ); - throwsErrorReq( userdatacls, "checkboolean" ); + throwsErrorReq(somenil, "checkboolean"); + assertEquals(true, sometrue.checkboolean()); + assertEquals(false, somefalse.checkboolean()); + throwsErrorReq(zero, "checkboolean"); + throwsErrorReq(intint, "checkboolean"); + throwsErrorReq(longdouble, "checkboolean"); + throwsErrorReq(doubledouble, "checkboolean"); + throwsErrorReq(somefunc, "checkboolean"); + throwsErrorReq(someclosure, "checkboolean"); + throwsErrorReq(stringstring, "checkboolean"); + throwsErrorReq(stringint, "checkboolean"); + throwsErrorReq(stringlong, "checkboolean"); + throwsErrorReq(stringdouble, "checkboolean"); + throwsErrorReq(thread, "checkboolean"); + throwsErrorReq(table, "checkboolean"); + throwsErrorReq(userdataobj, "checkboolean"); + throwsErrorReq(userdatacls, "checkboolean"); } public void testCheckClosure() { - throwsErrorReq( somenil, "checkclosure" ); - throwsErrorReq( sometrue, "checkclosure" ); - throwsErrorReq( somefalse, "checkclosure" ); - throwsErrorReq( zero, "checkclosure" ); - throwsErrorReq( intint, "checkclosure" ); - throwsErrorReq( longdouble, "checkclosure" ); - throwsErrorReq( doubledouble, "checkclosure" ); - throwsErrorReq( somefunc, "checkclosure" ); - assertEquals( someclosure, someclosure.checkclosure() ); - assertEquals( someclosure, someclosure.checkclosure() ); - throwsErrorReq( stringstring, "checkclosure" ); - throwsErrorReq( stringint, "checkclosure" ); - throwsErrorReq( stringlong, "checkclosure" ); - throwsErrorReq( stringdouble, "checkclosure" ); - throwsErrorReq( thread, "checkclosure" ); - throwsErrorReq( table, "checkclosure" ); - throwsErrorReq( userdataobj, "checkclosure" ); - throwsErrorReq( userdatacls, "checkclosure" ); + throwsErrorReq(somenil, "checkclosure"); + throwsErrorReq(sometrue, "checkclosure"); + throwsErrorReq(somefalse, "checkclosure"); + throwsErrorReq(zero, "checkclosure"); + throwsErrorReq(intint, "checkclosure"); + throwsErrorReq(longdouble, "checkclosure"); + throwsErrorReq(doubledouble, "checkclosure"); + throwsErrorReq(somefunc, "checkclosure"); + assertEquals(someclosure, someclosure.checkclosure()); + assertEquals(someclosure, someclosure.checkclosure()); + throwsErrorReq(stringstring, "checkclosure"); + throwsErrorReq(stringint, "checkclosure"); + throwsErrorReq(stringlong, "checkclosure"); + throwsErrorReq(stringdouble, "checkclosure"); + throwsErrorReq(thread, "checkclosure"); + throwsErrorReq(table, "checkclosure"); + throwsErrorReq(userdataobj, "checkclosure"); + throwsErrorReq(userdatacls, "checkclosure"); } public void testCheckDouble() { - throwsErrorReq( somenil, "checkdouble" ); - throwsErrorReq( sometrue, "checkdouble" ); - throwsErrorReq( somefalse, "checkdouble" ); - assertEquals( 0., zero.checkdouble() ); - assertEquals( (double) sampleint, intint.checkdouble() ); - assertEquals( (double) samplelong, longdouble.checkdouble() ); - assertEquals( sampledouble, doubledouble.checkdouble() ); - throwsErrorReq( somefunc, "checkdouble" ); - throwsErrorReq( someclosure, "checkdouble" ); - throwsErrorReq( stringstring, "checkdouble" ); - assertEquals( (double) sampleint, stringint.checkdouble() ); - assertEquals( (double) samplelong, stringlong.checkdouble() ); - assertEquals( sampledouble, stringdouble.checkdouble() ); - throwsErrorReq( thread, "checkdouble" ); - throwsErrorReq( table, "checkdouble" ); - throwsErrorReq( userdataobj, "checkdouble" ); - throwsErrorReq( userdatacls, "checkdouble" ); + throwsErrorReq(somenil, "checkdouble"); + throwsErrorReq(sometrue, "checkdouble"); + throwsErrorReq(somefalse, "checkdouble"); + assertEquals(0., zero.checkdouble()); + assertEquals((double) sampleint, intint.checkdouble()); + assertEquals((double) samplelong, longdouble.checkdouble()); + assertEquals(sampledouble, doubledouble.checkdouble()); + throwsErrorReq(somefunc, "checkdouble"); + throwsErrorReq(someclosure, "checkdouble"); + throwsErrorReq(stringstring, "checkdouble"); + assertEquals((double) sampleint, stringint.checkdouble()); + assertEquals((double) samplelong, stringlong.checkdouble()); + assertEquals(sampledouble, stringdouble.checkdouble()); + throwsErrorReq(thread, "checkdouble"); + throwsErrorReq(table, "checkdouble"); + throwsErrorReq(userdataobj, "checkdouble"); + throwsErrorReq(userdatacls, "checkdouble"); } public void testCheckFunction() { - throwsErrorReq( somenil, "checkfunction" ); - throwsErrorReq( sometrue, "checkfunction" ); - throwsErrorReq( somefalse, "checkfunction" ); - throwsErrorReq( zero, "checkfunction" ); - throwsErrorReq( intint, "checkfunction" ); - throwsErrorReq( longdouble, "checkfunction" ); - throwsErrorReq( doubledouble, "checkfunction" ); - assertEquals( somefunc, somefunc.checkfunction() ); - assertEquals( someclosure, someclosure.checkfunction() ); - assertEquals( somefunc, somefunc.checkfunction() ); - assertEquals( someclosure, someclosure.checkfunction() ); - throwsErrorReq( stringstring, "checkfunction" ); - throwsErrorReq( stringint, "checkfunction" ); - throwsErrorReq( stringlong, "checkfunction" ); - throwsErrorReq( stringdouble, "checkfunction" ); - throwsErrorReq( thread, "checkfunction" ); - throwsErrorReq( table, "checkfunction" ); - throwsErrorReq( userdataobj, "checkfunction" ); - throwsErrorReq( userdatacls, "checkfunction" ); + throwsErrorReq(somenil, "checkfunction"); + throwsErrorReq(sometrue, "checkfunction"); + throwsErrorReq(somefalse, "checkfunction"); + throwsErrorReq(zero, "checkfunction"); + throwsErrorReq(intint, "checkfunction"); + throwsErrorReq(longdouble, "checkfunction"); + throwsErrorReq(doubledouble, "checkfunction"); + assertEquals(somefunc, somefunc.checkfunction()); + assertEquals(someclosure, someclosure.checkfunction()); + assertEquals(somefunc, somefunc.checkfunction()); + assertEquals(someclosure, someclosure.checkfunction()); + throwsErrorReq(stringstring, "checkfunction"); + throwsErrorReq(stringint, "checkfunction"); + throwsErrorReq(stringlong, "checkfunction"); + throwsErrorReq(stringdouble, "checkfunction"); + throwsErrorReq(thread, "checkfunction"); + throwsErrorReq(table, "checkfunction"); + throwsErrorReq(userdataobj, "checkfunction"); + throwsErrorReq(userdatacls, "checkfunction"); } public void testCheckInt() { - throwsErrorReq( somenil, "checkint" ); - throwsErrorReq( sometrue, "checkint" ); - throwsErrorReq( somefalse, "checkint" ); - assertEquals( 0, zero.checkint() ); - assertEquals( sampleint, intint.checkint() ); - assertEquals( (int) samplelong, longdouble.checkint() ); - assertEquals( (int) sampledouble, doubledouble.checkint() ); - throwsErrorReq( somefunc, "checkint" ); - throwsErrorReq( someclosure, "checkint" ); - throwsErrorReq( stringstring, "checkint" ); - assertEquals( sampleint, stringint.checkint() ); - assertEquals( (int) samplelong, stringlong.checkint() ); - assertEquals( (int) sampledouble, stringdouble.checkint() ); - throwsErrorReq( thread, "checkint" ); - throwsErrorReq( table, "checkint" ); - throwsErrorReq( userdataobj, "checkint" ); - throwsErrorReq( userdatacls, "checkint" ); + throwsErrorReq(somenil, "checkint"); + throwsErrorReq(sometrue, "checkint"); + throwsErrorReq(somefalse, "checkint"); + assertEquals(0, zero.checkint()); + assertEquals(sampleint, intint.checkint()); + assertEquals((int) samplelong, longdouble.checkint()); + assertEquals((int) sampledouble, doubledouble.checkint()); + throwsErrorReq(somefunc, "checkint"); + throwsErrorReq(someclosure, "checkint"); + throwsErrorReq(stringstring, "checkint"); + assertEquals(sampleint, stringint.checkint()); + assertEquals((int) samplelong, stringlong.checkint()); + assertEquals((int) sampledouble, stringdouble.checkint()); + throwsErrorReq(thread, "checkint"); + throwsErrorReq(table, "checkint"); + throwsErrorReq(userdataobj, "checkint"); + throwsErrorReq(userdatacls, "checkint"); } - + public void testCheckInteger() { - throwsErrorReq( somenil, "checkinteger" ); - throwsErrorReq( sometrue, "checkinteger" ); - throwsErrorReq( somefalse, "checkinteger" ); - assertEquals( zero, zero.checkinteger() ); - assertEquals( LuaValue.valueOf( sampleint ), intint.checkinteger() ); - assertEquals( LuaValue.valueOf( (int) samplelong ), longdouble.checkinteger() ); - assertEquals( LuaValue.valueOf( (int) sampledouble ), doubledouble.checkinteger() ); - throwsErrorReq( somefunc, "checkinteger" ); - throwsErrorReq( someclosure, "checkinteger" ); - throwsErrorReq( stringstring, "checkinteger" ); - assertEquals( LuaValue.valueOf( sampleint), stringint.checkinteger() ); - assertEquals( LuaValue.valueOf( (int) samplelong), stringlong.checkinteger() ); - assertEquals( LuaValue.valueOf( (int) sampledouble), stringdouble.checkinteger() ); - throwsErrorReq( thread, "checkinteger" ); - throwsErrorReq( table, "checkinteger" ); - throwsErrorReq( userdataobj, "checkinteger" ); - throwsErrorReq( userdatacls, "checkinteger" ); + throwsErrorReq(somenil, "checkinteger"); + throwsErrorReq(sometrue, "checkinteger"); + throwsErrorReq(somefalse, "checkinteger"); + assertEquals(zero, zero.checkinteger()); + assertEquals(LuaValue.valueOf(sampleint), intint.checkinteger()); + assertEquals(LuaValue.valueOf((int) samplelong), longdouble.checkinteger()); + assertEquals(LuaValue.valueOf((int) sampledouble), doubledouble.checkinteger()); + throwsErrorReq(somefunc, "checkinteger"); + throwsErrorReq(someclosure, "checkinteger"); + throwsErrorReq(stringstring, "checkinteger"); + assertEquals(LuaValue.valueOf(sampleint), stringint.checkinteger()); + assertEquals(LuaValue.valueOf((int) samplelong), stringlong.checkinteger()); + assertEquals(LuaValue.valueOf((int) sampledouble), stringdouble.checkinteger()); + throwsErrorReq(thread, "checkinteger"); + throwsErrorReq(table, "checkinteger"); + throwsErrorReq(userdataobj, "checkinteger"); + throwsErrorReq(userdatacls, "checkinteger"); } public void testCheckLong() { - throwsErrorReq( somenil, "checklong" ); - throwsErrorReq( sometrue, "checklong" ); - throwsErrorReq( somefalse, "checklong" ); - assertEquals( 0L, zero.checklong() ); - assertEquals( sampleint, intint.checklong() ); - assertEquals( (long) samplelong, longdouble.checklong() ); - assertEquals( (long) sampledouble, doubledouble.checklong() ); - throwsErrorReq( somefunc, "checklong" ); - throwsErrorReq( someclosure, "checklong" ); - throwsErrorReq( stringstring, "checklong" ); - assertEquals( sampleint, stringint.checklong() ); - assertEquals( (long) samplelong, stringlong.checklong() ); - assertEquals( (long) sampledouble, stringdouble.checklong() ); - throwsErrorReq( thread, "checklong" ); - throwsErrorReq( table, "checklong" ); - throwsErrorReq( userdataobj, "checklong" ); - throwsErrorReq( userdatacls, "checklong" ); - } - - public void testCheckNumber() { - throwsErrorReq( somenil, "checknumber" ); - throwsErrorReq( sometrue, "checknumber" ); - throwsErrorReq( somefalse, "checknumber" ); - assertEquals( zero, zero.checknumber() ); - assertEquals( LuaValue.valueOf( sampleint ), intint.checknumber() ); - assertEquals( LuaValue.valueOf( samplelong ), longdouble.checknumber() ); - assertEquals( LuaValue.valueOf( sampledouble ), doubledouble.checknumber() ); - throwsErrorReq( somefunc, "checknumber" ); - throwsErrorReq( someclosure, "checknumber" ); - throwsErrorReq( stringstring, "checknumber" ); - assertEquals( LuaValue.valueOf( sampleint), stringint.checknumber() ); - assertEquals( LuaValue.valueOf( samplelong), stringlong.checknumber() ); - assertEquals( LuaValue.valueOf( sampledouble), stringdouble.checknumber() ); - throwsErrorReq( thread, "checknumber" ); - throwsErrorReq( table, "checknumber" ); - throwsErrorReq( userdataobj, "checknumber" ); - throwsErrorReq( userdatacls, "checknumber" ); - } - - public void testCheckTable() { - throwsErrorReq( somenil, "checktable" ); - throwsErrorReq( sometrue, "checktable" ); - throwsErrorReq( somefalse, "checktable" ); - throwsErrorReq( zero, "checktable" ); - throwsErrorReq( intint, "checktable" ); - throwsErrorReq( longdouble, "checktable" ); - throwsErrorReq( doubledouble, "checktable" ); - throwsErrorReq( somefunc, "checktable" ); - throwsErrorReq( someclosure, "checktable" ); - throwsErrorReq( stringstring, "checktable" ); - throwsErrorReq( stringint, "checktable" ); - throwsErrorReq( stringlong, "checktable" ); - throwsErrorReq( stringdouble, "checktable" ); - throwsErrorReq( thread, "checktable" ); - assertEquals( table, table.checktable() ); - assertEquals( table, table.checktable() ); - throwsErrorReq( userdataobj, "checktable" ); - throwsErrorReq( userdatacls, "checktable" ); - } - - public void testCheckThread() { - throwsErrorReq( somenil, "checkthread" ); - throwsErrorReq( sometrue, "checkthread" ); - throwsErrorReq( somefalse, "checkthread" ); - throwsErrorReq( zero, "checkthread" ); - throwsErrorReq( intint, "checkthread" ); - throwsErrorReq( longdouble, "checkthread" ); - throwsErrorReq( doubledouble, "checkthread" ); - throwsErrorReq( somefunc, "checkthread" ); - throwsErrorReq( someclosure, "checkthread" ); - throwsErrorReq( stringstring, "checkthread" ); - throwsErrorReq( stringint, "checkthread" ); - throwsErrorReq( stringlong, "checkthread" ); - throwsErrorReq( stringdouble, "checkthread" ); - throwsErrorReq( table, "checkthread" ); - assertEquals( thread, thread.checkthread() ); - assertEquals( thread, thread.checkthread() ); - throwsErrorReq( userdataobj, "checkthread" ); - throwsErrorReq( userdatacls, "checkthread" ); - } - - public void testCheckJavaString() { - throwsErrorReq( somenil, "checkjstring" ); - throwsErrorReq( sometrue, "checkjstring" ); - throwsErrorReq( somefalse, "checkjstring" ); - assertEquals( String.valueOf(zero), zero.checkjstring() ); - assertEquals( String.valueOf(intint), intint.checkjstring() ); - assertEquals( String.valueOf(longdouble), longdouble.checkjstring() ); - assertEquals( String.valueOf(doubledouble), doubledouble.checkjstring() ); - throwsErrorReq( somefunc, "checkjstring" ); - throwsErrorReq( someclosure, "checkjstring" ); - assertEquals( samplestringstring, stringstring.checkjstring() ); - assertEquals( samplestringint, stringint.checkjstring() ); - assertEquals( samplestringlong, stringlong.checkjstring() ); - assertEquals( samplestringdouble, stringdouble.checkjstring() ); - throwsErrorReq( thread, "checkjstring" ); - throwsErrorReq( table, "checkjstring" ); - throwsErrorReq( userdataobj, "checkjstring" ); - throwsErrorReq( userdatacls, "checkjstring" ); - } - - public void testCheckLuaString() { - throwsErrorReq( somenil, "checkstring" ); - throwsErrorReq( sometrue, "checkstring" ); - throwsErrorReq( somefalse, "checkstring" ); - assertEquals( LuaValue.valueOf("0"), zero.checkstring() ); - assertEquals( stringint, intint.checkstring() ); - assertEquals( stringlong, longdouble.checkstring() ); - assertEquals( stringdouble, doubledouble.checkstring() ); - throwsErrorReq( somefunc, "checkstring" ); - throwsErrorReq( someclosure, "checkstring" ); - assertEquals( stringstring, stringstring.checkstring() ); - assertEquals( stringint, stringint.checkstring() ); - assertEquals( stringlong, stringlong.checkstring() ); - assertEquals( stringdouble, stringdouble.checkstring() ); - throwsErrorReq( thread, "checkstring" ); - throwsErrorReq( table, "checkstring" ); - throwsErrorReq( userdataobj, "checkstring" ); - throwsErrorReq( userdatacls, "checkstring" ); - } - - public void testCheckUserdata() { - throwsErrorReq( somenil, "checkuserdata" ); - throwsErrorReq( sometrue, "checkuserdata" ); - throwsErrorReq( somefalse, "checkuserdata" ); - throwsErrorReq( zero, "checkuserdata" ); - throwsErrorReq( intint, "checkuserdata" ); - throwsErrorReq( longdouble, "checkuserdata" ); - throwsErrorReq( doubledouble, "checkuserdata" ); - throwsErrorReq( somefunc, "checkuserdata" ); - throwsErrorReq( someclosure, "checkuserdata" ); - throwsErrorReq( stringstring, "checkuserdata" ); - throwsErrorReq( stringint, "checkuserdata" ); - throwsErrorReq( stringlong, "checkuserdata" ); - throwsErrorReq( stringdouble, "checkuserdata" ); - throwsErrorReq( table, "checkuserdata" ); - assertEquals( sampleobject, userdataobj.checkuserdata() ); - assertEquals( sampleobject, userdataobj.checkuserdata() ); - assertEquals( sampledata, userdatacls.checkuserdata() ); - assertEquals( sampledata, userdatacls.checkuserdata() ); + throwsErrorReq(somenil, "checklong"); + throwsErrorReq(sometrue, "checklong"); + throwsErrorReq(somefalse, "checklong"); + assertEquals(0L, zero.checklong()); + assertEquals(sampleint, intint.checklong()); + assertEquals((long) samplelong, longdouble.checklong()); + assertEquals((long) sampledouble, doubledouble.checklong()); + throwsErrorReq(somefunc, "checklong"); + throwsErrorReq(someclosure, "checklong"); + throwsErrorReq(stringstring, "checklong"); + assertEquals(sampleint, stringint.checklong()); + assertEquals((long) samplelong, stringlong.checklong()); + assertEquals((long) sampledouble, stringdouble.checklong()); + throwsErrorReq(thread, "checklong"); + throwsErrorReq(table, "checklong"); + throwsErrorReq(userdataobj, "checklong"); + throwsErrorReq(userdatacls, "checklong"); } - private void throwsErrorReqCheckUserdataClass(LuaValue obj, Class arg ) { + public void testCheckNumber() { + throwsErrorReq(somenil, "checknumber"); + throwsErrorReq(sometrue, "checknumber"); + throwsErrorReq(somefalse, "checknumber"); + assertEquals(zero, zero.checknumber()); + assertEquals(LuaValue.valueOf(sampleint), intint.checknumber()); + assertEquals(LuaValue.valueOf(samplelong), longdouble.checknumber()); + assertEquals(LuaValue.valueOf(sampledouble), doubledouble.checknumber()); + throwsErrorReq(somefunc, "checknumber"); + throwsErrorReq(someclosure, "checknumber"); + throwsErrorReq(stringstring, "checknumber"); + assertEquals(LuaValue.valueOf(sampleint), stringint.checknumber()); + assertEquals(LuaValue.valueOf(samplelong), stringlong.checknumber()); + assertEquals(LuaValue.valueOf(sampledouble), stringdouble.checknumber()); + throwsErrorReq(thread, "checknumber"); + throwsErrorReq(table, "checknumber"); + throwsErrorReq(userdataobj, "checknumber"); + throwsErrorReq(userdatacls, "checknumber"); + } + + public void testCheckTable() { + throwsErrorReq(somenil, "checktable"); + throwsErrorReq(sometrue, "checktable"); + throwsErrorReq(somefalse, "checktable"); + throwsErrorReq(zero, "checktable"); + throwsErrorReq(intint, "checktable"); + throwsErrorReq(longdouble, "checktable"); + throwsErrorReq(doubledouble, "checktable"); + throwsErrorReq(somefunc, "checktable"); + throwsErrorReq(someclosure, "checktable"); + throwsErrorReq(stringstring, "checktable"); + throwsErrorReq(stringint, "checktable"); + throwsErrorReq(stringlong, "checktable"); + throwsErrorReq(stringdouble, "checktable"); + throwsErrorReq(thread, "checktable"); + assertEquals(table, table.checktable()); + assertEquals(table, table.checktable()); + throwsErrorReq(userdataobj, "checktable"); + throwsErrorReq(userdatacls, "checktable"); + } + + public void testCheckThread() { + throwsErrorReq(somenil, "checkthread"); + throwsErrorReq(sometrue, "checkthread"); + throwsErrorReq(somefalse, "checkthread"); + throwsErrorReq(zero, "checkthread"); + throwsErrorReq(intint, "checkthread"); + throwsErrorReq(longdouble, "checkthread"); + throwsErrorReq(doubledouble, "checkthread"); + throwsErrorReq(somefunc, "checkthread"); + throwsErrorReq(someclosure, "checkthread"); + throwsErrorReq(stringstring, "checkthread"); + throwsErrorReq(stringint, "checkthread"); + throwsErrorReq(stringlong, "checkthread"); + throwsErrorReq(stringdouble, "checkthread"); + throwsErrorReq(table, "checkthread"); + assertEquals(thread, thread.checkthread()); + assertEquals(thread, thread.checkthread()); + throwsErrorReq(userdataobj, "checkthread"); + throwsErrorReq(userdatacls, "checkthread"); + } + + public void testCheckJavaString() { + throwsErrorReq(somenil, "checkjstring"); + throwsErrorReq(sometrue, "checkjstring"); + throwsErrorReq(somefalse, "checkjstring"); + assertEquals(String.valueOf(zero), zero.checkjstring()); + assertEquals(String.valueOf(intint), intint.checkjstring()); + assertEquals(String.valueOf(longdouble), longdouble.checkjstring()); + assertEquals(String.valueOf(doubledouble), doubledouble.checkjstring()); + throwsErrorReq(somefunc, "checkjstring"); + throwsErrorReq(someclosure, "checkjstring"); + assertEquals(samplestringstring, stringstring.checkjstring()); + assertEquals(samplestringint, stringint.checkjstring()); + assertEquals(samplestringlong, stringlong.checkjstring()); + assertEquals(samplestringdouble, stringdouble.checkjstring()); + throwsErrorReq(thread, "checkjstring"); + throwsErrorReq(table, "checkjstring"); + throwsErrorReq(userdataobj, "checkjstring"); + throwsErrorReq(userdatacls, "checkjstring"); + } + + public void testCheckLuaString() { + throwsErrorReq(somenil, "checkstring"); + throwsErrorReq(sometrue, "checkstring"); + throwsErrorReq(somefalse, "checkstring"); + assertEquals(LuaValue.valueOf("0"), zero.checkstring()); + assertEquals(stringint, intint.checkstring()); + assertEquals(stringlong, longdouble.checkstring()); + assertEquals(stringdouble, doubledouble.checkstring()); + throwsErrorReq(somefunc, "checkstring"); + throwsErrorReq(someclosure, "checkstring"); + assertEquals(stringstring, stringstring.checkstring()); + assertEquals(stringint, stringint.checkstring()); + assertEquals(stringlong, stringlong.checkstring()); + assertEquals(stringdouble, stringdouble.checkstring()); + throwsErrorReq(thread, "checkstring"); + throwsErrorReq(table, "checkstring"); + throwsErrorReq(userdataobj, "checkstring"); + throwsErrorReq(userdatacls, "checkstring"); + } + + public void testCheckUserdata() { + throwsErrorReq(somenil, "checkuserdata"); + throwsErrorReq(sometrue, "checkuserdata"); + throwsErrorReq(somefalse, "checkuserdata"); + throwsErrorReq(zero, "checkuserdata"); + throwsErrorReq(intint, "checkuserdata"); + throwsErrorReq(longdouble, "checkuserdata"); + throwsErrorReq(doubledouble, "checkuserdata"); + throwsErrorReq(somefunc, "checkuserdata"); + throwsErrorReq(someclosure, "checkuserdata"); + throwsErrorReq(stringstring, "checkuserdata"); + throwsErrorReq(stringint, "checkuserdata"); + throwsErrorReq(stringlong, "checkuserdata"); + throwsErrorReq(stringdouble, "checkuserdata"); + throwsErrorReq(table, "checkuserdata"); + assertEquals(sampleobject, userdataobj.checkuserdata()); + assertEquals(sampleobject, userdataobj.checkuserdata()); + assertEquals(sampledata, userdatacls.checkuserdata()); + assertEquals(sampledata, userdatacls.checkuserdata()); + } + + private void throwsErrorReqCheckUserdataClass(LuaValue obj, Class arg) { try { - obj.getClass().getMethod("checkuserdata", Class.class ).invoke(obj, arg); + obj.getClass().getMethod("checkuserdata", Class.class).invoke(obj, arg); } catch (InvocationTargetException e) { - if ( ! (e.getTargetException() instanceof LuaError) ) - fail("not a LuaError: "+e.getTargetException()); + if (!(e.getTargetException() instanceof LuaError)) + fail("not a LuaError: " + e.getTargetException()); return; // pass - } catch ( Exception e ) { - fail( "bad exception: "+e ); + } catch (Exception e) { + fail("bad exception: " + e); } fail("failed to throw LuaError as required"); } - + public void testCheckUserdataClass() { - throwsErrorReqCheckUserdataClass( somenil, Object.class ); - throwsErrorReqCheckUserdataClass( somenil, MyData.class); - throwsErrorReqCheckUserdataClass( sometrue, Object.class ); - throwsErrorReqCheckUserdataClass( zero, MyData.class); - throwsErrorReqCheckUserdataClass( intint, MyData.class); - throwsErrorReqCheckUserdataClass( longdouble, MyData.class); - throwsErrorReqCheckUserdataClass( somefunc, MyData.class); - throwsErrorReqCheckUserdataClass( someclosure, MyData.class); - throwsErrorReqCheckUserdataClass( stringstring, MyData.class); - throwsErrorReqCheckUserdataClass( stringint, MyData.class); - throwsErrorReqCheckUserdataClass( stringlong, MyData.class); - throwsErrorReqCheckUserdataClass( stringlong, MyData.class); - throwsErrorReqCheckUserdataClass( stringdouble, MyData.class); - throwsErrorReqCheckUserdataClass( table, MyData.class); - throwsErrorReqCheckUserdataClass( thread, MyData.class); - assertEquals( sampleobject, userdataobj.checkuserdata(Object.class) ); - assertEquals( sampleobject, userdataobj.checkuserdata() ); - assertEquals( sampledata, userdatacls.checkuserdata(MyData.class) ); - assertEquals( sampledata, userdatacls.checkuserdata(Object.class) ); - assertEquals( sampledata, userdatacls.checkuserdata() ); + throwsErrorReqCheckUserdataClass(somenil, Object.class); + throwsErrorReqCheckUserdataClass(somenil, MyData.class); + throwsErrorReqCheckUserdataClass(sometrue, Object.class); + throwsErrorReqCheckUserdataClass(zero, MyData.class); + throwsErrorReqCheckUserdataClass(intint, MyData.class); + throwsErrorReqCheckUserdataClass(longdouble, MyData.class); + throwsErrorReqCheckUserdataClass(somefunc, MyData.class); + throwsErrorReqCheckUserdataClass(someclosure, MyData.class); + throwsErrorReqCheckUserdataClass(stringstring, MyData.class); + throwsErrorReqCheckUserdataClass(stringint, MyData.class); + throwsErrorReqCheckUserdataClass(stringlong, MyData.class); + throwsErrorReqCheckUserdataClass(stringlong, MyData.class); + throwsErrorReqCheckUserdataClass(stringdouble, MyData.class); + throwsErrorReqCheckUserdataClass(table, MyData.class); + throwsErrorReqCheckUserdataClass(thread, MyData.class); + assertEquals(sampleobject, userdataobj.checkuserdata(Object.class)); + assertEquals(sampleobject, userdataobj.checkuserdata()); + assertEquals(sampledata, userdatacls.checkuserdata(MyData.class)); + assertEquals(sampledata, userdatacls.checkuserdata(Object.class)); + assertEquals(sampledata, userdatacls.checkuserdata()); // should fail due to wrong class try { Object o = userdataobj.checkuserdata(MyData.class); - fail( "did not throw bad type error" ); - assertTrue( o instanceof MyData ); - } catch ( LuaError le ) { - assertEquals( "org.luaj.vm2.TypeTest$MyData expected, got userdata", le.getMessage() ); + fail("did not throw bad type error"); + assertTrue(o instanceof MyData); + } catch (LuaError le) { + assertEquals("org.luaj.vm2.TypeTest$MyData expected, got userdata", le.getMessage()); } } - + public void testCheckValue() { - throwsErrorReq( somenil, "checknotnil" ); - assertEquals( sometrue, sometrue.checknotnil() ); - assertEquals( somefalse, somefalse.checknotnil() ); - assertEquals( zero, zero.checknotnil() ); - assertEquals( intint, intint.checknotnil() ); - assertEquals( longdouble, longdouble.checknotnil() ); - assertEquals( somefunc, somefunc.checknotnil() ); - assertEquals( someclosure, someclosure.checknotnil() ); - assertEquals( stringstring, stringstring.checknotnil() ); - assertEquals( stringint, stringint.checknotnil() ); - assertEquals( stringlong, stringlong.checknotnil() ); - assertEquals( stringdouble, stringdouble.checknotnil() ); - assertEquals( thread, thread.checknotnil() ); - assertEquals( table, table.checknotnil() ); - assertEquals( userdataobj, userdataobj.checknotnil() ); - assertEquals( userdatacls, userdatacls.checknotnil() ); + throwsErrorReq(somenil, "checknotnil"); + assertEquals(sometrue, sometrue.checknotnil()); + assertEquals(somefalse, somefalse.checknotnil()); + assertEquals(zero, zero.checknotnil()); + assertEquals(intint, intint.checknotnil()); + assertEquals(longdouble, longdouble.checknotnil()); + assertEquals(somefunc, somefunc.checknotnil()); + assertEquals(someclosure, someclosure.checknotnil()); + assertEquals(stringstring, stringstring.checknotnil()); + assertEquals(stringint, stringint.checknotnil()); + assertEquals(stringlong, stringlong.checknotnil()); + assertEquals(stringdouble, stringdouble.checknotnil()); + assertEquals(thread, thread.checknotnil()); + assertEquals(table, table.checknotnil()); + assertEquals(userdataobj, userdataobj.checknotnil()); + assertEquals(userdatacls, userdatacls.checknotnil()); } - + } diff --git a/luaj-test/src/test/java/org/luaj/vm2/UTF8StreamTest.java b/luaj-test/src/test/java/org/luaj/vm2/UTF8StreamTest.java index 1d9f3d23..5940f138 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/UTF8StreamTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/UTF8StreamTest.java @@ -25,12 +25,10 @@ import junit.framework.TestCase; import org.luaj.vm2.lib.jse.JsePlatform; -public class UTF8StreamTest extends TestCase { +public class UTF8StreamTest extends TestCase { public void testUtf8CharsInStream() { - String script = "x = \"98\u00b0: today's temp!\"\n" - + "print('x = ', x)\n" - + "return x"; + 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/luaj-test/src/test/java/org/luaj/vm2/UnaryBinaryOperatorsTest.java b/luaj-test/src/test/java/org/luaj/vm2/UnaryBinaryOperatorsTest.java index 90bacd19..89a75426 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/UnaryBinaryOperatorsTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/UnaryBinaryOperatorsTest.java @@ -33,15 +33,15 @@ import org.luaj.vm2.lib.TwoArgFunction; public class UnaryBinaryOperatorsTest extends TestCase { LuaValue dummy; - + protected void setUp() throws Exception { super.setUp(); dummy = LuaValue.ZERO; } public void testEqualsBool() { - assertEquals(LuaValue.FALSE,LuaValue.FALSE); - assertEquals(LuaValue.TRUE,LuaValue.TRUE); + assertEquals(LuaValue.FALSE, LuaValue.FALSE); + assertEquals(LuaValue.TRUE, LuaValue.TRUE); assertTrue(LuaValue.FALSE.equals(LuaValue.FALSE)); assertTrue(LuaValue.TRUE.equals(LuaValue.TRUE)); assertTrue(!LuaValue.FALSE.equals(LuaValue.TRUE)); @@ -65,770 +65,975 @@ public class UnaryBinaryOperatorsTest extends TestCase { assertTrue(LuaValue.TRUE.toboolean()); assertFalse(LuaValue.FALSE.toboolean()); } - + public void testNot() { - LuaValue ia=LuaValue.valueOf(3); - LuaValue da=LuaValue.valueOf(.25); - LuaValue sa=LuaValue.valueOf("1.5"); - LuaValue ba=LuaValue.TRUE, bb=LuaValue.FALSE; - + LuaValue ia = LuaValue.valueOf(3); + LuaValue da = LuaValue.valueOf(.25); + LuaValue sa = LuaValue.valueOf("1.5"); + LuaValue ba = LuaValue.TRUE, bb = LuaValue.FALSE; + // like kinds - assertEquals(LuaValue.FALSE, ia.not()); - assertEquals(LuaValue.FALSE, da.not()); - assertEquals(LuaValue.FALSE, sa.not()); - assertEquals(LuaValue.FALSE, ba.not()); - assertEquals(LuaValue.TRUE, bb.not()); + assertEquals(LuaValue.FALSE, ia.not()); + assertEquals(LuaValue.FALSE, da.not()); + assertEquals(LuaValue.FALSE, sa.not()); + assertEquals(LuaValue.FALSE, ba.not()); + assertEquals(LuaValue.TRUE, bb.not()); } public void testNeg() { - LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(-4); - LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(-.5); - LuaValue sa=LuaValue.valueOf("1.5"), sb=LuaValue.valueOf("-2.0"); - + LuaValue ia = LuaValue.valueOf(3), ib = LuaValue.valueOf(-4); + LuaValue da = LuaValue.valueOf(.25), db = LuaValue.valueOf(-.5); + LuaValue sa = LuaValue.valueOf("1.5"), sb = LuaValue.valueOf("-2.0"); + // like kinds assertEquals(-3., ia.neg().todouble()); - assertEquals(-.25, da.neg().todouble()); - assertEquals(-1.5, sa.neg().todouble()); - assertEquals(4., ib.neg().todouble()); - assertEquals(.5, db.neg().todouble()); - assertEquals(2.0, sb.neg().todouble()); + assertEquals(-.25, da.neg().todouble()); + assertEquals(-1.5, sa.neg().todouble()); + assertEquals(4., ib.neg().todouble()); + assertEquals(.5, db.neg().todouble()); + assertEquals(2.0, sb.neg().todouble()); } - + public void testDoublesBecomeInts() { // DoubleValue.valueOf should return int - LuaValue ia=LuaInteger.valueOf(345), da=LuaDouble.valueOf(345.0), db=LuaDouble.valueOf(345.5); - LuaValue sa=LuaValue.valueOf("3.0"), sb=LuaValue.valueOf("3"), sc=LuaValue.valueOf("-2.0"), sd=LuaValue.valueOf("-2"); - - assertEquals(ia,da); + LuaValue ia = LuaInteger.valueOf(345), da = LuaDouble.valueOf(345.0), db = LuaDouble.valueOf(345.5); + LuaValue sa = LuaValue.valueOf("3.0"), sb = LuaValue.valueOf("3"), sc = LuaValue.valueOf("-2.0"), + sd = LuaValue.valueOf("-2"); + + assertEquals(ia, da); assertTrue(ia instanceof LuaInteger); assertTrue(da instanceof LuaInteger); assertTrue(db instanceof LuaDouble); - assertEquals( ia.toint(), 345 ); - assertEquals( da.toint(), 345 ); - assertEquals( da.todouble(), 345.0 ); - assertEquals( db.todouble(), 345.5 ); - + assertEquals(ia.toint(), 345); + assertEquals(da.toint(), 345); + assertEquals(da.todouble(), 345.0); + assertEquals(db.todouble(), 345.5); + assertTrue(sa instanceof LuaString); assertTrue(sb instanceof LuaString); assertTrue(sc instanceof LuaString); assertTrue(sd instanceof LuaString); - assertEquals( 3., sa.todouble() ); - assertEquals( 3., sb.todouble() ); - assertEquals( -2., sc.todouble() ); - assertEquals( -2., sd.todouble() ); - + assertEquals(3., sa.todouble()); + assertEquals(3., sb.todouble()); + assertEquals(-2., sc.todouble()); + assertEquals(-2., sd.todouble()); + } - public void testEqualsInt() { - LuaValue ia=LuaInteger.valueOf(345), ib=LuaInteger.valueOf(345), ic=LuaInteger.valueOf(-345); - LuaString sa=LuaString.valueOf("345"), sb=LuaString.valueOf("345"), sc=LuaString.valueOf("-345"); - + LuaValue ia = LuaInteger.valueOf(345), ib = LuaInteger.valueOf(345), ic = LuaInteger.valueOf(-345); + LuaString sa = LuaString.valueOf("345"), sb = LuaString.valueOf("345"), sc = LuaString.valueOf("-345"); + // objects should be different assertNotSame(ia, ib); assertSame(sa, sb); assertNotSame(ia, ic); assertNotSame(sa, sc); - + // assert equals for same type assertEquals(ia, ib); assertEquals(sa, sb); assertFalse(ia.equals(ic)); assertFalse(sa.equals(sc)); - + // check object equality for different types assertFalse(ia.equals(sa)); assertFalse(sa.equals(ia)); } - + public void testEqualsDouble() { - LuaValue da=LuaDouble.valueOf(345.5), db=LuaDouble.valueOf(345.5), dc=LuaDouble.valueOf(-345.5); - LuaString sa=LuaString.valueOf("345.5"), sb=LuaString.valueOf("345.5"), sc=LuaString.valueOf("-345.5"); - + LuaValue da = LuaDouble.valueOf(345.5), db = LuaDouble.valueOf(345.5), dc = LuaDouble.valueOf(-345.5); + LuaString sa = LuaString.valueOf("345.5"), sb = LuaString.valueOf("345.5"), sc = LuaString.valueOf("-345.5"); + // objects should be different assertNotSame(da, db); assertSame(sa, sb); assertNotSame(da, dc); assertNotSame(sa, sc); - + // assert equals for same type assertEquals(da, db); assertEquals(sa, sb); assertFalse(da.equals(dc)); assertFalse(sa.equals(sc)); - + // check object equality for different types assertFalse(da.equals(sa)); assertFalse(sa.equals(da)); } - + public void testEqInt() { - LuaValue ia=LuaInteger.valueOf(345), ib=LuaInteger.valueOf(345), ic=LuaInteger.valueOf(-123); - LuaValue sa=LuaString.valueOf("345"), sb=LuaString.valueOf("345"), sc=LuaString.valueOf("-345"); - + LuaValue ia = LuaInteger.valueOf(345), ib = LuaInteger.valueOf(345), ic = LuaInteger.valueOf(-123); + LuaValue sa = LuaString.valueOf("345"), sb = LuaString.valueOf("345"), sc = LuaString.valueOf("-345"); + // check arithmetic equality among same types - assertEquals(ia.eq(ib),LuaValue.TRUE); - assertEquals(sa.eq(sb),LuaValue.TRUE); - assertEquals(ia.eq(ic),LuaValue.FALSE); - assertEquals(sa.eq(sc),LuaValue.FALSE); + assertEquals(ia.eq(ib), LuaValue.TRUE); + assertEquals(sa.eq(sb), LuaValue.TRUE); + assertEquals(ia.eq(ic), LuaValue.FALSE); + assertEquals(sa.eq(sc), LuaValue.FALSE); // check arithmetic equality among different types - assertEquals(ia.eq(sa),LuaValue.FALSE); - assertEquals(sa.eq(ia),LuaValue.FALSE); + assertEquals(ia.eq(sa), LuaValue.FALSE); + assertEquals(sa.eq(ia), LuaValue.FALSE); // equals with mismatched types LuaValue t = new LuaTable(); - assertEquals(ia.eq(t),LuaValue.FALSE); - assertEquals(t.eq(ia),LuaValue.FALSE); - assertEquals(ia.eq(LuaValue.FALSE),LuaValue.FALSE); - assertEquals(LuaValue.FALSE.eq(ia),LuaValue.FALSE); - assertEquals(ia.eq(LuaValue.NIL),LuaValue.FALSE); - assertEquals(LuaValue.NIL.eq(ia),LuaValue.FALSE); + assertEquals(ia.eq(t), LuaValue.FALSE); + assertEquals(t.eq(ia), LuaValue.FALSE); + assertEquals(ia.eq(LuaValue.FALSE), LuaValue.FALSE); + assertEquals(LuaValue.FALSE.eq(ia), LuaValue.FALSE); + assertEquals(ia.eq(LuaValue.NIL), LuaValue.FALSE); + assertEquals(LuaValue.NIL.eq(ia), LuaValue.FALSE); } - + public void testEqDouble() { - LuaValue da=LuaDouble.valueOf(345.5), db=LuaDouble.valueOf(345.5), dc=LuaDouble.valueOf(-345.5); - LuaValue sa=LuaString.valueOf("345.5"), sb=LuaString.valueOf("345.5"), sc=LuaString.valueOf("-345.5"); - + LuaValue da = LuaDouble.valueOf(345.5), db = LuaDouble.valueOf(345.5), dc = LuaDouble.valueOf(-345.5); + LuaValue sa = LuaString.valueOf("345.5"), sb = LuaString.valueOf("345.5"), sc = LuaString.valueOf("-345.5"); + // check arithmetic equality among same types - assertEquals(da.eq(db),LuaValue.TRUE); - assertEquals(sa.eq(sb),LuaValue.TRUE); - assertEquals(da.eq(dc),LuaValue.FALSE); - assertEquals(sa.eq(sc),LuaValue.FALSE); + assertEquals(da.eq(db), LuaValue.TRUE); + assertEquals(sa.eq(sb), LuaValue.TRUE); + assertEquals(da.eq(dc), LuaValue.FALSE); + assertEquals(sa.eq(sc), LuaValue.FALSE); // check arithmetic equality among different types - assertEquals(da.eq(sa),LuaValue.FALSE); - assertEquals(sa.eq(da),LuaValue.FALSE); + assertEquals(da.eq(sa), LuaValue.FALSE); + assertEquals(sa.eq(da), LuaValue.FALSE); // equals with mismatched types LuaValue t = new LuaTable(); - assertEquals(da.eq(t),LuaValue.FALSE); - assertEquals(t.eq(da),LuaValue.FALSE); - assertEquals(da.eq(LuaValue.FALSE),LuaValue.FALSE); - assertEquals(LuaValue.FALSE.eq(da),LuaValue.FALSE); - assertEquals(da.eq(LuaValue.NIL),LuaValue.FALSE); - assertEquals(LuaValue.NIL.eq(da),LuaValue.FALSE); + assertEquals(da.eq(t), LuaValue.FALSE); + assertEquals(t.eq(da), LuaValue.FALSE); + assertEquals(da.eq(LuaValue.FALSE), LuaValue.FALSE); + assertEquals(LuaValue.FALSE.eq(da), LuaValue.FALSE); + assertEquals(da.eq(LuaValue.NIL), LuaValue.FALSE); + assertEquals(LuaValue.NIL.eq(da), LuaValue.FALSE); } - + private static final TwoArgFunction RETURN_NIL = new TwoArgFunction() { public LuaValue call(LuaValue lhs, LuaValue rhs) { return NIL; } }; - + private static final TwoArgFunction RETURN_ONE = new TwoArgFunction() { public LuaValue call(LuaValue lhs, LuaValue rhs) { return ONE; } }; - - + public void testEqualsMetatag() { LuaValue tru = LuaValue.TRUE; LuaValue fal = LuaValue.FALSE; LuaValue zer = LuaValue.ZERO; LuaValue one = LuaValue.ONE; - LuaValue abc = LuaValue.valueOf("abcdef").substring(0,3); - LuaValue def = LuaValue.valueOf("abcdef").substring(3,6); - LuaValue pi = LuaValue.valueOf(Math.PI); - LuaValue ee = LuaValue.valueOf(Math.E); + LuaValue abc = LuaValue.valueOf("abcdef").substring(0, 3); + LuaValue def = LuaValue.valueOf("abcdef").substring(3, 6); + LuaValue pi = LuaValue.valueOf(Math.PI); + LuaValue ee = LuaValue.valueOf(Math.E); LuaValue tbl = new LuaTable(); LuaValue tbl2 = new LuaTable(); LuaValue tbl3 = new LuaTable(); - LuaValue uda = new LuaUserdata(new Object()); - LuaValue udb = new LuaUserdata(uda.touserdata()); + LuaValue uda = new LuaUserdata(new Object()); + LuaValue udb = new LuaUserdata(uda.touserdata()); LuaValue uda2 = new LuaUserdata(new Object()); LuaValue uda3 = new LuaUserdata(uda.touserdata()); - LuaValue nilb = LuaValue.valueOf( LuaValue.NIL.toboolean() ); - LuaValue oneb = LuaValue.valueOf( LuaValue.ONE.toboolean() ); - assertEquals( LuaValue.FALSE, nilb ); - assertEquals( LuaValue.TRUE, oneb ); + LuaValue nilb = LuaValue.valueOf(LuaValue.NIL.toboolean()); + LuaValue oneb = LuaValue.valueOf(LuaValue.ONE.toboolean()); + assertEquals(LuaValue.FALSE, nilb); + assertEquals(LuaValue.TRUE, oneb); LuaValue smt = LuaString.s_metatable; try { // always return nil0 - LuaBoolean.s_metatable = LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } ); - LuaNumber.s_metatable = LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } ); - LuaString.s_metatable = LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } ); - tbl.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } )); - tbl2.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } )); - uda.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } )); + LuaBoolean.s_metatable = LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_NIL, }); + LuaNumber.s_metatable = LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_NIL, }); + LuaString.s_metatable = LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_NIL, }); + tbl.setmetatable(LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_NIL, })); + tbl2.setmetatable(LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_NIL, })); + uda.setmetatable(LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_NIL, })); udb.setmetatable(uda.getmetatable()); - uda2.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } )); + uda2.setmetatable(LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_NIL, })); // diff metatag function - tbl3.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } )); - uda3.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } )); - + tbl3.setmetatable(LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_ONE, })); + uda3.setmetatable(LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_ONE, })); + // primitive types or same valu do not invoke metatag as per C implementation - assertEquals( tru, tru.eq(tru) ); - assertEquals( tru, one.eq(one) ); - assertEquals( tru, abc.eq(abc) ); - assertEquals( tru, tbl.eq(tbl) ); - assertEquals( tru, uda.eq(uda) ); - assertEquals( tru, uda.eq(udb) ); - assertEquals( fal, tru.eq(fal) ); - assertEquals( fal, fal.eq(tru) ); - assertEquals( fal, zer.eq(one) ); - assertEquals( fal, one.eq(zer) ); - assertEquals( fal, pi.eq(ee) ); - assertEquals( fal, ee.eq(pi) ); - assertEquals( fal, pi.eq(one) ); - assertEquals( fal, one.eq(pi) ); - assertEquals( fal, abc.eq(def) ); - assertEquals( fal, def.eq(abc) ); + assertEquals(tru, tru.eq(tru)); + assertEquals(tru, one.eq(one)); + assertEquals(tru, abc.eq(abc)); + assertEquals(tru, tbl.eq(tbl)); + assertEquals(tru, uda.eq(uda)); + assertEquals(tru, uda.eq(udb)); + assertEquals(fal, tru.eq(fal)); + assertEquals(fal, fal.eq(tru)); + assertEquals(fal, zer.eq(one)); + assertEquals(fal, one.eq(zer)); + assertEquals(fal, pi.eq(ee)); + assertEquals(fal, ee.eq(pi)); + assertEquals(fal, pi.eq(one)); + assertEquals(fal, one.eq(pi)); + assertEquals(fal, abc.eq(def)); + assertEquals(fal, def.eq(abc)); // different types. not comparable - assertEquals( fal, fal.eq(tbl) ); - assertEquals( fal, tbl.eq(fal) ); - assertEquals( fal, tbl.eq(one) ); - assertEquals( fal, one.eq(tbl) ); - assertEquals( fal, fal.eq(one) ); - assertEquals( fal, one.eq(fal) ); - assertEquals( fal, abc.eq(one) ); - assertEquals( fal, one.eq(abc) ); - assertEquals( fal, tbl.eq(uda) ); - assertEquals( fal, uda.eq(tbl) ); + assertEquals(fal, fal.eq(tbl)); + assertEquals(fal, tbl.eq(fal)); + assertEquals(fal, tbl.eq(one)); + assertEquals(fal, one.eq(tbl)); + assertEquals(fal, fal.eq(one)); + assertEquals(fal, one.eq(fal)); + assertEquals(fal, abc.eq(one)); + assertEquals(fal, one.eq(abc)); + assertEquals(fal, tbl.eq(uda)); + assertEquals(fal, uda.eq(tbl)); // same type, same value, does not invoke metatag op - assertEquals( tru, tbl.eq(tbl) ); + assertEquals(tru, tbl.eq(tbl)); // same type, different value, same metatag op. comparabile via metatag op - assertEquals( nilb, tbl.eq(tbl2) ); - assertEquals( nilb, tbl2.eq(tbl) ); - assertEquals( nilb, uda.eq(uda2) ); - assertEquals( nilb, uda2.eq(uda) ); + assertEquals(nilb, tbl.eq(tbl2)); + assertEquals(nilb, tbl2.eq(tbl)); + assertEquals(nilb, uda.eq(uda2)); + assertEquals(nilb, uda2.eq(uda)); // same type, different metatag ops. not comparable - assertEquals( fal, tbl.eq(tbl3) ); - assertEquals( fal, tbl3.eq(tbl) ); - assertEquals( fal, uda.eq(uda3) ); - assertEquals( fal, uda3.eq(uda) ); + assertEquals(fal, tbl.eq(tbl3)); + assertEquals(fal, tbl3.eq(tbl)); + assertEquals(fal, uda.eq(uda3)); + assertEquals(fal, uda3.eq(uda)); // always use right argument - LuaBoolean.s_metatable = LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } ); - LuaNumber.s_metatable = LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } ); - LuaString.s_metatable = LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } ); - tbl.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } )); - tbl2.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } )); - uda.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } )); + LuaBoolean.s_metatable = LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_ONE, }); + LuaNumber.s_metatable = LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_ONE, }); + LuaString.s_metatable = LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_ONE, }); + tbl.setmetatable(LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_ONE, })); + tbl2.setmetatable(LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_ONE, })); + uda.setmetatable(LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_ONE, })); udb.setmetatable(uda.getmetatable()); - uda2.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_ONE, } )); + uda2.setmetatable(LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_ONE, })); // diff metatag function - tbl3.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } )); - uda3.setmetatable(LuaValue.tableOf( new LuaValue[] { LuaValue.EQ, RETURN_NIL, } )); - + tbl3.setmetatable(LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_NIL, })); + uda3.setmetatable(LuaValue.tableOf(new LuaValue[] { LuaValue.EQ, RETURN_NIL, })); + // primitive types or same value do not invoke metatag as per C implementation - assertEquals( tru, tru.eq(tru) ); - assertEquals( tru, one.eq(one) ); - assertEquals( tru, abc.eq(abc) ); - assertEquals( tru, tbl.eq(tbl) ); - assertEquals( tru, uda.eq(uda) ); - assertEquals( tru, uda.eq(udb) ); - assertEquals( fal, tru.eq(fal) ); - assertEquals( fal, fal.eq(tru) ); - assertEquals( fal, zer.eq(one) ); - assertEquals( fal, one.eq(zer) ); - assertEquals( fal, pi.eq(ee) ); - assertEquals( fal, ee.eq(pi) ); - assertEquals( fal, pi.eq(one) ); - assertEquals( fal, one.eq(pi) ); - assertEquals( fal, abc.eq(def) ); - assertEquals( fal, def.eq(abc) ); + assertEquals(tru, tru.eq(tru)); + assertEquals(tru, one.eq(one)); + assertEquals(tru, abc.eq(abc)); + assertEquals(tru, tbl.eq(tbl)); + assertEquals(tru, uda.eq(uda)); + assertEquals(tru, uda.eq(udb)); + assertEquals(fal, tru.eq(fal)); + assertEquals(fal, fal.eq(tru)); + assertEquals(fal, zer.eq(one)); + assertEquals(fal, one.eq(zer)); + assertEquals(fal, pi.eq(ee)); + assertEquals(fal, ee.eq(pi)); + assertEquals(fal, pi.eq(one)); + assertEquals(fal, one.eq(pi)); + assertEquals(fal, abc.eq(def)); + assertEquals(fal, def.eq(abc)); // different types. not comparable - assertEquals( fal, fal.eq(tbl) ); - assertEquals( fal, tbl.eq(fal) ); - assertEquals( fal, tbl.eq(one) ); - assertEquals( fal, one.eq(tbl) ); - assertEquals( fal, fal.eq(one) ); - assertEquals( fal, one.eq(fal) ); - assertEquals( fal, abc.eq(one) ); - assertEquals( fal, one.eq(abc) ); - assertEquals( fal, tbl.eq(uda) ); - assertEquals( fal, uda.eq(tbl) ); + assertEquals(fal, fal.eq(tbl)); + assertEquals(fal, tbl.eq(fal)); + assertEquals(fal, tbl.eq(one)); + assertEquals(fal, one.eq(tbl)); + assertEquals(fal, fal.eq(one)); + assertEquals(fal, one.eq(fal)); + assertEquals(fal, abc.eq(one)); + assertEquals(fal, one.eq(abc)); + assertEquals(fal, tbl.eq(uda)); + assertEquals(fal, uda.eq(tbl)); // same type, same value, does not invoke metatag op - assertEquals( tru, tbl.eq(tbl) ); + assertEquals(tru, tbl.eq(tbl)); // same type, different value, same metatag op. comparabile via metatag op - assertEquals( oneb, tbl.eq(tbl2) ); - assertEquals( oneb, tbl2.eq(tbl) ); - assertEquals( oneb, uda.eq(uda2) ); - assertEquals( oneb, uda2.eq(uda) ); + assertEquals(oneb, tbl.eq(tbl2)); + assertEquals(oneb, tbl2.eq(tbl)); + assertEquals(oneb, uda.eq(uda2)); + assertEquals(oneb, uda2.eq(uda)); // same type, different metatag ops. not comparable - assertEquals( fal, tbl.eq(tbl3) ); - assertEquals( fal, tbl3.eq(tbl) ); - assertEquals( fal, uda.eq(uda3) ); - assertEquals( fal, uda3.eq(uda) ); - - } finally { + assertEquals(fal, tbl.eq(tbl3)); + assertEquals(fal, tbl3.eq(tbl)); + assertEquals(fal, uda.eq(uda3)); + assertEquals(fal, uda3.eq(uda)); + + } finally { LuaBoolean.s_metatable = null; LuaNumber.s_metatable = null; LuaString.s_metatable = smt; } } - - + public void testAdd() { - LuaValue ia=LuaValue.valueOf(111), ib=LuaValue.valueOf(44); - LuaValue da=LuaValue.valueOf(55.25), db=LuaValue.valueOf(3.5); - LuaValue sa=LuaValue.valueOf("22.125"), sb=LuaValue.valueOf("7.25"); + LuaValue ia = LuaValue.valueOf(111), ib = LuaValue.valueOf(44); + LuaValue da = LuaValue.valueOf(55.25), db = LuaValue.valueOf(3.5); + LuaValue sa = LuaValue.valueOf("22.125"), sb = LuaValue.valueOf("7.25"); // check types - assertTrue( ia instanceof LuaInteger ); - assertTrue( ib instanceof LuaInteger ); - assertTrue( da instanceof LuaDouble ); - assertTrue( db instanceof LuaDouble ); - assertTrue( sa instanceof LuaString ); - assertTrue( sb instanceof LuaString ); - + assertTrue(ia instanceof LuaInteger); + assertTrue(ib instanceof LuaInteger); + assertTrue(da instanceof LuaDouble); + assertTrue(db instanceof LuaDouble); + assertTrue(sa instanceof LuaString); + assertTrue(sb instanceof LuaString); + // like kinds - assertEquals(155.0, ia.add(ib).todouble()); - assertEquals(58.75, da.add(db).todouble()); + assertEquals(155.0, ia.add(ib).todouble()); + assertEquals(58.75, da.add(db).todouble()); assertEquals(29.375, sa.add(sb).todouble()); - + // unlike kinds assertEquals(166.25, ia.add(da).todouble()); assertEquals(166.25, da.add(ia).todouble()); - assertEquals(133.125,ia.add(sa).todouble()); - assertEquals(133.125,sa.add(ia).todouble()); + assertEquals(133.125, ia.add(sa).todouble()); + assertEquals(133.125, sa.add(ia).todouble()); assertEquals(77.375, da.add(sa).todouble()); assertEquals(77.375, sa.add(da).todouble()); } - + public void testSub() { - LuaValue ia=LuaValue.valueOf(111), ib=LuaValue.valueOf(44); - LuaValue da=LuaValue.valueOf(55.25), db=LuaValue.valueOf(3.5); - LuaValue sa=LuaValue.valueOf("22.125"), sb=LuaValue.valueOf("7.25"); - + LuaValue ia = LuaValue.valueOf(111), ib = LuaValue.valueOf(44); + LuaValue da = LuaValue.valueOf(55.25), db = LuaValue.valueOf(3.5); + LuaValue sa = LuaValue.valueOf("22.125"), sb = LuaValue.valueOf("7.25"); + // like kinds - assertEquals(67.0, ia.sub(ib).todouble()); - assertEquals(51.75, da.sub(db).todouble()); - assertEquals(14.875, sa.sub(sb).todouble()); - + assertEquals(67.0, ia.sub(ib).todouble()); + assertEquals(51.75, da.sub(db).todouble()); + assertEquals(14.875, sa.sub(sb).todouble()); + // unlike kinds - assertEquals(55.75, ia.sub(da).todouble()); - assertEquals(-55.75, da.sub(ia).todouble()); - assertEquals(88.875, ia.sub(sa).todouble()); + assertEquals(55.75, ia.sub(da).todouble()); + assertEquals(-55.75, da.sub(ia).todouble()); + assertEquals(88.875, ia.sub(sa).todouble()); assertEquals(-88.875, sa.sub(ia).todouble()); - assertEquals(33.125, da.sub(sa).todouble()); - assertEquals(-33.125, sa.sub(da).todouble()); + assertEquals(33.125, da.sub(sa).todouble()); + assertEquals(-33.125, sa.sub(da).todouble()); } - + public void testMul() { - LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4); - LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(.5); - LuaValue sa=LuaValue.valueOf("1.5"), sb=LuaValue.valueOf("2.0"); - + LuaValue ia = LuaValue.valueOf(3), ib = LuaValue.valueOf(4); + LuaValue da = LuaValue.valueOf(.25), db = LuaValue.valueOf(.5); + LuaValue sa = LuaValue.valueOf("1.5"), sb = LuaValue.valueOf("2.0"); + // like kinds - assertEquals(12.0, ia.mul(ib).todouble()); - assertEquals(.125, da.mul(db).todouble()); - assertEquals(3.0, sa.mul(sb).todouble()); - + assertEquals(12.0, ia.mul(ib).todouble()); + assertEquals(.125, da.mul(db).todouble()); + assertEquals(3.0, sa.mul(sb).todouble()); + // unlike kinds - assertEquals(.75, ia.mul(da).todouble()); - assertEquals(.75, da.mul(ia).todouble()); - assertEquals(4.5, ia.mul(sa).todouble()); - assertEquals(4.5, sa.mul(ia).todouble()); - assertEquals(.375, da.mul(sa).todouble()); - assertEquals(.375, sa.mul(da).todouble()); + assertEquals(.75, ia.mul(da).todouble()); + assertEquals(.75, da.mul(ia).todouble()); + assertEquals(4.5, ia.mul(sa).todouble()); + assertEquals(4.5, sa.mul(ia).todouble()); + assertEquals(.375, da.mul(sa).todouble()); + assertEquals(.375, sa.mul(da).todouble()); } - + public void testDiv() { - LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4); - LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(.5); - LuaValue sa=LuaValue.valueOf("1.5"), sb=LuaValue.valueOf("2.0"); - + LuaValue ia = LuaValue.valueOf(3), ib = LuaValue.valueOf(4); + LuaValue da = LuaValue.valueOf(.25), db = LuaValue.valueOf(.5); + LuaValue sa = LuaValue.valueOf("1.5"), sb = LuaValue.valueOf("2.0"); + // like kinds - assertEquals(3./4., ia.div(ib).todouble()); - assertEquals(.25/.5, da.div(db).todouble()); - assertEquals(1.5/2., sa.div(sb).todouble()); - + assertEquals(3./4., ia.div(ib).todouble()); + assertEquals(.25/.5, da.div(db).todouble()); + assertEquals(1.5/2., sa.div(sb).todouble()); + // unlike kinds - assertEquals(3./.25, ia.div(da).todouble()); - assertEquals(.25/3., da.div(ia).todouble()); - assertEquals(3./1.5, ia.div(sa).todouble()); - assertEquals(1.5/3., sa.div(ia).todouble()); - assertEquals(.25/1.5, da.div(sa).todouble()); - assertEquals(1.5/.25, sa.div(da).todouble()); + assertEquals(3./.25, ia.div(da).todouble()); + assertEquals(.25/3., da.div(ia).todouble()); + assertEquals(3./1.5, ia.div(sa).todouble()); + assertEquals(1.5/3., sa.div(ia).todouble()); + assertEquals(.25/1.5, da.div(sa).todouble()); + assertEquals(1.5/.25, sa.div(da).todouble()); } - + public void testPow() { - LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4); - LuaValue da=LuaValue.valueOf(4.), db=LuaValue.valueOf(.5); - LuaValue sa=LuaValue.valueOf("1.5"), sb=LuaValue.valueOf("2.0"); - + LuaValue ia = LuaValue.valueOf(3), ib = LuaValue.valueOf(4); + LuaValue da = LuaValue.valueOf(4.), db = LuaValue.valueOf(.5); + LuaValue sa = LuaValue.valueOf("1.5"), sb = LuaValue.valueOf("2.0"); + // like kinds - assertEquals(Math.pow(3.,4.), ia.pow(ib).todouble()); - assertEquals(Math.pow(4.,.5), da.pow(db).todouble()); - assertEquals(Math.pow(1.5,2.), sa.pow(sb).todouble()); - + assertEquals(Math.pow(3., 4.), ia.pow(ib).todouble()); + assertEquals(Math.pow(4., .5), da.pow(db).todouble()); + assertEquals(Math.pow(1.5, 2.), sa.pow(sb).todouble()); + // unlike kinds - assertEquals(Math.pow(3.,4.), ia.pow(da).todouble()); - assertEquals(Math.pow(4.,3.), da.pow(ia).todouble()); - assertEquals(Math.pow(3.,1.5), ia.pow(sa).todouble()); - assertEquals(Math.pow(1.5,3.), sa.pow(ia).todouble()); - assertEquals(Math.pow(4.,1.5), da.pow(sa).todouble()); - assertEquals(Math.pow(1.5,4.), sa.pow(da).todouble()); + assertEquals(Math.pow(3., 4.), ia.pow(da).todouble()); + assertEquals(Math.pow(4., 3.), da.pow(ia).todouble()); + assertEquals(Math.pow(3., 1.5), ia.pow(sa).todouble()); + assertEquals(Math.pow(1.5, 3.), sa.pow(ia).todouble()); + assertEquals(Math.pow(4., 1.5), da.pow(sa).todouble()); + assertEquals(Math.pow(1.5, 4.), sa.pow(da).todouble()); } private static double luaMod(double x, double y) { - return y!=0? x-y*Math.floor(x/y): Double.NaN; + return y != 0? x-y*Math.floor(x/y): Double.NaN; } - + public void testMod() { - LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(-4); - LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(-.5); - LuaValue sa=LuaValue.valueOf("1.5"), sb=LuaValue.valueOf("-2.0"); - + LuaValue ia = LuaValue.valueOf(3), ib = LuaValue.valueOf(-4); + LuaValue da = LuaValue.valueOf(.25), db = LuaValue.valueOf(-.5); + LuaValue sa = LuaValue.valueOf("1.5"), sb = LuaValue.valueOf("-2.0"); + // like kinds - assertEquals(luaMod(3.,-4.), ia.mod(ib).todouble()); - assertEquals(luaMod(.25,-.5), da.mod(db).todouble()); - assertEquals(luaMod(1.5,-2.), sa.mod(sb).todouble()); - + assertEquals(luaMod(3., -4.), ia.mod(ib).todouble()); + assertEquals(luaMod(.25, -.5), da.mod(db).todouble()); + assertEquals(luaMod(1.5, -2.), sa.mod(sb).todouble()); + // unlike kinds - assertEquals(luaMod(3.,.25), ia.mod(da).todouble()); - assertEquals(luaMod(.25,3.), da.mod(ia).todouble()); - assertEquals(luaMod(3.,1.5), ia.mod(sa).todouble()); - assertEquals(luaMod(1.5,3.), sa.mod(ia).todouble()); - assertEquals(luaMod(.25,1.5), da.mod(sa).todouble()); - assertEquals(luaMod(1.5,.25), sa.mod(da).todouble()); + assertEquals(luaMod(3., .25), ia.mod(da).todouble()); + assertEquals(luaMod(.25, 3.), da.mod(ia).todouble()); + assertEquals(luaMod(3., 1.5), ia.mod(sa).todouble()); + assertEquals(luaMod(1.5, 3.), sa.mod(ia).todouble()); + assertEquals(luaMod(.25, 1.5), da.mod(sa).todouble()); + assertEquals(luaMod(1.5, .25), sa.mod(da).todouble()); } public void testArithErrors() { - LuaValue ia=LuaValue.valueOf(111), ib=LuaValue.valueOf(44); - LuaValue da=LuaValue.valueOf(55.25), db=LuaValue.valueOf(3.5); - LuaValue sa=LuaValue.valueOf("22.125"), sb=LuaValue.valueOf("7.25"); + LuaValue ia = LuaValue.valueOf(111), ib = LuaValue.valueOf(44); + LuaValue da = LuaValue.valueOf(55.25), db = LuaValue.valueOf(3.5); + LuaValue sa = LuaValue.valueOf("22.125"), sb = LuaValue.valueOf("7.25"); String[] ops = { "add", "sub", "mul", "div", "mod", "pow" }; LuaValue[] vals = { LuaValue.NIL, LuaValue.TRUE, LuaValue.tableOf() }; - LuaValue[] numerics = { LuaValue.valueOf(111), LuaValue.valueOf(55.25), LuaValue.valueOf("22.125") }; - for ( int i=0; i4., ia.gt(ib).toboolean()); - assertEquals(.25>.5, da.gt(db).toboolean()); - assertEquals(3.>4., ia.gt_b(ib)); - assertEquals(.25>.5, da.gt_b(db)); - + assertEquals(3. > 4., ia.gt(ib).toboolean()); + assertEquals(.25 > .5, da.gt(db).toboolean()); + assertEquals(3. > 4., ia.gt_b(ib)); + assertEquals(.25 > .5, da.gt_b(db)); + // unlike kinds - assertEquals(3.>.25, ia.gt(da).toboolean()); - assertEquals(.25>3., da.gt(ia).toboolean()); - assertEquals(3.>.25, ia.gt_b(da)); - assertEquals(.25>3., da.gt_b(ia)); + assertEquals(3. > .25, ia.gt(da).toboolean()); + assertEquals(.25 > 3., da.gt(ia).toboolean()); + assertEquals(3. > .25, ia.gt_b(da)); + assertEquals(.25 > 3., da.gt_b(ia)); } - + public void testGtEq() { - LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4); - LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(.5); - + LuaValue ia = LuaValue.valueOf(3), ib = LuaValue.valueOf(4); + LuaValue da = LuaValue.valueOf(.25), db = LuaValue.valueOf(.5); + // like kinds - assertEquals(3.>=4., ia.gteq(ib).toboolean()); - assertEquals(.25>=.5, da.gteq(db).toboolean()); - assertEquals(3.>=4., ia.gteq_b(ib)); - assertEquals(.25>=.5, da.gteq_b(db)); - + assertEquals(3. >= 4., ia.gteq(ib).toboolean()); + assertEquals(.25 >= .5, da.gteq(db).toboolean()); + assertEquals(3. >= 4., ia.gteq_b(ib)); + assertEquals(.25 >= .5, da.gteq_b(db)); + // unlike kinds - assertEquals(3.>=.25, ia.gteq(da).toboolean()); - assertEquals(.25>=3., da.gteq(ia).toboolean()); - assertEquals(3.>=.25, ia.gteq_b(da)); - assertEquals(.25>=3., da.gteq_b(ia)); + assertEquals(3. >= .25, ia.gteq(da).toboolean()); + assertEquals(.25 >= 3., da.gteq(ia).toboolean()); + assertEquals(3. >= .25, ia.gteq_b(da)); + assertEquals(.25 >= 3., da.gteq_b(ia)); } public void testNotEq() { - LuaValue ia=LuaValue.valueOf(3), ib=LuaValue.valueOf(4); - LuaValue da=LuaValue.valueOf(.25), db=LuaValue.valueOf(.5); - LuaValue sa=LuaValue.valueOf("1.5"), sb=LuaValue.valueOf("2.0"); - + LuaValue ia = LuaValue.valueOf(3), ib = LuaValue.valueOf(4); + LuaValue da = LuaValue.valueOf(.25), db = LuaValue.valueOf(.5); + LuaValue sa = LuaValue.valueOf("1.5"), sb = LuaValue.valueOf("2.0"); + // like kinds - assertEquals(3.!=4., ia.neq(ib).toboolean()); - assertEquals(.25!=.5, da.neq(db).toboolean()); - assertEquals(1.5!=2., sa.neq(sb).toboolean()); - assertEquals(3.!=4., ia.neq_b(ib)); - assertEquals(.25!=.5, da.neq_b(db)); - assertEquals(1.5!=2., sa.neq_b(sb)); - + assertEquals(3. != 4., ia.neq(ib).toboolean()); + assertEquals(.25 != .5, da.neq(db).toboolean()); + assertEquals(1.5 != 2., sa.neq(sb).toboolean()); + assertEquals(3. != 4., ia.neq_b(ib)); + assertEquals(.25 != .5, da.neq_b(db)); + assertEquals(1.5 != 2., sa.neq_b(sb)); + // unlike kinds - assertEquals(3.!=.25, ia.neq(da).toboolean()); - assertEquals(.25!=3., da.neq(ia).toboolean()); - assertEquals(3.!=1.5, ia.neq(sa).toboolean()); - assertEquals(1.5!=3., sa.neq(ia).toboolean()); - assertEquals(.25!=1.5, da.neq(sa).toboolean()); - assertEquals(1.5!=.25, sa.neq(da).toboolean()); - assertEquals(3.!=.25, ia.neq_b(da)); - assertEquals(.25!=3., da.neq_b(ia)); - assertEquals(3.!=1.5, ia.neq_b(sa)); - assertEquals(1.5!=3., sa.neq_b(ia)); - assertEquals(.25!=1.5, da.neq_b(sa)); - assertEquals(1.5!=.25, sa.neq_b(da)); + assertEquals(3. != .25, ia.neq(da).toboolean()); + assertEquals(.25 != 3., da.neq(ia).toboolean()); + assertEquals(3. != 1.5, ia.neq(sa).toboolean()); + assertEquals(1.5 != 3., sa.neq(ia).toboolean()); + assertEquals(.25 != 1.5, da.neq(sa).toboolean()); + assertEquals(1.5 != .25, sa.neq(da).toboolean()); + assertEquals(3. != .25, ia.neq_b(da)); + assertEquals(.25 != 3., da.neq_b(ia)); + assertEquals(3. != 1.5, ia.neq_b(sa)); + assertEquals(1.5 != 3., sa.neq_b(ia)); + assertEquals(.25 != 1.5, da.neq_b(sa)); + assertEquals(1.5 != .25, sa.neq_b(da)); } - public void testCompareErrors() { - LuaValue ia=LuaValue.valueOf(111), ib=LuaValue.valueOf(44); - LuaValue da=LuaValue.valueOf(55.25), db=LuaValue.valueOf(3.5); - LuaValue sa=LuaValue.valueOf("22.125"), sb=LuaValue.valueOf("7.25"); + LuaValue ia = LuaValue.valueOf(111), ib = LuaValue.valueOf(44); + LuaValue da = LuaValue.valueOf(55.25), db = LuaValue.valueOf(3.5); + LuaValue sa = LuaValue.valueOf("22.125"), sb = LuaValue.valueOf("7.25"); - String[] ops = { "lt", "lteq", }; + String[] ops = { "lt", "lteq", }; LuaValue[] vals = { LuaValue.NIL, LuaValue.TRUE, LuaValue.tableOf() }; - LuaValue[] numerics = { LuaValue.valueOf(111), LuaValue.valueOf(55.25), LuaValue.valueOf("22.125") }; - for ( int i=0; i= 0) - baos.write(buffer, 0, n); - is.close(); - return baos.toByteArray(); - } + // re-undump + Prototype p2 = loadFromBytes(dumped, file); + String actual2 = protoToString(p2); - protected Prototype loadFromBytes(byte[] bytes, String script) - throws IOException { - InputStream is = new ByteArrayInputStream(bytes); - return globals.loadPrototype(is, script, "b"); - } + // compare again + assertEquals(actual, actual2); - protected String protoToString(Prototype p) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - PrintStream ps = new PrintStream(baos); - Print.ps = ps; - new Print().printFunction(p, true); - return baos.toString(); - } + } catch (IOException e) { + fail(e.toString()); + } + } + + protected byte[] bytesFromJar(String path) throws IOException { + InputStream is = inputStreamOfPath(path); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[2048]; + int n; + while ( (n = is.read(buffer)) >= 0 ) + baos.write(buffer, 0, n); + is.close(); + return baos.toByteArray(); + } + + protected Prototype loadFromBytes(byte[] bytes, String script) throws IOException { + InputStream is = new ByteArrayInputStream(bytes); + return globals.loadPrototype(is, script, "b"); + } + + protected String protoToString(Prototype p) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(baos); + Print.ps = ps; + new Print().printFunction(p, true); + return baos.toString(); + } } diff --git a/luaj-test/src/test/java/org/luaj/vm2/compiler/CompilerUnitTests.java b/luaj-test/src/test/java/org/luaj/vm2/compiler/CompilerUnitTests.java index 1cdea93d..933c72a3 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/compiler/CompilerUnitTests.java +++ b/luaj-test/src/test/java/org/luaj/vm2/compiler/CompilerUnitTests.java @@ -1,38 +1,62 @@ package org.luaj.vm2.compiler; - - public class CompilerUnitTests extends AbstractUnitTests { - public CompilerUnitTests() { - super("test/lua", "luaj3.0-tests.zip", "lua5.2.1-tests"); - } + public CompilerUnitTests() { + super("test/lua", "luaj3.0-tests.zip", "lua5.2.1-tests"); + } + + public void testAll() { doTest("all.lua"); } + + public void testApi() { doTest("api.lua"); } + + public void testAttrib() { doTest("attrib.lua"); } + + public void testBig() { doTest("big.lua"); } + + public void testBitwise() { doTest("bitwise.lua"); } + + public void testCalls() { doTest("calls.lua"); } - public void testAll() { doTest("all.lua"); } - public void testApi() { doTest("api.lua"); } - public void testAttrib() { doTest("attrib.lua"); } - public void testBig() { doTest("big.lua"); } - public void testBitwise() { doTest("bitwise.lua"); } - public void testCalls() { doTest("calls.lua"); } public void testChecktable() { doTest("checktable.lua"); } - public void testClosure() { doTest("closure.lua"); } - public void testCode() { doTest("code.lua"); } - public void testConstruct() { doTest("constructs.lua"); } - public void testCoroutine() { doTest("coroutine.lua"); } - public void testDb() { doTest("db.lua"); } - public void testErrors() { doTest("errors.lua"); } - public void testEvents() { doTest("events.lua"); } - public void testFiles() { doTest("files.lua"); } - public void testGc() { doTest("gc.lua"); } - public void testGoto() { doTest("goto.lua"); } - public void testLiterals() { doTest("literals.lua"); } - public void testLocals() { doTest("locals.lua"); } - public void testMain() { doTest("main.lua"); } - public void testMath() { doTest("math.lua"); } - public void testNextvar() { doTest("nextvar.lua"); } - public void testPm() { doTest("pm.lua"); } - public void testSort() { doTest("sort.lua"); } - public void testStrings() { doTest("strings.lua"); } - public void testVararg() { doTest("vararg.lua"); } - public void testVerybig() { doTest("verybig.lua"); } + + public void testClosure() { doTest("closure.lua"); } + + public void testCode() { doTest("code.lua"); } + + public void testConstruct() { doTest("constructs.lua"); } + + public void testCoroutine() { doTest("coroutine.lua"); } + + public void testDb() { doTest("db.lua"); } + + public void testErrors() { doTest("errors.lua"); } + + public void testEvents() { doTest("events.lua"); } + + public void testFiles() { doTest("files.lua"); } + + public void testGc() { doTest("gc.lua"); } + + public void testGoto() { doTest("goto.lua"); } + + public void testLiterals() { doTest("literals.lua"); } + + public void testLocals() { doTest("locals.lua"); } + + public void testMain() { doTest("main.lua"); } + + public void testMath() { doTest("math.lua"); } + + public void testNextvar() { doTest("nextvar.lua"); } + + public void testPm() { doTest("pm.lua"); } + + public void testSort() { doTest("sort.lua"); } + + public void testStrings() { doTest("strings.lua"); } + + public void testVararg() { doTest("vararg.lua"); } + + public void testVerybig() { doTest("verybig.lua"); } } diff --git a/luaj-test/src/test/java/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java b/luaj-test/src/test/java/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java index 69437a58..0766489e 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/compiler/DumpLoadEndianIntTest.java @@ -19,119 +19,121 @@ import org.luaj.vm2.LuaValue; import org.luaj.vm2.Prototype; import org.luaj.vm2.lib.jse.JsePlatform; - public class DumpLoadEndianIntTest extends TestCase { 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 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; + private Globals globals; - protected void setUp() throws Exception { - super.setUp(); - globals = JsePlatform.standardGlobals(); - DumpState.ALLOW_INTEGER_CASTING = false; - } + protected void setUp() throws Exception { + super.setUp(); + globals = JsePlatform.standardGlobals(); + DumpState.ALLOW_INTEGER_CASTING = false; + } public 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 ); + 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); } - - public 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 ); - } - - public 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 ); - } - - public 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 ); - } - - public 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 ); - } - - public 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 ); - } - - public 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()); - } + public 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); + } + + public 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); + } + + public 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); + } + + public 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); + } + + public 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); + } + + public 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-test/src/test/java/org/luaj/vm2/compiler/LuaParserTests.java b/luaj-test/src/test/java/org/luaj/vm2/compiler/LuaParserTests.java index 3c9c9d21..d40fcbc0 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/compiler/LuaParserTests.java +++ b/luaj-test/src/test/java/org/luaj/vm2/compiler/LuaParserTests.java @@ -9,11 +9,11 @@ import org.luaj.vm2.parser.LuaParser; public class LuaParserTests extends CompilerUnitTests { - protected void setUp() throws Exception { - super.setUp(); - LuaValue.valueOf(true); - } - + protected void setUp() throws Exception { + super.setUp(); + LuaValue.valueOf(true); + } + protected void doTest(String file) { try { InputStream is = inputStreamOfFile(file); diff --git a/luaj-test/src/test/java/org/luaj/vm2/compiler/RegressionTests.java b/luaj-test/src/test/java/org/luaj/vm2/compiler/RegressionTests.java index 8e07a2a7..5a3ff5b3 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/compiler/RegressionTests.java +++ b/luaj-test/src/test/java/org/luaj/vm2/compiler/RegressionTests.java @@ -3,28 +3,32 @@ package org.luaj.vm2.compiler; /** * 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 + * 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. + * After adding a test, check in the zip file rather than the individual + * regression test files. * * @author jrosebor */ public class RegressionTests extends AbstractUnitTests { - + public RegressionTests() { - super( "test/lua", "luaj3.0-tests.zip", "regressions" ); + super("test/lua", "luaj3.0-tests.zip", "regressions"); } - - public void testModulo() { doTest("modulo.lua"); } - public void testConstruct() { doTest("construct.lua"); } - public void testBigAttrs() { doTest("bigattr.lua"); } - public void testControlChars() { doTest("controlchars.lua"); } - public void testComparators() { doTest("comparators.lua"); } - public void testMathRandomseed() { doTest("mathrandomseed.lua"); } - public void testVarargs() { doTest("varargs.lua"); } + + public void testModulo() { doTest("modulo.lua"); } + + public void testConstruct() { doTest("construct.lua"); } + + public void testBigAttrs() { doTest("bigattr.lua"); } + + public void testControlChars() { doTest("controlchars.lua"); } + + public void testComparators() { doTest("comparators.lua"); } + + public void testMathRandomseed() { doTest("mathrandomseed.lua"); } + + public void testVarargs() { doTest("varargs.lua"); } } diff --git a/luaj-test/src/test/java/org/luaj/vm2/compiler/SimpleTests.java b/luaj-test/src/test/java/org/luaj/vm2/compiler/SimpleTests.java index 993a9861..d4b40deb 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/compiler/SimpleTests.java +++ b/luaj-test/src/test/java/org/luaj/vm2/compiler/SimpleTests.java @@ -12,85 +12,73 @@ public class SimpleTests extends TestCase { private Globals globals; - protected void setUp() throws Exception { - super.setUp(); - globals = JsePlatform.standardGlobals(); - } + protected void setUp() throws Exception { + super.setUp(); + globals = JsePlatform.standardGlobals(); + } - private void doTest( String script ) { - try { + private void doTest(String script) { + try { LuaValue c = globals.load(script, "script"); c.call(); - } catch ( Exception e ) { - fail("i/o exception: "+e ); - } - } + } catch (Exception e) { + fail("i/o exception: " + e); + } + } - public void testTrivial() { + public void testTrivial() { String s = "print( 2 )\n"; - doTest( s ); + doTest(s); } - + public void testAlmostTrivial() { - String s = "print( 2 )\n" + - "print( 3 )\n"; - doTest( s ); + String s = "print( 2 )\n" + "print( 3 )\n"; + doTest(s); } - + public void testSimple() { - String s = "print( 'hello, world' )\n"+ - "for i = 2,4 do\n" + - " print( 'i', i )\n" + - "end\n"; - doTest( s ); + String s = "print( 'hello, world' )\n" + "for i = 2,4 do\n" + " print( 'i', i )\n" + "end\n"; + doTest(s); } - + public 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 ); + 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); } - + public void testShebang() { - String s = "#!../lua\n"+ - "print( 2 )\n"; - doTest( s ); + String s = "#!../lua\n" + "print( 2 )\n"; + doTest(s); } - + public void testInlineTable() { - String s = "A = {g=10}\n"+ - "print( A )\n"; - doTest( s ); + String s = "A = {g=10}\n" + "print( A )\n"; + doTest(s); } public void testEqualsAnd() { String s = "print( 1 == b and b )\n"; - doTest( s ); + 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 }; - + + 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 }; + public void testDoubleHashCode() { - for ( int i=0; i=0 ); + assertEquals(LuaValue.FALSE, status); + int index = message.toString().indexOf("this is some message"); + assertTrue("bad message: " + message, index >= 0); } public void testLuaErrorCause() { - String script = "luajava.bindClass( \""+SomeClass.class.getName()+"\"):someMethod()"; + 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 ) { + fail("call should not have succeeded"); + } catch (LuaError lee) { Throwable c = lee.getCause(); - assertEquals( SomeException.class, c.getClass() ); + assertEquals(SomeException.class, c.getClass()); } } - + public interface VarArgsInterface { - public String varargsMethod( String a, String ... v ); - public String arrayargsMethod( String a, String[] v ); + public String varargsMethod(String a, String... v); + + public String arrayargsMethod(String a, String[] v); } - - public 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"; + + public 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() ); + 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) ); + 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)); } - + public 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" + + 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() ); + 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 ); + 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 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 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 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 { - } - - public void testOverloadedJavaMethodObject() { doOverloadedMethodTest( "Object", "" ); } - public void testOverloadedJavaMethodString() { doOverloadedMethodTest( "String", "abc" ); } - public void testOverloadedJavaMethodA() { doOverloadedMethodTest( "A", "" ); } - public void testOverloadedJavaMethodB() { doOverloadedMethodTest( "B", "" ); } - public void testOverloadedJavaMethodC() { doOverloadedMethodTest( "C", "" ); } - public void testOverloadedJavaMethodByte() { doOverloadedMethodTest( "byte", "1" ); } - public void testOverloadedJavaMethodChar() { doOverloadedMethodTest( "char", "65000" ); } - public void testOverloadedJavaMethodShort() { doOverloadedMethodTest( "short", "-32000" ); } - public void testOverloadedJavaMethodInt() { doOverloadedMethodTest( "int", "100000" ); } - public void testOverloadedJavaMethodLong() { doOverloadedMethodTest( "long", "50000000000" ); } - public void testOverloadedJavaMethodFloat() { doOverloadedMethodTest( "float", "6.5" ); } - public 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"; + public static class C extends B implements IC { + } + + public static class D extends C implements IA { + } + + public void testOverloadedJavaMethodObject() { doOverloadedMethodTest("Object", ""); } + + public void testOverloadedJavaMethodString() { doOverloadedMethodTest("String", "abc"); } + + public void testOverloadedJavaMethodA() { doOverloadedMethodTest("A", ""); } + + public void testOverloadedJavaMethodB() { doOverloadedMethodTest("B", ""); } + + public void testOverloadedJavaMethodC() { doOverloadedMethodTest("C", ""); } + + public void testOverloadedJavaMethodByte() { doOverloadedMethodTest("byte", "1"); } + + public void testOverloadedJavaMethodChar() { doOverloadedMethodTest("char", "65000"); } + + public void testOverloadedJavaMethodShort() { doOverloadedMethodTest("short", "-32000"); } + + public void testOverloadedJavaMethodInt() { doOverloadedMethodTest("int", "100000"); } + + public void testOverloadedJavaMethodLong() { doOverloadedMethodTest("long", "50000000000"); } + + public void testOverloadedJavaMethodFloat() { doOverloadedMethodTest("float", "6.5"); } + + public 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() ); + if (!chunk.arg1().toboolean()) + fail(chunk.arg(2).toString()); Varargs results = chunk.arg1().invoke(); int nresults = results.narg(); - assertEquals( 2, nresults ); + 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 ); + assertEquals("set(" + typename + ") " + value, sb); + assertEquals("setr(" + typename + ") " + value, sc); } public 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) ); - } - - public 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(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(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) ); + 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)); + } + + public 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)); } public void testCoerceJavaToLuaLuaValue() { @@ -443,4 +490,3 @@ public class LuaJavaCoercionTest extends TestCase { assertEquals(LuaValue.valueOf("abcd"), value); } } - diff --git a/luaj-test/src/test/java/org/luaj/vm2/lib/jse/LuajavaAccessibleMembersTest.java b/luaj-test/src/test/java/org/luaj/vm2/lib/jse/LuajavaAccessibleMembersTest.java index 3a86a8e6..4f88e67e 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/lib/jse/LuajavaAccessibleMembersTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/lib/jse/LuajavaAccessibleMembersTest.java @@ -6,63 +6,52 @@ import org.luaj.vm2.Globals; import org.luaj.vm2.LuaValue; public class LuajavaAccessibleMembersTest extends TestCase { - + private Globals globals; - protected void setUp() throws Exception { - super.setUp(); - globals = JsePlatform.standardGlobals(); - } + protected void setUp() throws Exception { + super.setUp(); + globals = JsePlatform.standardGlobals(); + } - private String invokeScript(String script) { - try { + private String invokeScript(String script) { + try { LuaValue c = globals.load(script, "script"); return c.call().tojstring(); - } catch ( Exception e ) { - fail("exception: "+e ); - return "failed"; - } - } - + } catch (Exception e) { + fail("exception: " + e); + return "failed"; + } + } + public 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');")); + assertEquals("privateImpl-aaa-interface_method(bar)", + invokeScript("b = luajava.newInstance('" + TestClass.class.getName() + "');" + + "a = b:create_PrivateImpl('aaa');" + "return a:interface_method('bar');")); } public void testAccessFromPrivateClassPublicMethod() { - assertEquals("privateImpl-aaa-public_method", invokeScript( - "b = luajava.newInstance('"+TestClass.class.getName()+"');" + - "a = b:create_PrivateImpl('aaa');" + - "return a:public_method();")); + assertEquals("privateImpl-aaa-public_method", invokeScript("b = luajava.newInstance('" + + TestClass.class.getName() + "');" + "a = b:create_PrivateImpl('aaa');" + "return a:public_method();")); } public void testAccessFromPrivateClassGetPublicField() { - assertEquals("aaa", invokeScript( - "b = luajava.newInstance('"+TestClass.class.getName()+"');" + - "a = b:create_PrivateImpl('aaa');" + - "return a.public_field;")); + assertEquals("aaa", invokeScript("b = luajava.newInstance('" + TestClass.class.getName() + "');" + + "a = b:create_PrivateImpl('aaa');" + "return a.public_field;")); } public void testAccessFromPrivateClassSetPublicField() { - assertEquals("foo", invokeScript( - "b = luajava.newInstance('"+TestClass.class.getName()+"');" + - "a = b:create_PrivateImpl('aaa');" + - "a.public_field = 'foo';" + - "return a.public_field;")); + assertEquals("foo", invokeScript("b = luajava.newInstance('" + TestClass.class.getName() + "');" + + "a = b:create_PrivateImpl('aaa');" + "a.public_field = 'foo';" + "return a.public_field;")); } public void testAccessFromPrivateClassPublicConstructor() { - assertEquals("privateImpl-constructor", invokeScript( - "b = luajava.newInstance('"+TestClass.class.getName()+"');" + - "c = b:get_PrivateImplClass();" + - "return luajava.new(c);")); + assertEquals("privateImpl-constructor", invokeScript("b = luajava.newInstance('" + TestClass.class.getName() + + "');" + "c = b:get_PrivateImplClass();" + "return luajava.new(c);")); } public void testAccessPublicEnum() { - assertEquals("class org.luaj.vm2.lib.jse.TestClass$SomeEnum", invokeScript( - "b = luajava.newInstance('"+TestClass.class.getName()+"');" + - "return b.SomeEnum")); + assertEquals("class org.luaj.vm2.lib.jse.TestClass$SomeEnum", + invokeScript("b = luajava.newInstance('" + TestClass.class.getName() + "');" + "return b.SomeEnum")); } } diff --git a/luaj-test/src/test/java/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java b/luaj-test/src/test/java/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java index 496adffe..54a48cbc 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/lib/jse/LuajavaClassMembersTest.java @@ -6,172 +6,221 @@ import org.luaj.vm2.LuaError; import org.luaj.vm2.LuaValue; public class LuajavaClassMembersTest extends TestCase { - public static class A { + public static class A { protected A() {} } + public static class B extends A { - public byte m_byte_field; - public int m_int_field; + 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 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 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; } + public int getint() { return 200000; } - public String pick(String s) { return "class-c-pick(string:"+s+")"; } - public String pick(int i) { return "class-c-pick(int:"+i+")"; } + public String pick(String s) { return "class-c-pick(string:" + s + ")"; } + + public String pick(int i) { return "class-c-pick(int:" + i + ")"; } + public static class D { - public static String name() { return "name-of-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 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 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()); - + public 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") ); - } + 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")); + } + public 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") ); + 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")); } + public void testNoFactory() { JavaClass c = JavaClass.forClass(A.class); try { c.call(); - fail( "did not throw lua error as expected" ); - } catch ( LuaError e ) { + fail("did not throw lua error as expected"); + } catch (LuaError e) { } } + public void testUniqueFactoryCoercible() { JavaClass c = JavaClass.forClass(B.class); - assertEquals( JavaClass.class, c.getClass() ); + assertEquals(JavaClass.class, c.getClass()); LuaValue constr = c.get("new"); - assertEquals( JavaConstructor.class, constr.getClass() ); + 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 ); + 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 ); + assertEquals(B.class, b0.getClass()); + assertEquals(0, ((B) b0).m_int_field); } + public void testUniqueFactoryUncoercible() { JavaClass f = JavaClass.forClass(B.class); LuaValue constr = f.get("new"); - assertEquals( JavaConstructor.class, constr.getClass() ); - try { + 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 ) { + assertEquals(0, ((B) b).m_int_field); + } catch (LuaError e) { } } + public void testOverloadedFactoryCoercible() { JavaClass f = JavaClass.forClass(C.class); LuaValue constr = f.get("new"); - assertEquals( JavaConstructor.Overload.class, constr.getClass() ); + 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 ); + 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); } + public void testOverloadedFactoryUncoercible() { JavaClass f = JavaClass.forClass(C.class); - try { - Object c = f.call(LuaValue.userdataOf(new Object())); + 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 ) { + assertEquals(0, ((C) c).m_int_field); + assertEquals(null, ((C) c).m_string_field); + } catch (LuaError e) { } } - + public 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 ) {} + assertEquals(v, LuaValue.NIL); + try { + f.set("bogus", ONE); + fail("did not throw lua error as expected"); + } catch (LuaError e) { + } } + public 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.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() ); + 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()); } + public 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()); + 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()); } + public void testUniqueMethodAttributeArgsCoercible() { B b = new B(); JavaInstance ib = new JavaInstance(b); @@ -180,52 +229,60 @@ public class LuajavaClassMembersTest extends TestCase { 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() ); + 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()); } + public 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() ); + 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()); } + public 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() ); + 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()); } + public 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() ); + 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()); } + public void testGetInnerClass() { C c = new C(); JavaInstance ic = new JavaInstance(c); diff --git a/luaj-test/src/test/java/org/luaj/vm2/lib/jse/OsLibTest.java b/luaj-test/src/test/java/org/luaj/vm2/lib/jse/OsLibTest.java index 6c698acc..54b498cb 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/lib/jse/OsLibTest.java +++ b/luaj-test/src/test/java/org/luaj/vm2/lib/jse/OsLibTest.java @@ -10,53 +10,85 @@ public class OsLibTest extends TestCase { LuaValue jme_lib; LuaValue jse_lib; - double time; - + double time; + public void setUp() { - jse_lib = JsePlatform.standardGlobals().get("os");; - jme_lib = JmePlatform.standardGlobals().get("os");; - time = new java.util.Date(2001-1900, 7, 23, 14, 55, 02).getTime() / 1000.0; + jse_lib = JsePlatform.standardGlobals().get("os"); + ; + jme_lib = JmePlatform.standardGlobals().get("os"); + ; + time = new java.util.Date(2001-1900, 7, 23, 14, 55, 02).getTime()/1000.0; } void t(String format, String expected) { String actual = jme_lib.get("date").call(LuaValue.valueOf(format), LuaValue.valueOf(time)).tojstring(); assertEquals(expected, actual); } - - public void testStringDateChars() { t("foo", "foo"); } - public void testStringDate_a() { t("%a", "Thu"); } - public void testStringDate_A() { t("%A", "Thursday"); } - public void testStringDate_b() { t("%b", "Aug"); } - public void testStringDate_B() { t("%B", "August"); } - public void testStringDate_c() { t("%c", "Thu Aug 23 14:55:02 2001"); } - public void testStringDate_d() { t("%d", "23"); } - public void testStringDate_H() { t("%H", "14"); } - public void testStringDate_I() { t("%I", "02"); } - public void testStringDate_j() { t("%j", "235"); } - public void testStringDate_m() { t("%m", "08"); } - public void testStringDate_M() { t("%M", "55"); } - public void testStringDate_p() { t("%p", "PM"); } - public void testStringDate_S() { t("%S", "02"); } - public void testStringDate_U() { t("%U", "33"); } - public void testStringDate_w() { t("%w", "4"); } - public void testStringDate_W() { t("%W", "34"); } - public void testStringDate_x() { t("%x", "08/23/01"); } - public void testStringDate_X() { t("%X", "14:55:02"); } - public void testStringDate_y() { t("%y", "01"); } - public void testStringDate_Y() { t("%Y", "2001"); } - public void testStringDate_Pct() { t("%%", "%"); } - static final double DAY = 24. * 3600.; - public void testStringDate_UW_neg4() { time-=4*DAY; t("%c %U %W", "Sun Aug 19 14:55:02 2001 33 33"); } - public void testStringDate_UW_neg3() { time-=3*DAY; t("%c %U %W", "Mon Aug 20 14:55:02 2001 33 34"); } - public void testStringDate_UW_neg2() { time-=2*DAY; t("%c %U %W", "Tue Aug 21 14:55:02 2001 33 34"); } - public void testStringDate_UW_neg1() { time-=DAY; t("%c %U %W", "Wed Aug 22 14:55:02 2001 33 34"); } - public void testStringDate_UW_pos0() { time+=0; t("%c %U %W", "Thu Aug 23 14:55:02 2001 33 34"); } - public void testStringDate_UW_pos1() { time+=DAY; t("%c %U %W", "Fri Aug 24 14:55:02 2001 33 34"); } - public void testStringDate_UW_pos2() { time+=2*DAY; t("%c %U %W", "Sat Aug 25 14:55:02 2001 33 34"); } - public void testStringDate_UW_pos3() { time+=3*DAY; t("%c %U %W", "Sun Aug 26 14:55:02 2001 34 34"); } - public void testStringDate_UW_pos4() { time+=4*DAY; t("%c %U %W", "Mon Aug 27 14:55:02 2001 34 35"); } - + public void testStringDateChars() { t("foo", "foo"); } + + public void testStringDate_a() { t("%a", "Thu"); } + + public void testStringDate_A() { t("%A", "Thursday"); } + + public void testStringDate_b() { t("%b", "Aug"); } + + public void testStringDate_B() { t("%B", "August"); } + + public void testStringDate_c() { t("%c", "Thu Aug 23 14:55:02 2001"); } + + public void testStringDate_d() { t("%d", "23"); } + + public void testStringDate_H() { t("%H", "14"); } + + public void testStringDate_I() { t("%I", "02"); } + + public void testStringDate_j() { t("%j", "235"); } + + public void testStringDate_m() { t("%m", "08"); } + + public void testStringDate_M() { t("%M", "55"); } + + public void testStringDate_p() { t("%p", "PM"); } + + public void testStringDate_S() { t("%S", "02"); } + + public void testStringDate_U() { t("%U", "33"); } + + public void testStringDate_w() { t("%w", "4"); } + + public void testStringDate_W() { t("%W", "34"); } + + public void testStringDate_x() { t("%x", "08/23/01"); } + + public void testStringDate_X() { t("%X", "14:55:02"); } + + public void testStringDate_y() { t("%y", "01"); } + + public void testStringDate_Y() { t("%Y", "2001"); } + + public void testStringDate_Pct() { t("%%", "%"); } + + static final double DAY = 24.*3600.; + + public void testStringDate_UW_neg4() { time -= 4*DAY; t("%c %U %W", "Sun Aug 19 14:55:02 2001 33 33"); } + + public void testStringDate_UW_neg3() { time -= 3*DAY; t("%c %U %W", "Mon Aug 20 14:55:02 2001 33 34"); } + + public void testStringDate_UW_neg2() { time -= 2*DAY; t("%c %U %W", "Tue Aug 21 14:55:02 2001 33 34"); } + + public void testStringDate_UW_neg1() { time -= DAY; t("%c %U %W", "Wed Aug 22 14:55:02 2001 33 34"); } + + public void testStringDate_UW_pos0() { time += 0; t("%c %U %W", "Thu Aug 23 14:55:02 2001 33 34"); } + + public void testStringDate_UW_pos1() { time += DAY; t("%c %U %W", "Fri Aug 24 14:55:02 2001 33 34"); } + + public void testStringDate_UW_pos2() { time += 2*DAY; t("%c %U %W", "Sat Aug 25 14:55:02 2001 33 34"); } + + public void testStringDate_UW_pos3() { time += 3*DAY; t("%c %U %W", "Sun Aug 26 14:55:02 2001 34 34"); } + + public void testStringDate_UW_pos4() { time += 4*DAY; t("%c %U %W", "Mon Aug 27 14:55:02 2001 34 35"); } + public void testJseOsGetenvForEnvVariables() { LuaValue USER = LuaValue.valueOf("USER"); LuaValue jse_user = jse_lib.get("getenv").call(USER); diff --git a/luaj-test/src/test/java/org/luaj/vm2/lib/jse/TestClass.java b/luaj-test/src/test/java/org/luaj/vm2/lib/jse/TestClass.java index dc57bc4b..4e8e2931 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/lib/jse/TestClass.java +++ b/luaj-test/src/test/java/org/luaj/vm2/lib/jse/TestClass.java @@ -1,22 +1,31 @@ package org.luaj.vm2.lib.jse; public class TestClass { - private static class PrivateImpl implements TestInterface { + private static class PrivateImpl implements TestInterface { public String public_field; + public PrivateImpl() { this.public_field = "privateImpl-constructor"; } - PrivateImpl(String f) { + + 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 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, - } -} \ No newline at end of file + } + + 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/luaj-test/src/test/java/org/luaj/vm2/lib/jse/TestInterface.java b/luaj-test/src/test/java/org/luaj/vm2/lib/jse/TestInterface.java index 1b58a0a5..a64d3303 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/lib/jse/TestInterface.java +++ b/luaj-test/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-test/src/test/java/org/luaj/vm2/require/RequireSampleClassCastExcep.java b/luaj-test/src/test/java/org/luaj/vm2/require/RequireSampleClassCastExcep.java index 88ba21f6..9e9eea38 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/require/RequireSampleClassCastExcep.java +++ b/luaj-test/src/test/java/org/luaj/vm2/require/RequireSampleClassCastExcep.java @@ -3,15 +3,16 @@ package org.luaj.vm2.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/luaj-test/src/test/java/org/luaj/vm2/require/RequireSampleLoadLuaError.java b/luaj-test/src/test/java/org/luaj/vm2/require/RequireSampleLoadLuaError.java index 0ba5e148..cd1a29d5 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/require/RequireSampleLoadLuaError.java +++ b/luaj-test/src/test/java/org/luaj/vm2/require/RequireSampleLoadLuaError.java @@ -4,17 +4,17 @@ 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/luaj-test/src/test/java/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java b/luaj-test/src/test/java/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java index 1f416b89..57c2d03b 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java +++ b/luaj-test/src/test/java/org/luaj/vm2/require/RequireSampleLoadRuntimeExcep.java @@ -4,15 +4,16 @@ 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/luaj-test/src/test/java/org/luaj/vm2/require/RequireSampleSuccess.java b/luaj-test/src/test/java/org/luaj/vm2/require/RequireSampleSuccess.java index 766d3eb8..edddb49b 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/require/RequireSampleSuccess.java +++ b/luaj-test/src/test/java/org/luaj/vm2/require/RequireSampleSuccess.java @@ -4,15 +4,16 @@ 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/luaj-test/src/test/java/org/luaj/vm2/script/ScriptEngineTests.java b/luaj-test/src/test/java/org/luaj/vm2/script/ScriptEngineTests.java index 102c2874..8af34378 100644 --- a/luaj-test/src/test/java/org/luaj/vm2/script/ScriptEngineTests.java +++ b/luaj-test/src/test/java/org/luaj/vm2/script/ScriptEngineTests.java @@ -42,46 +42,49 @@ import org.luaj.vm2.LuaFunction; import org.luaj.vm2.LuaValue; import org.luaj.vm2.lib.OneArgFunction; -public class ScriptEngineTests extends TestSuite { +public class ScriptEngineTests extends TestSuite { public static TestSuite suite() { TestSuite suite = new TestSuite("Script Engine Tests"); - suite.addTest( new TestSuite( LookupEngineTestCase.class, "Lookup Engine" ) ); - suite.addTest( new TestSuite( DefaultBindingsTest.class, "Default Bindings" ) ); - suite.addTest( new TestSuite( SimpleBindingsTest.class, "Simple Bindings" ) ); - suite.addTest( new TestSuite( CompileClosureTest.class, "Compile Closure" ) ); - suite.addTest( new TestSuite( CompileNonClosureTest.class, "Compile NonClosure" ) ); - suite.addTest( new TestSuite( UserContextTest.class, "User Context" ) ); - suite.addTest( new TestSuite( WriterTest.class, "Writer" ) ); + suite.addTest(new TestSuite(LookupEngineTestCase.class, "Lookup Engine")); + suite.addTest(new TestSuite(DefaultBindingsTest.class, "Default Bindings")); + suite.addTest(new TestSuite(SimpleBindingsTest.class, "Simple Bindings")); + suite.addTest(new TestSuite(CompileClosureTest.class, "Compile Closure")); + suite.addTest(new TestSuite(CompileNonClosureTest.class, "Compile NonClosure")); + suite.addTest(new TestSuite(UserContextTest.class, "User Context")); + suite.addTest(new TestSuite(WriterTest.class, "Writer")); return suite; } - - public static class LookupEngineTestCase extends TestCase { + + public static class LookupEngineTestCase extends TestCase { public void testGetEngineByExtension() { - ScriptEngine e = new ScriptEngineManager().getEngineByExtension(".lua"); - assertNotNull(e); - assertEquals(LuaScriptEngine.class, e.getClass()); + ScriptEngine e = new ScriptEngineManager().getEngineByExtension(".lua"); + assertNotNull(e); + assertEquals(LuaScriptEngine.class, e.getClass()); } + public void testGetEngineByName() { - ScriptEngine e = new ScriptEngineManager().getEngineByName("luaj"); - assertNotNull(e); - assertEquals(LuaScriptEngine.class, e.getClass()); + ScriptEngine e = new ScriptEngineManager().getEngineByName("luaj"); + assertNotNull(e); + assertEquals(LuaScriptEngine.class, e.getClass()); } + public void testGetEngineByMimeType() { - ScriptEngine e = new ScriptEngineManager().getEngineByMimeType("text/lua"); - assertNotNull(e); - assertEquals(LuaScriptEngine.class, e.getClass()); + ScriptEngine e = new ScriptEngineManager().getEngineByMimeType("text/lua"); + assertNotNull(e); + assertEquals(LuaScriptEngine.class, e.getClass()); } + public 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()); + 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()); } } - + public static class DefaultBindingsTest extends EngineTestCase { protected Bindings createBindings() { return e.createBindings(); @@ -99,213 +102,233 @@ public class ScriptEngineTests extends TestSuite { System.setProperty("org.luaj.luajc", "false"); super.setUp(); } + public void testCompiledFunctionIsClosure() throws ScriptException { - CompiledScript cs = ((Compilable)e).compile("return 'foo'"); - LuaValue value = ((LuaScriptEngine.LuajCompiledScript)cs).function; - assertTrue(value.isclosure()); + CompiledScript cs = ((Compilable) e).compile("return 'foo'"); + LuaValue value = ((LuaScriptEngine.LuajCompiledScript) cs).function; + assertTrue(value.isclosure()); } } - + public static class CompileNonClosureTest extends DefaultBindingsTest { protected void setUp() throws Exception { System.setProperty("org.luaj.luajc", "true"); super.setUp(); } + public void testCompiledFunctionIsNotClosure() throws ScriptException { - CompiledScript cs = ((Compilable)e).compile("return 'foo'"); - LuaValue value = ((LuaScriptEngine.LuajCompiledScript)cs).function; - assertFalse(value.isclosure()); + CompiledScript cs = ((Compilable) e).compile("return 'foo'"); + LuaValue value = ((LuaScriptEngine.LuajCompiledScript) cs).function; + assertFalse(value.isclosure()); } } - abstract public static class EngineTestCase extends TestCase { + abstract public static class EngineTestCase extends TestCase { protected ScriptEngine e; - protected Bindings b; + protected Bindings b; + abstract protected Bindings createBindings(); + protected void setUp() throws Exception { - this.e = new ScriptEngineManager().getEngineByName("luaj"); + this.e = new ScriptEngineManager().getEngineByName("luaj"); this.b = createBindings(); } + public void testSqrtIntResult() throws ScriptException { - e.put("x", 25); - e.eval("y = math.sqrt(x)"); - Object y = e.get("y"); - assertEquals(5, y); + e.put("x", 25); + e.eval("y = math.sqrt(x)"); + Object y = e.get("y"); + assertEquals(5, y); } + public 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() { - public LuaValue call(LuaValue arg) { - return LuaValue.valueOf(arg.toString()+"123"); - } - }); - Object r = e.eval("return f('abc')"); - assertEquals("abc123", r); + e.put("x", 25); + e.eval("y = math.sqrt(x)"); + Object y = e.get("y"); + assertEquals(5, y); + e.put("f", new OneArgFunction() { + public LuaValue call(LuaValue arg) { + return LuaValue.valueOf(arg.toString() + "123"); + } + }); + Object r = e.eval("return f('abc')"); + assertEquals("abc123", r); } + public void testCompiledScript() throws ScriptException { - CompiledScript cs = ((Compilable)e).compile("y = math.sqrt(x); return y"); - b.put("x", 144); - assertEquals(12, cs.eval(b)); + CompiledScript cs = ((Compilable) e).compile("y = math.sqrt(x); return y"); + b.put("x", 144); + assertEquals(12, cs.eval(b)); } + public 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."); + 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."); } + public 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"; + 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 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()); + // 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()); } + public 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")); + 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")); } + public 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")); + 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")); } + public 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")); + 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")); } + public 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()); + 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()); } + public 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()); + 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()); } + public 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))); + 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))); } - public 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)); - } + + public 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)); + } + public 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]); + 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]); } } public static class SomeUserClass { - public String toString() { - return "some-user-value"; - } - } + public String toString() { + return "some-user-value"; + } + } - public static class UserContextTest extends TestCase { - protected ScriptEngine e; - protected Bindings b; + public static class UserContextTest extends TestCase { + protected ScriptEngine e; + protected Bindings b; protected ScriptContext c; + public void setUp() { - this.e = new ScriptEngineManager().getEngineByName("luaj"); + this.e = new ScriptEngineManager().getEngineByName("luaj"); this.c = new LuajContext(); this.b = c.getBindings(ScriptContext.ENGINE_SCOPE); } + public 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", 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")); + 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")); } - public 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")); + public 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")); } } - public static class WriterTest extends TestCase { + public static class WriterTest extends TestCase { protected ScriptEngine e; - protected Bindings b; + protected Bindings b; + public void setUp() { - this.e = new ScriptEngineManager().getEngineByName("luaj"); + this.e = new ScriptEngineManager().getEngineByName("luaj"); this.b = e.getBindings(ScriptContext.ENGINE_SCOPE); } + public 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(); - } + 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(); + } } }