Improve string byte backing ownership, add gradle file, up version, improve build packaging rules.
This commit is contained in:
@@ -968,6 +968,9 @@ Files are no longer hosted at LuaForge.
|
||||
<li>Add fallback to __lt when pocessing __le metatag.</li>
|
||||
<li>Convert anonymous classes to inner classes (gradle build support).</li>
|
||||
<li>Allow error() function to pass any lua object including non-strings.</li>
|
||||
<li>Fix string backing ownership issue when compiling many scripts.</li>
|
||||
<li>Make LuaC compile state explicit and improve factoring.</li>
|
||||
<li>Add sample build.gradle file for Android example.</li>
|
||||
|
||||
</ul></td></tr>
|
||||
</table></td></tr></table>
|
||||
|
||||
14
build.xml
14
build.xml
@@ -13,6 +13,11 @@
|
||||
<delete>
|
||||
<fileset dir="." includes="luaj-*.jar"/>
|
||||
</delete>
|
||||
<delete dir="examples/android/bin"/>
|
||||
<delete dir="examples/android/build"/>
|
||||
<delete dir="examples/android/gen"/>
|
||||
<delete dir="examples/android/libs"/>
|
||||
<delete dir="examples/maven/target"/>
|
||||
</target>
|
||||
|
||||
<import file="build-libs.xml"/>
|
||||
@@ -150,7 +155,14 @@
|
||||
<fileset dir="test"/>
|
||||
</copy>
|
||||
<copy todir="build/luaj-${version}/examples">
|
||||
<fileset dir="examples"/>
|
||||
<fileset dir="examples">
|
||||
<include name="android/*.*"/>
|
||||
<include name="android/assets/**"/>
|
||||
<include name="android/res/**"/>
|
||||
<include name="android/src/**"/>
|
||||
<include name="maven/pom.xml"/>
|
||||
<include name="maven/src/**"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy todir="build/luaj-${version}/lib">
|
||||
<fileset dir=".">
|
||||
|
||||
37
examples/android/build.gradle
Normal file
37
examples/android/build.gradle
Normal file
@@ -0,0 +1,37 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:1.0.1'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 20
|
||||
buildToolsVersion "20.0.0"
|
||||
defaultConfig {
|
||||
minSdkVersion 13
|
||||
targetSdkVersion 20
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
java.srcDirs = ['src']
|
||||
res.srcDirs = ['res']
|
||||
assets.srcDirs = ['assets']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'org.luaj:luaj-jse:3.0.1'
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
<dependency>
|
||||
<groupId>org.luaj</groupId>
|
||||
<artifactId>luaj-jse</artifactId>
|
||||
<version>3.0</version>
|
||||
<version>3.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
|
||||
@@ -220,7 +220,7 @@ public class LoadState {
|
||||
return null;
|
||||
byte[] bytes = new byte[size];
|
||||
is.readFully( bytes, 0, size );
|
||||
return LuaString.valueOf( bytes, 0, bytes.length - 1 );
|
||||
return LuaString.valueUsing( bytes, 0, bytes.length - 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,7 +38,7 @@ import org.luaj.vm2.lib.StringLib;
|
||||
* sequences of characters or unicode code points, the {@link LuaString}
|
||||
* implementation holds the string value in an internal byte array.
|
||||
* <p>
|
||||
* {@link LuaString} values are generally not mutable once constructed,
|
||||
* {@link LuaString} values are not considered mutable once constructed,
|
||||
* so multiple {@link LuaString} values can chare a single byte array.
|
||||
* <p>
|
||||
* Currently {@link LuaString}s are pooled via a centrally managed weak table.
|
||||
@@ -46,6 +46,9 @@ import org.luaj.vm2.lib.StringLib;
|
||||
* Constructors are not exposed directly. As with number, booleans, and nil,
|
||||
* instance construction should be via {@link LuaValue#valueOf(byte[])} or similar API.
|
||||
* <p>
|
||||
* Because of this pooling, users of LuaString <em>must not directly alter the
|
||||
* bytes in a LuaString</em>, or undefined behavior will result.
|
||||
* <p>
|
||||
* When Java Strings are used to initialize {@link LuaString} data, the UTF8 encoding is assumed.
|
||||
* The functions
|
||||
* {@link LuaString#lengthAsUtf8(char[]),
|
||||
@@ -59,47 +62,42 @@ import org.luaj.vm2.lib.StringLib;
|
||||
*/
|
||||
public class LuaString extends LuaValue {
|
||||
|
||||
/** 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. */
|
||||
public 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,
|
||||
* ecause no LuaString whose backing exceeds this length will be put into the cache. */
|
||||
public static final int RECENT_STRINGS_MAX_LENGTH = 32;
|
||||
|
||||
/** The singleton instance representing lua {@code true} */
|
||||
public static LuaValue s_metatable;
|
||||
|
||||
/** The bytes for the string */
|
||||
/** The bytes for the string. These <em><b>must not be mutated directly</b></em> 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;
|
||||
public final int m_offset;
|
||||
|
||||
/** The number of bytes that comprise this string */
|
||||
public final int m_length;
|
||||
|
||||
private static class Cache {
|
||||
/** 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 may show up as a cache hit and resolve
|
||||
* to the same value. */
|
||||
public final LuaString recent_short_strings[] = new LuaString[RECENT_STRINGS_CACHE_SIZE];
|
||||
|
||||
public LuaString get(LuaString s) {
|
||||
final int index = s.hashCode() & (RECENT_STRINGS_CACHE_SIZE - 1);
|
||||
final LuaString cached = (LuaString) recent_short_strings[index];
|
||||
if (cached != null && s.raweq(cached))
|
||||
return cached;
|
||||
recent_short_strings[index] = s;
|
||||
return s;
|
||||
}
|
||||
|
||||
static final Cache instance = new Cache();
|
||||
}
|
||||
public final int m_length;
|
||||
|
||||
/** 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. */
|
||||
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. */
|
||||
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. */
|
||||
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.
|
||||
@@ -110,13 +108,12 @@ public class LuaString extends LuaValue {
|
||||
char[] c = string.toCharArray();
|
||||
byte[] b = new byte[lengthAsUtf8(c)];
|
||||
encodeToUtf8(c, c.length, b, 0);
|
||||
return valueOf(b, 0, b.length);
|
||||
return valueUsing(b, 0, b.length);
|
||||
}
|
||||
|
||||
// TODO: should this be deprecated or made private?
|
||||
/** Construct a {@link LuaString} around a byte array that may be used directly as the backing.
|
||||
/** Construct a {@link LuaString} for a portion of a byte array.
|
||||
* <p>
|
||||
* The array may be used as the backing for this object, so clients must not change contents.
|
||||
* 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.
|
||||
@@ -127,21 +124,46 @@ public class LuaString extends LuaValue {
|
||||
* @return {@link LuaString} wrapping the byte buffer
|
||||
*/
|
||||
public static LuaString valueOf(byte[] bytes, int off, int len) {
|
||||
if (bytes.length < RECENT_STRINGS_MAX_LENGTH) {
|
||||
// Short string. Reuse the backing and check the cache of recent strings before returning.
|
||||
final LuaString s = new LuaString(bytes, off, len);
|
||||
return Cache.instance.get( s );
|
||||
} else if (len >= bytes.length / 2) {
|
||||
// Reuse backing only when more than half the bytes are part of the result.
|
||||
return new LuaString(bytes, off, len);
|
||||
} else {
|
||||
// Short result relative to the source. Copy only the bytes that are actually to be used.
|
||||
final byte[] b = new byte[len];
|
||||
System.arraycopy(bytes, off, b, 0, len);
|
||||
return valueOf(b, 0, len); // To possibly use cached version.
|
||||
}
|
||||
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 LuaString t = recent_short_strings[bucket];
|
||||
if (t != null && t.m_hashcode == hash && t.byteseq(bytes, off, len)) return t;
|
||||
final LuaString s = valueFromCopy(bytes, off, len);
|
||||
recent_short_strings[bucket] = s;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/** Construct a new LuaString using a copy of the bytes array supplied */
|
||||
private static LuaString valueFromCopy(byte[] bytes, int off, int len) {
|
||||
final byte[] copy = new byte[len];
|
||||
for (int i=0; i<len; ++i) copy[i] = bytes[off+i];
|
||||
return new LuaString(copy, 0, len);
|
||||
}
|
||||
|
||||
/** Construct a {@link LuaString} around, possibly using the the supplied
|
||||
* byte array as the backing store.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* @param bytes byte buffer
|
||||
* @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 LuaString t = recent_short_strings[bucket];
|
||||
if (t != null && t.m_hashcode == hash && t.byteseq(bytes, off, len)) return t;
|
||||
final LuaString s = new LuaString(bytes, off, len);
|
||||
recent_short_strings[bucket] = s;
|
||||
return s;
|
||||
}
|
||||
|
||||
/** Construct a {@link LuaString} using the supplied characters as byte values.
|
||||
* <p>
|
||||
* Only the low-order 8-bits of each character are used, the remainder is ignored.
|
||||
@@ -166,13 +188,13 @@ public class LuaString extends LuaValue {
|
||||
byte[] b = new byte[len];
|
||||
for ( int i=0; i<len; i++ )
|
||||
b[i] = (byte) bytes[i + off];
|
||||
return valueOf(b, 0, len);
|
||||
return valueUsing(b, 0, len);
|
||||
}
|
||||
|
||||
|
||||
/** Construct a {@link LuaString} around a byte array without copying the contents.
|
||||
/** Construct a {@link LuaString} for all the bytes in a byte array.
|
||||
* <p>
|
||||
* The array may be used directly as the backing, so clients must not change contents.
|
||||
* 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.
|
||||
* <p>
|
||||
* @param bytes byte buffer
|
||||
* @return {@link LuaString} wrapping the byte buffer
|
||||
@@ -181,6 +203,21 @@ public class LuaString extends LuaValue {
|
||||
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.
|
||||
* <p>
|
||||
* The LuaString returned will either be a new LuaString containing the byte array,
|
||||
* or be an existing LuaString used already having the same value.
|
||||
* <p>
|
||||
* 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
|
||||
*/
|
||||
public static LuaString valueUsing(byte[] bytes) {
|
||||
return valueUsing(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
/** Construct a {@link LuaString} around a byte array without copying the contents.
|
||||
* <p>
|
||||
* The array is used directly after this is called, so clients must not change contents.
|
||||
@@ -194,6 +231,7 @@ public class LuaString extends LuaValue {
|
||||
this.m_bytes = bytes;
|
||||
this.m_offset = offset;
|
||||
this.m_length = length;
|
||||
this.m_hashcode = hashCode(bytes, offset, length);
|
||||
}
|
||||
|
||||
public boolean isstring() {
|
||||
@@ -275,7 +313,7 @@ public class LuaString extends LuaValue {
|
||||
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);
|
||||
return valueOf(b, 0, b.length);
|
||||
return valueUsing(b, 0, b.length);
|
||||
}
|
||||
|
||||
// string comparison
|
||||
@@ -394,17 +432,32 @@ public class LuaString extends LuaValue {
|
||||
* beginIndex and extending for (endIndex - beginIndex ) characters.
|
||||
*/
|
||||
public LuaString substring( int beginIndex, int endIndex ) {
|
||||
return valueOf( m_bytes, m_offset + beginIndex, endIndex - beginIndex );
|
||||
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() {
|
||||
int h = m_length; /* seed */
|
||||
int step = (m_length>>5)+1; /* if string is too long, don't hash all its chars */
|
||||
for (int l1=m_length; l1>=step; l1-=step) /* compute hash */
|
||||
h = h ^ ((h<<5)+(h>>2)+(((int) m_bytes[m_offset+l1-1] ) & 0x0FF ));
|
||||
return h;
|
||||
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.
|
||||
* @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.
|
||||
* @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 ));
|
||||
return h;
|
||||
}
|
||||
|
||||
// object comparison, used in key comparison
|
||||
public boolean equals( Object o ) {
|
||||
if ( o instanceof LuaString ) {
|
||||
@@ -441,6 +494,11 @@ public class LuaString extends LuaValue {
|
||||
return equals( a.m_bytes, a.m_offset + i, b.m_bytes, b.m_offset + j, n );
|
||||
}
|
||||
|
||||
/** Return true if the bytes in the supplied range match this LuaStrings bytes. */
|
||||
private boolean byteseq(byte[] bytes, int off, int len) {
|
||||
return (m_length == len && equals(m_bytes, m_offset, bytes, off, len));
|
||||
}
|
||||
|
||||
public static boolean equals( byte[] a, int i, byte[] b, int j, int n ) {
|
||||
if ( a.length < i + n || b.length < j + n )
|
||||
return false;
|
||||
|
||||
185
src/core/org/luaj/vm2/compiler/Constants.java
Normal file
185
src/core/org/luaj/vm2/compiler/Constants.java
Normal file
@@ -0,0 +1,185 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015 Luaj.org. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
package org.luaj.vm2.compiler;
|
||||
|
||||
import org.luaj.vm2.LocVars;
|
||||
import org.luaj.vm2.Lua;
|
||||
import org.luaj.vm2.LuaError;
|
||||
import org.luaj.vm2.LuaString;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.Prototype;
|
||||
import org.luaj.vm2.Upvaldesc;
|
||||
|
||||
/**
|
||||
* Constants used by the LuaC compiler and related classes.
|
||||
*
|
||||
* @see LuaC
|
||||
* @see FuncState
|
||||
*/
|
||||
public class Constants extends Lua {
|
||||
|
||||
/** Maximum stack size of a luaj vm interpreter instance. */
|
||||
public static final int MAXSTACK = 250;
|
||||
|
||||
static final int LUAI_MAXUPVAL = 0xff;
|
||||
static final int LUAI_MAXVARS = 200;
|
||||
static final int NO_REG = MAXARG_A;
|
||||
|
||||
|
||||
/* OpMode - basic instruction format */
|
||||
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 */
|
||||
|
||||
|
||||
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 SETARG_A(int[] code, int index, int u) {
|
||||
code[index] = (code[index] & (MASK_NOT_A)) | ((u << POS_A) & MASK_A);
|
||||
}
|
||||
|
||||
static void SETARG_A(InstructionPtr i,int u) {
|
||||
i.set( ( i.get() & (MASK_NOT_A)) | ((u << POS_A) & MASK_A) );
|
||||
}
|
||||
|
||||
static void SETARG_B(InstructionPtr i,int u) {
|
||||
i.set( ( i.get() & (MASK_NOT_B)) | ((u << POS_B) & MASK_B) );
|
||||
}
|
||||
|
||||
static void SETARG_C(InstructionPtr i,int u) {
|
||||
i.set( ( i.get() & (MASK_NOT_C)) | ((u << POS_C) & MASK_C) );
|
||||
}
|
||||
|
||||
static void SETARG_Bx(InstructionPtr i,int u) {
|
||||
i.set( ( i.get() & (MASK_NOT_Bx)) | ((u << POS_Bx) & MASK_Bx) );
|
||||
}
|
||||
|
||||
static void SETARG_sBx(InstructionPtr i,int u) {
|
||||
SETARG_Bx( i, u + MAXARG_sBx );
|
||||
}
|
||||
|
||||
static int CREATE_ABC(int o, int a, int b, int c) {
|
||||
return ((o << POS_OP) & MASK_OP) |
|
||||
((a << POS_A) & MASK_A) |
|
||||
((b << POS_B) & MASK_B) |
|
||||
((c << POS_C) & MASK_C) ;
|
||||
}
|
||||
|
||||
static int CREATE_ABx(int o, int a, int bc) {
|
||||
return ((o << POS_OP) & MASK_OP) |
|
||||
((a << POS_A) & MASK_A) |
|
||||
((bc << POS_Bx) & MASK_Bx) ;
|
||||
}
|
||||
|
||||
// vector reallocation
|
||||
|
||||
static LuaValue[] realloc(LuaValue[] v, int n) {
|
||||
LuaValue[] a = new LuaValue[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static Prototype[] realloc(Prototype[] v, int n) {
|
||||
Prototype[] a = new Prototype[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static LuaString[] realloc(LuaString[] v, int n) {
|
||||
LuaString[] a = new LuaString[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static LocVars[] realloc(LocVars[] v, int n) {
|
||||
LocVars[] a = new LocVars[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static Upvaldesc[] realloc(Upvaldesc[] v, int n) {
|
||||
Upvaldesc[] a = new Upvaldesc[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static LexState.Vardesc[] realloc(LexState.Vardesc[] v, int n) {
|
||||
LexState.Vardesc[] a = new LexState.Vardesc[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static LexState.Labeldesc[] grow(LexState.Labeldesc[] v, int min_n) {
|
||||
return v == null ? new LexState.Labeldesc[2] : v.length < min_n ? realloc(v, v.length*2) : v;
|
||||
}
|
||||
|
||||
static LexState.Labeldesc[] realloc(LexState.Labeldesc[] v, int n) {
|
||||
LexState.Labeldesc[] a = new LexState.Labeldesc[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static int[] realloc(int[] v, int n) {
|
||||
int[] a = new int[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static byte[] realloc(byte[] v, int n) {
|
||||
byte[] a = new byte[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static char[] realloc(char[] v, int n) {
|
||||
char[] a = new char[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
protected Constants() {}
|
||||
}
|
||||
@@ -28,8 +28,6 @@ import org.luaj.vm2.Lua;
|
||||
import org.luaj.vm2.LuaDouble;
|
||||
import org.luaj.vm2.LuaInteger;
|
||||
import org.luaj.vm2.LuaString;
|
||||
import org.luaj.vm2.LuaTable;
|
||||
import org.luaj.vm2.LuaUserdata;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.Prototype;
|
||||
import org.luaj.vm2.Upvaldesc;
|
||||
@@ -37,7 +35,7 @@ import org.luaj.vm2.compiler.LexState.ConsControl;
|
||||
import org.luaj.vm2.compiler.LexState.expdesc;
|
||||
|
||||
|
||||
public class FuncState extends LuaC {
|
||||
public class FuncState extends Constants {
|
||||
|
||||
static class BlockCnt {
|
||||
BlockCnt previous; /* chain */
|
||||
@@ -52,7 +50,7 @@ public class FuncState extends LuaC {
|
||||
Hashtable h; /* table to find (and reuse) elements in `k' */
|
||||
FuncState prev; /* enclosing function */
|
||||
LexState ls; /* lexical state */
|
||||
LuaC L; /* compiler being invoked */
|
||||
LuaC.CompileState L; /* compiler being invoked */
|
||||
BlockCnt bl; /* chain of current blocks */
|
||||
int pc; /* next position to code (equivalent to `ncode') */
|
||||
int lasttarget; /* `pc' of last `jump target' */
|
||||
|
||||
@@ -23,7 +23,6 @@ package org.luaj.vm2.compiler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.luaj.vm2.LocVars;
|
||||
@@ -37,7 +36,7 @@ import org.luaj.vm2.compiler.FuncState.BlockCnt;
|
||||
import org.luaj.vm2.lib.MathLib;
|
||||
|
||||
|
||||
public class LexState {
|
||||
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)";
|
||||
@@ -135,7 +134,7 @@ public class LexState {
|
||||
final Token t = new Token(); /* current token */
|
||||
final Token lookahead = new Token(); /* look ahead token */
|
||||
FuncState fs; /* `FuncState' is private to the parser */
|
||||
LuaC L;
|
||||
LuaC.CompileState L;
|
||||
InputStream z; /* input stream */
|
||||
char[] buff; /* buffer for tokens */
|
||||
int nbuff; /* length of buffer */
|
||||
@@ -203,7 +202,7 @@ public class LexState {
|
||||
}
|
||||
|
||||
|
||||
public LexState(LuaC state, InputStream stream) {
|
||||
public LexState(LuaC.CompileState state, InputStream stream) {
|
||||
this.z = stream;
|
||||
this.buff = new char[32];
|
||||
this.L = state;
|
||||
@@ -229,7 +228,7 @@ public class LexState {
|
||||
|
||||
void save(int c) {
|
||||
if ( buff == null || nbuff + 1 > buff.length )
|
||||
buff = LuaC.realloc( buff, nbuff*2+1 );
|
||||
buff = realloc( buff, nbuff*2+1 );
|
||||
buff[nbuff++] = (char) c;
|
||||
}
|
||||
|
||||
@@ -282,7 +281,7 @@ public class LexState {
|
||||
|
||||
void inclinenumber() {
|
||||
int old = current;
|
||||
LuaC._assert( currIsNewline() );
|
||||
_assert( currIsNewline() );
|
||||
nextChar(); /* skip '\n' or '\r' */
|
||||
if ( currIsNewline() && current != old )
|
||||
nextChar(); /* skip '\n\r' or '\r\n' */
|
||||
@@ -290,7 +289,7 @@ public class LexState {
|
||||
syntaxerror("chunk has too many lines");
|
||||
}
|
||||
|
||||
void setinput( LuaC L, int firstByte, InputStream z, LuaString source ) {
|
||||
void setinput(LuaC.CompileState L, int firstByte, InputStream z, LuaString source) {
|
||||
this.decpoint = '.';
|
||||
this.L = L;
|
||||
this.lookahead.token = TK_EOS; /* no look-ahead token */
|
||||
@@ -397,7 +396,7 @@ public class LexState {
|
||||
void read_numeral(SemInfo seminfo) {
|
||||
String expo = "Ee";
|
||||
int first = current;
|
||||
LuaC._assert (isdigit(current));
|
||||
_assert (isdigit(current));
|
||||
save_and_next();
|
||||
if (first == '0' && check_next("Xx"))
|
||||
expo = "Pp";
|
||||
@@ -417,7 +416,7 @@ public class LexState {
|
||||
int skip_sep() {
|
||||
int count = 0;
|
||||
int s = current;
|
||||
LuaC._assert (s == '[' || s == ']');
|
||||
_assert (s == '[' || s == ']');
|
||||
save_and_next();
|
||||
while (current == '=') {
|
||||
save_and_next();
|
||||
@@ -690,7 +689,7 @@ public class LexState {
|
||||
}
|
||||
default: {
|
||||
if (isspace(current)) {
|
||||
LuaC._assert (!currIsNewline());
|
||||
_assert (!currIsNewline());
|
||||
nextChar();
|
||||
continue;
|
||||
} else if (isdigit(current)) {
|
||||
@@ -729,7 +728,7 @@ public class LexState {
|
||||
}
|
||||
|
||||
void lookahead() {
|
||||
LuaC._assert (lookahead.token == TK_EOS);
|
||||
_assert (lookahead.token == TK_EOS);
|
||||
lookahead.token = llex(lookahead.seminfo);
|
||||
}
|
||||
|
||||
@@ -841,7 +840,7 @@ public class LexState {
|
||||
|
||||
void anchor_token () {
|
||||
/* last token from outer function must be EOS */
|
||||
LuaC._assert(fs != null || t.token == TK_EOS);
|
||||
_assert(fs != null || t.token == TK_EOS);
|
||||
if (t.token == TK_NAME || t.token == TK_STRING) {
|
||||
LuaString ts = t.seminfo.ts;
|
||||
// TODO: is this necessary?
|
||||
@@ -916,7 +915,7 @@ public class LexState {
|
||||
FuncState fs = this.fs;
|
||||
Prototype f = fs.f;
|
||||
if (f.locvars == null || fs.nlocvars + 1 > f.locvars.length)
|
||||
f.locvars = LuaC.realloc( f.locvars, fs.nlocvars*2+1 );
|
||||
f.locvars = realloc( f.locvars, fs.nlocvars*2+1 );
|
||||
f.locvars[fs.nlocvars] = new LocVars(varname,0,0);
|
||||
return fs.nlocvars++;
|
||||
}
|
||||
@@ -925,7 +924,7 @@ public class LexState {
|
||||
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 = LuaC.realloc(dyd.actvar, Math.max(1, dyd.n_actvar * 2));
|
||||
dyd.actvar = realloc(dyd.actvar, Math.max(1, dyd.n_actvar * 2));
|
||||
dyd.actvar[dyd.n_actvar++] = new Vardesc(reg);
|
||||
}
|
||||
|
||||
@@ -954,7 +953,7 @@ public class LexState {
|
||||
if (FuncState.singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */
|
||||
expdesc key = new expdesc();
|
||||
FuncState.singlevaraux(fs, this.envn, var, 1); /* get environment variable */
|
||||
LuaC._assert(var.k == VLOCAL || var.k == VUPVAL);
|
||||
_assert(var.k == VLOCAL || var.k == VUPVAL);
|
||||
this.codestring(key, varname); /* key is variable name */
|
||||
fs.indexed(var, key); /* env[varname] */
|
||||
}
|
||||
@@ -997,7 +996,7 @@ public class LexState {
|
||||
FuncState fs = this.fs;
|
||||
Labeldesc[] gl = this.dyd.gt;
|
||||
Labeldesc gt = gl[g];
|
||||
LuaC._assert(gt.name.eq_b(label.name));
|
||||
_assert(gt.name.eq_b(label.name));
|
||||
if (gt.nactvar < label.nactvar) {
|
||||
LuaString vname = fs.getlocvar(gt.nactvar).varname;
|
||||
String msg = L.pushfstring("<goto " + gt.name + "> at line "
|
||||
@@ -1033,7 +1032,7 @@ public class LexState {
|
||||
return false; /* label not found; cannot close goto */
|
||||
}
|
||||
|
||||
/* Caller must LuaC.grow() the vector before calling this. */
|
||||
/* Caller must grow() the vector before calling this. */
|
||||
int newlabelentry(Labeldesc[] l, int index, LuaString name, int line, int pc) {
|
||||
l[index] = new Labeldesc(name, pc, line, fs.nactvar);
|
||||
return index;
|
||||
@@ -1060,7 +1059,7 @@ public class LexState {
|
||||
*/
|
||||
void breaklabel () {
|
||||
LuaString n = LuaString.valueOf("break");
|
||||
int l = newlabelentry(dyd.label=LuaC.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]);
|
||||
}
|
||||
|
||||
@@ -1079,7 +1078,7 @@ public class LexState {
|
||||
Prototype clp;
|
||||
Prototype f = fs.f; /* prototype of current function */
|
||||
if (f.p == null || fs.np >= f.p.length) {
|
||||
f.p = LuaC.realloc(f.p, Math.max(1, fs.np * 2));
|
||||
f.p = realloc(f.p, Math.max(1, fs.np * 2));
|
||||
}
|
||||
f.p[fs.np++] = clp = new Prototype();
|
||||
return clp;
|
||||
@@ -1087,7 +1086,7 @@ public class LexState {
|
||||
|
||||
void codeclosure (expdesc v) {
|
||||
FuncState fs = this.fs.prev;
|
||||
v.init(VRELOCABLE, fs.codeABx(LuaC.OP_CLOSURE, 0, fs.np - 1));
|
||||
v.init(VRELOCABLE, fs.codeABx(OP_CLOSURE, 0, fs.np - 1));
|
||||
fs.exp2nextreg(v); /* fix it at stack top (for GC) */
|
||||
}
|
||||
|
||||
@@ -1116,13 +1115,13 @@ public class LexState {
|
||||
Prototype f = fs.f;
|
||||
fs.ret(0, 0); /* final return */
|
||||
fs.leaveblock();
|
||||
f.code = LuaC.realloc(f.code, fs.pc);
|
||||
f.lineinfo = LuaC.realloc(f.lineinfo, fs.pc);
|
||||
f.k = LuaC.realloc(f.k, fs.nk);
|
||||
f.p = LuaC.realloc(f.p, fs.np);
|
||||
f.locvars = LuaC.realloc(f.locvars, fs.nlocvars);
|
||||
f.upvalues = LuaC.realloc(f.upvalues, fs.nups);
|
||||
LuaC._assert (fs.bl == null);
|
||||
f.code = realloc(f.code, fs.pc);
|
||||
f.lineinfo = realloc(f.lineinfo, fs.pc);
|
||||
f.k = realloc(f.k, fs.nk);
|
||||
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);
|
||||
this.fs = fs.prev;
|
||||
// last token read was anchored in defunct function; must reanchor it
|
||||
// ls.anchor_token();
|
||||
@@ -1209,7 +1208,7 @@ public class LexState {
|
||||
fs.exp2nextreg(t); /* fix it at stack top (for gc) */
|
||||
this.checknext('{');
|
||||
do {
|
||||
LuaC._assert (cc.v.k == VVOID || cc.tostore > 0);
|
||||
_assert (cc.v.k == VVOID || cc.tostore > 0);
|
||||
if (this.t.token == '}')
|
||||
break;
|
||||
fs.closelistfield(cc);
|
||||
@@ -1235,8 +1234,8 @@ public class LexState {
|
||||
this.check_match('}', '{', line);
|
||||
fs.lastlistfield(cc);
|
||||
InstructionPtr i = new InstructionPtr(fs.f.code, pc);
|
||||
LuaC.SETARG_B(i, luaO_int2fb(cc.na)); /* set initial array size */
|
||||
LuaC.SETARG_C(i, luaO_int2fb(cc.nh)); /* set initial table size */
|
||||
SETARG_B(i, luaO_int2fb(cc.na)); /* set initial array size */
|
||||
SETARG_C(i, luaO_int2fb(cc.nh)); /* set initial table size */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1350,7 +1349,7 @@ public class LexState {
|
||||
return;
|
||||
}
|
||||
}
|
||||
LuaC._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 */
|
||||
@@ -1727,7 +1726,7 @@ public class LexState {
|
||||
next(); /* skip break */
|
||||
label = LuaString.valueOf("break");
|
||||
}
|
||||
g = newlabelentry(dyd.gt =LuaC.grow(dyd.gt, dyd.n_gt+1), dyd.n_gt++, label, line, pc);
|
||||
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 */
|
||||
}
|
||||
|
||||
@@ -1745,7 +1744,7 @@ public class LexState {
|
||||
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=LuaC.grow(dyd.label, dyd.n_label+1), dyd.n_label++, label, line, fs.pc);
|
||||
l = newlabelentry(dyd.label=grow(dyd.label, dyd.n_label+1), dyd.n_label++, label, line, fs.pc);
|
||||
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 */
|
||||
@@ -2014,7 +2013,7 @@ public class LexState {
|
||||
}
|
||||
else { /* stat -> func */
|
||||
check_condition(v.v.k == VCALL, "syntax error");
|
||||
LuaC.SETARG_C(fs.getcodePtr(v.v), 1); /* call statement uses no results */
|
||||
SETARG_C(fs.getcodePtr(v.v), 1); /* call statement uses no results */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2030,8 +2029,8 @@ public class LexState {
|
||||
if (hasmultret(e.k)) {
|
||||
fs.setmultret(e);
|
||||
if (e.k == VCALL && nret == 1) { /* tail call? */
|
||||
LuaC.SET_OPCODE(fs.getcodePtr(e), Lua.OP_TAILCALL);
|
||||
LuaC._assert (Lua.GETARG_A(fs.getcode(e)) == fs.nactvar);
|
||||
SET_OPCODE(fs.getcodePtr(e), Lua.OP_TAILCALL);
|
||||
_assert (Lua.GETARG_A(fs.getcode(e)) == fs.nactvar);
|
||||
}
|
||||
first = fs.nactvar;
|
||||
nret = Lua.LUA_MULTRET; /* return all values */
|
||||
@@ -2041,7 +2040,7 @@ public class LexState {
|
||||
else {
|
||||
fs.exp2nextreg(e); /* values must go to the `stack' */
|
||||
first = fs.nactvar; /* return all `active' values */
|
||||
LuaC._assert (nret == fs.freereg - first);
|
||||
_assert (nret == fs.freereg - first);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2111,7 +2110,7 @@ public class LexState {
|
||||
break;
|
||||
}
|
||||
}
|
||||
LuaC._assert(fs.f.maxstacksize >= fs.freereg
|
||||
_assert(fs.f.maxstacksize >= fs.freereg
|
||||
&& fs.freereg >= fs.nactvar);
|
||||
fs.freereg = fs.nactvar; /* free registers */
|
||||
leavelevel();
|
||||
|
||||
@@ -26,15 +26,11 @@ import java.io.InputStream;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.luaj.vm2.Globals;
|
||||
import org.luaj.vm2.LocVars;
|
||||
import org.luaj.vm2.Lua;
|
||||
import org.luaj.vm2.LuaClosure;
|
||||
import org.luaj.vm2.LuaError;
|
||||
import org.luaj.vm2.LuaFunction;
|
||||
import org.luaj.vm2.LuaString;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.Prototype;
|
||||
import org.luaj.vm2.Upvaldesc;
|
||||
import org.luaj.vm2.lib.BaseLib;
|
||||
|
||||
/**
|
||||
@@ -77,7 +73,7 @@ import org.luaj.vm2.lib.BaseLib;
|
||||
* @see LuaCompiler
|
||||
* @see Prototype
|
||||
*/
|
||||
public class LuaC extends Lua implements Globals.Compiler, Globals.Loader {
|
||||
public class LuaC extends Constants implements Globals.Compiler, Globals.Loader {
|
||||
|
||||
/** A sharable instance of the LuaC compiler. */
|
||||
public static final LuaC instance = new LuaC();
|
||||
@@ -92,156 +88,7 @@ public class LuaC extends Lua implements Globals.Compiler, Globals.Loader {
|
||||
globals.loader = instance;
|
||||
}
|
||||
|
||||
protected static void _assert(boolean b) {
|
||||
if (!b)
|
||||
throw new LuaError("compiler assert failed");
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
/* OpMode - basic instruction format */
|
||||
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 void SET_OPCODE(InstructionPtr i,int o) {
|
||||
i.set( ( i.get() & (MASK_NOT_OP)) | ((o << POS_OP) & MASK_OP) );
|
||||
}
|
||||
|
||||
static void SETARG_A(int[] code, int index, int u) {
|
||||
code[index] = (code[index] & (MASK_NOT_A)) | ((u << POS_A) & MASK_A);
|
||||
}
|
||||
|
||||
static void SETARG_A(InstructionPtr i,int u) {
|
||||
i.set( ( i.get() & (MASK_NOT_A)) | ((u << POS_A) & MASK_A) );
|
||||
}
|
||||
|
||||
static void SETARG_B(InstructionPtr i,int u) {
|
||||
i.set( ( i.get() & (MASK_NOT_B)) | ((u << POS_B) & MASK_B) );
|
||||
}
|
||||
|
||||
static void SETARG_C(InstructionPtr i,int u) {
|
||||
i.set( ( i.get() & (MASK_NOT_C)) | ((u << POS_C) & MASK_C) );
|
||||
}
|
||||
|
||||
static void SETARG_Bx(InstructionPtr i,int u) {
|
||||
i.set( ( i.get() & (MASK_NOT_Bx)) | ((u << POS_Bx) & MASK_Bx) );
|
||||
}
|
||||
|
||||
static void SETARG_sBx(InstructionPtr i,int u) {
|
||||
SETARG_Bx( i, u + MAXARG_sBx );
|
||||
}
|
||||
|
||||
static int CREATE_ABC(int o, int a, int b, int c) {
|
||||
return ((o << POS_OP) & MASK_OP) |
|
||||
((a << POS_A) & MASK_A) |
|
||||
((b << POS_B) & MASK_B) |
|
||||
((c << POS_C) & MASK_C) ;
|
||||
}
|
||||
|
||||
static int CREATE_ABx(int o, int a, int bc) {
|
||||
return ((o << POS_OP) & MASK_OP) |
|
||||
((a << POS_A) & MASK_A) |
|
||||
((bc << POS_Bx) & MASK_Bx) ;
|
||||
}
|
||||
|
||||
// vector reallocation
|
||||
|
||||
static LuaValue[] realloc(LuaValue[] v, int n) {
|
||||
LuaValue[] a = new LuaValue[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static Prototype[] realloc(Prototype[] v, int n) {
|
||||
Prototype[] a = new Prototype[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static LuaString[] realloc(LuaString[] v, int n) {
|
||||
LuaString[] a = new LuaString[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static LocVars[] realloc(LocVars[] v, int n) {
|
||||
LocVars[] a = new LocVars[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static Upvaldesc[] realloc(Upvaldesc[] v, int n) {
|
||||
Upvaldesc[] a = new Upvaldesc[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static LexState.Vardesc[] realloc(LexState.Vardesc[] v, int n) {
|
||||
LexState.Vardesc[] a = new LexState.Vardesc[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static LexState.Labeldesc[] grow(LexState.Labeldesc[] v, int min_n) {
|
||||
return v == null ? new LexState.Labeldesc[2] : v.length < min_n ? realloc(v, v.length*2) : v;
|
||||
}
|
||||
|
||||
static LexState.Labeldesc[] realloc(LexState.Labeldesc[] v, int n) {
|
||||
LexState.Labeldesc[] a = new LexState.Labeldesc[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static int[] realloc(int[] v, int n) {
|
||||
int[] a = new int[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static byte[] realloc(byte[] v, int n) {
|
||||
byte[] a = new byte[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
static char[] realloc(char[] v, int n) {
|
||||
char[] a = new char[n];
|
||||
if ( v != null )
|
||||
System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
|
||||
return a;
|
||||
}
|
||||
|
||||
public int nCcalls;
|
||||
Hashtable strings;
|
||||
|
||||
protected LuaC() {}
|
||||
|
||||
private LuaC(Hashtable strings) {
|
||||
this.strings = strings;
|
||||
}
|
||||
|
||||
/** Compile lua source into a Prototype.
|
||||
* @param stream InputStream representing the text source conforming to lua source syntax.
|
||||
@@ -250,59 +97,64 @@ public class LuaC extends Lua implements Globals.Compiler, Globals.Loader {
|
||||
* @throws IOException
|
||||
*/
|
||||
public Prototype compile(InputStream stream, String chunkname) throws IOException {
|
||||
return (new LuaC(new Hashtable())).luaY_parser(stream, chunkname);
|
||||
}
|
||||
|
||||
/** @deprecated
|
||||
* Use Globals.load(InputString, String, String) instead,
|
||||
* or LuaC.compil(InputStream, String) and construct LuaClosure directly.
|
||||
*/
|
||||
public LuaValue load(InputStream stream, String chunkname, Globals globals) throws IOException {
|
||||
return new LuaClosure(compile(stream, chunkname), globals);
|
||||
}
|
||||
|
||||
|
||||
/** Parse the input */
|
||||
private Prototype luaY_parser(InputStream z, String name) throws IOException{
|
||||
LexState lexstate = new LexState(this, z);
|
||||
FuncState funcstate = new FuncState();
|
||||
// lexstate.buff = buff;
|
||||
lexstate.fs = funcstate;
|
||||
lexstate.setinput( this, 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);
|
||||
/* 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));
|
||||
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)
|
||||
return c;
|
||||
strings.put(s, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
public String pushfstring(String string) {
|
||||
return string;
|
||||
return (new CompileState()).luaY_parser(stream, chunkname);
|
||||
}
|
||||
|
||||
public LuaFunction load(Prototype prototype, String chunkname, LuaValue env) throws IOException {
|
||||
return new LuaClosure(prototype, env);
|
||||
}
|
||||
|
||||
/** @deprecated
|
||||
* Use Globals.load(InputString, String, String) instead,
|
||||
* or LuaC.compile(InputStream, String) and construct LuaClosure directly.
|
||||
*/
|
||||
public LuaValue load(InputStream stream, String chunkname, Globals globals) throws IOException {
|
||||
return new LuaClosure(compile(stream, chunkname), globals);
|
||||
}
|
||||
|
||||
static class CompileState {
|
||||
int nCcalls = 0;
|
||||
private Hashtable strings = new Hashtable();
|
||||
protected CompileState() {}
|
||||
|
||||
/** Parse the input */
|
||||
private Prototype luaY_parser(InputStream z, String name) throws IOException{
|
||||
LexState lexstate = new LexState(this, z);
|
||||
FuncState funcstate = new FuncState();
|
||||
// lexstate.buff = buff;
|
||||
lexstate.fs = funcstate;
|
||||
lexstate.setinput(this, 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);
|
||||
/* 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));
|
||||
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)
|
||||
return c;
|
||||
strings.put(s, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
public String pushfstring(String string) {
|
||||
return string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,7 +557,7 @@ public class IoLib extends TwoArgFunction {
|
||||
int r;
|
||||
if ( ( r = f.read(b,0,b.length) ) < 0 )
|
||||
return NIL;
|
||||
return LuaString.valueOf(b, 0, r);
|
||||
return LuaString.valueUsing(b, 0, r);
|
||||
}
|
||||
public static LuaValue freaduntil(File f,boolean lineonly) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
@@ -580,7 +580,7 @@ public class IoLib extends TwoArgFunction {
|
||||
}
|
||||
return ( c < 0 && baos.size() == 0 )?
|
||||
(LuaValue) NIL:
|
||||
(LuaValue) LuaString.valueOf(baos.toByteArray());
|
||||
(LuaValue) LuaString.valueUsing(baos.toByteArray());
|
||||
}
|
||||
public static LuaValue freadline(File f) throws IOException {
|
||||
return freaduntil(f,true);
|
||||
|
||||
@@ -160,7 +160,7 @@ public class StringLib extends TwoArgFunction {
|
||||
if (c<0 || c>=256) argerror(a, "invalid value");
|
||||
bytes[i] = (byte) c;
|
||||
}
|
||||
return LuaString.valueOf( bytes );
|
||||
return LuaString.valueUsing( bytes );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,7 +177,7 @@ public class StringLib extends TwoArgFunction {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try {
|
||||
DumpState.dump( ((LuaClosure)f).p, baos, true );
|
||||
return LuaString.valueOf(baos.toByteArray());
|
||||
return LuaString.valueUsing(baos.toByteArray());
|
||||
} catch (IOException e) {
|
||||
return error( e.getMessage() );
|
||||
}
|
||||
@@ -658,7 +658,7 @@ public class StringLib extends TwoArgFunction {
|
||||
for ( int offset = 0; offset < bytes.length; offset += len ) {
|
||||
s.copyInto( 0, bytes, offset, len );
|
||||
}
|
||||
return LuaString.valueOf( bytes );
|
||||
return LuaString.valueUsing( bytes );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -672,7 +672,7 @@ public class StringLib extends TwoArgFunction {
|
||||
byte[] b = new byte[n];
|
||||
for ( int i=0, j=n-1; i<n; i++, j-- )
|
||||
b[j] = (byte) s.luaByte(i);
|
||||
return LuaString.valueOf( b );
|
||||
return LuaString.valueUsing( b );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,20 +33,20 @@ public class Str {
|
||||
public static LuaString quoteString(String image) {
|
||||
String s = image.substring(1, image.length()-1);
|
||||
byte[] bytes = unquote(s);
|
||||
return LuaString.valueOf(bytes);
|
||||
return LuaString.valueUsing(bytes);
|
||||
}
|
||||
|
||||
public static LuaString charString(String image) {
|
||||
String s = image.substring(1, image.length()-1);
|
||||
byte[] bytes = unquote(s);
|
||||
return LuaString.valueOf(bytes);
|
||||
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);
|
||||
byte[] b = iso88591bytes(s);
|
||||
return LuaString.valueOf(b);
|
||||
return LuaString.valueUsing(b);
|
||||
}
|
||||
|
||||
public static byte[] iso88591bytes( String s ) {
|
||||
|
||||
@@ -1 +1 @@
|
||||
version: 3.0
|
||||
version: 3.0.1
|
||||
Reference in New Issue
Block a user