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>Add fallback to __lt when pocessing __le metatag.</li>
|
||||||
<li>Convert anonymous classes to inner classes (gradle build support).</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>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>
|
</ul></td></tr>
|
||||||
</table></td></tr></table>
|
</table></td></tr></table>
|
||||||
|
|||||||
14
build.xml
14
build.xml
@@ -13,6 +13,11 @@
|
|||||||
<delete>
|
<delete>
|
||||||
<fileset dir="." includes="luaj-*.jar"/>
|
<fileset dir="." includes="luaj-*.jar"/>
|
||||||
</delete>
|
</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>
|
</target>
|
||||||
|
|
||||||
<import file="build-libs.xml"/>
|
<import file="build-libs.xml"/>
|
||||||
@@ -150,7 +155,14 @@
|
|||||||
<fileset dir="test"/>
|
<fileset dir="test"/>
|
||||||
</copy>
|
</copy>
|
||||||
<copy todir="build/luaj-${version}/examples">
|
<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>
|
||||||
<copy todir="build/luaj-${version}/lib">
|
<copy todir="build/luaj-${version}/lib">
|
||||||
<fileset dir=".">
|
<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>
|
<dependency>
|
||||||
<groupId>org.luaj</groupId>
|
<groupId>org.luaj</groupId>
|
||||||
<artifactId>luaj-jse</artifactId>
|
<artifactId>luaj-jse</artifactId>
|
||||||
<version>3.0</version>
|
<version>3.0.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ public class LoadState {
|
|||||||
return null;
|
return null;
|
||||||
byte[] bytes = new byte[size];
|
byte[] bytes = new byte[size];
|
||||||
is.readFully( bytes, 0, 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}
|
* sequences of characters or unicode code points, the {@link LuaString}
|
||||||
* implementation holds the string value in an internal byte array.
|
* implementation holds the string value in an internal byte array.
|
||||||
* <p>
|
* <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.
|
* so multiple {@link LuaString} values can chare a single byte array.
|
||||||
* <p>
|
* <p>
|
||||||
* Currently {@link LuaString}s are pooled via a centrally managed weak table.
|
* 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,
|
* Constructors are not exposed directly. As with number, booleans, and nil,
|
||||||
* instance construction should be via {@link LuaValue#valueOf(byte[])} or similar API.
|
* instance construction should be via {@link LuaValue#valueOf(byte[])} or similar API.
|
||||||
* <p>
|
* <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.
|
* When Java Strings are used to initialize {@link LuaString} data, the UTF8 encoding is assumed.
|
||||||
* The functions
|
* The functions
|
||||||
* {@link LuaString#lengthAsUtf8(char[]),
|
* {@link LuaString#lengthAsUtf8(char[]),
|
||||||
@@ -59,46 +62,41 @@ import org.luaj.vm2.lib.StringLib;
|
|||||||
*/
|
*/
|
||||||
public class LuaString extends LuaValue {
|
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} */
|
/** The singleton instance representing lua {@code true} */
|
||||||
public static LuaValue s_metatable;
|
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;
|
public final byte[] m_bytes;
|
||||||
|
|
||||||
/** The offset into the byte array, 0 means start at the first byte */
|
/** 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 */
|
/** The number of bytes that comprise this string */
|
||||||
public final int m_length;
|
public final int m_length;
|
||||||
|
|
||||||
private static class Cache {
|
/** The hashcode for this string. Computed at construct time. */
|
||||||
/** Simple cache of recently created strings that are short.
|
private final int m_hashcode;
|
||||||
* 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) {
|
/** Size of cache of recent short strings. This is the maximum number of LuaStrings that
|
||||||
final int index = s.hashCode() & (RECENT_STRINGS_CACHE_SIZE - 1);
|
* will be retained in the cache of recent short strings. Exposed to package for testing. */
|
||||||
final LuaString cached = (LuaString) recent_short_strings[index];
|
static final int RECENT_STRINGS_CACHE_SIZE = 128;
|
||||||
if (cached != null && s.raweq(cached))
|
|
||||||
return cached;
|
|
||||||
recent_short_strings[index] = s;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static final Cache instance = new Cache();
|
/** 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
|
* Get a {@link LuaString} instance whose bytes match
|
||||||
@@ -110,13 +108,12 @@ public class LuaString extends LuaValue {
|
|||||||
char[] c = string.toCharArray();
|
char[] c = string.toCharArray();
|
||||||
byte[] b = new byte[lengthAsUtf8(c)];
|
byte[] b = new byte[lengthAsUtf8(c)];
|
||||||
encodeToUtf8(c, c.length, b, 0);
|
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} for a portion of a byte array.
|
||||||
/** Construct a {@link LuaString} around a byte array that may be used directly as the backing.
|
|
||||||
* <p>
|
* <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
|
* 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
|
* 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.
|
* new byte array, and cache lookup may be performed.
|
||||||
@@ -127,19 +124,44 @@ public class LuaString extends LuaValue {
|
|||||||
* @return {@link LuaString} wrapping the byte buffer
|
* @return {@link LuaString} wrapping the byte buffer
|
||||||
*/
|
*/
|
||||||
public static LuaString valueOf(byte[] bytes, int off, int len) {
|
public static LuaString valueOf(byte[] bytes, int off, int len) {
|
||||||
if (bytes.length < RECENT_STRINGS_MAX_LENGTH) {
|
if (len > RECENT_STRINGS_MAX_LENGTH)
|
||||||
// Short string. Reuse the backing and check the cache of recent strings before returning.
|
return valueFromCopy(bytes, off, len);
|
||||||
final LuaString s = new LuaString(bytes, off, len);
|
final int hash = hashCode(bytes, off, len);
|
||||||
return Cache.instance.get( s );
|
final int bucket = hash & (RECENT_STRINGS_CACHE_SIZE - 1);
|
||||||
} else if (len >= bytes.length / 2) {
|
final LuaString t = recent_short_strings[bucket];
|
||||||
// Reuse backing only when more than half the bytes are part of the result.
|
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);
|
return new LuaString(bytes, off, len);
|
||||||
} else {
|
final int hash = hashCode(bytes, off, len);
|
||||||
// Short result relative to the source. Copy only the bytes that are actually to be used.
|
final int bucket = hash & (RECENT_STRINGS_CACHE_SIZE - 1);
|
||||||
final byte[] b = new byte[len];
|
final LuaString t = recent_short_strings[bucket];
|
||||||
System.arraycopy(bytes, off, b, 0, len);
|
if (t != null && t.m_hashcode == hash && t.byteseq(bytes, off, len)) return t;
|
||||||
return valueOf(b, 0, len); // To possibly use cached version.
|
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.
|
/** Construct a {@link LuaString} using the supplied characters as byte values.
|
||||||
@@ -166,13 +188,13 @@ public class LuaString extends LuaValue {
|
|||||||
byte[] b = new byte[len];
|
byte[] b = new byte[len];
|
||||||
for ( int i=0; i<len; i++ )
|
for ( int i=0; i<len; i++ )
|
||||||
b[i] = (byte) bytes[i + off];
|
b[i] = (byte) bytes[i + off];
|
||||||
return valueOf(b, 0, len);
|
return valueUsing(b, 0, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Construct a {@link LuaString} for all the bytes in a byte array.
|
||||||
/** Construct a {@link LuaString} around a byte array without copying the contents.
|
|
||||||
* <p>
|
* <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>
|
* <p>
|
||||||
* @param bytes byte buffer
|
* @param bytes byte buffer
|
||||||
* @return {@link LuaString} wrapping the byte buffer
|
* @return {@link LuaString} wrapping the byte buffer
|
||||||
@@ -181,6 +203,21 @@ public class LuaString extends LuaValue {
|
|||||||
return valueOf(bytes, 0, bytes.length);
|
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.
|
/** Construct a {@link LuaString} around a byte array without copying the contents.
|
||||||
* <p>
|
* <p>
|
||||||
* 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.
|
||||||
@@ -194,6 +231,7 @@ public class LuaString extends LuaValue {
|
|||||||
this.m_bytes = bytes;
|
this.m_bytes = bytes;
|
||||||
this.m_offset = offset;
|
this.m_offset = offset;
|
||||||
this.m_length = length;
|
this.m_length = length;
|
||||||
|
this.m_hashcode = hashCode(bytes, offset, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isstring() {
|
public boolean isstring() {
|
||||||
@@ -275,7 +313,7 @@ public class LuaString extends LuaValue {
|
|||||||
byte[] b = new byte[lhs.m_length+this.m_length];
|
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(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);
|
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
|
// string comparison
|
||||||
@@ -394,14 +432,29 @@ public class LuaString extends LuaValue {
|
|||||||
* beginIndex and extending for (endIndex - beginIndex ) characters.
|
* beginIndex and extending for (endIndex - beginIndex ) characters.
|
||||||
*/
|
*/
|
||||||
public LuaString substring( int beginIndex, int endIndex ) {
|
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() {
|
public int hashCode() {
|
||||||
int h = m_length; /* seed */
|
return m_hashcode;
|
||||||
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 ));
|
/** 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;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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 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 ) {
|
public static boolean equals( byte[] a, int i, byte[] b, int j, int n ) {
|
||||||
if ( a.length < i + n || b.length < j + n )
|
if ( a.length < i + n || b.length < j + n )
|
||||||
return false;
|
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.LuaDouble;
|
||||||
import org.luaj.vm2.LuaInteger;
|
import org.luaj.vm2.LuaInteger;
|
||||||
import org.luaj.vm2.LuaString;
|
import org.luaj.vm2.LuaString;
|
||||||
import org.luaj.vm2.LuaTable;
|
|
||||||
import org.luaj.vm2.LuaUserdata;
|
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Prototype;
|
import org.luaj.vm2.Prototype;
|
||||||
import org.luaj.vm2.Upvaldesc;
|
import org.luaj.vm2.Upvaldesc;
|
||||||
@@ -37,7 +35,7 @@ import org.luaj.vm2.compiler.LexState.ConsControl;
|
|||||||
import org.luaj.vm2.compiler.LexState.expdesc;
|
import org.luaj.vm2.compiler.LexState.expdesc;
|
||||||
|
|
||||||
|
|
||||||
public class FuncState extends LuaC {
|
public class FuncState extends Constants {
|
||||||
|
|
||||||
static class BlockCnt {
|
static class BlockCnt {
|
||||||
BlockCnt previous; /* chain */
|
BlockCnt previous; /* chain */
|
||||||
@@ -52,7 +50,7 @@ public class FuncState extends LuaC {
|
|||||||
Hashtable h; /* table to find (and reuse) elements in `k' */
|
Hashtable h; /* table to find (and reuse) elements in `k' */
|
||||||
FuncState prev; /* enclosing function */
|
FuncState prev; /* enclosing function */
|
||||||
LexState ls; /* lexical state */
|
LexState ls; /* lexical state */
|
||||||
LuaC L; /* compiler being invoked */
|
LuaC.CompileState L; /* compiler being invoked */
|
||||||
BlockCnt bl; /* chain of current blocks */
|
BlockCnt bl; /* chain of current blocks */
|
||||||
int pc; /* next position to code (equivalent to `ncode') */
|
int pc; /* next position to code (equivalent to `ncode') */
|
||||||
int lasttarget; /* `pc' of last `jump target' */
|
int lasttarget; /* `pc' of last `jump target' */
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ package org.luaj.vm2.compiler;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.Reader;
|
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
|
||||||
import org.luaj.vm2.LocVars;
|
import org.luaj.vm2.LocVars;
|
||||||
@@ -37,7 +36,7 @@ import org.luaj.vm2.compiler.FuncState.BlockCnt;
|
|||||||
import org.luaj.vm2.lib.MathLib;
|
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_CONTROL = "(for control)";
|
||||||
protected static final String RESERVED_LOCAL_VAR_FOR_STATE = "(for state)";
|
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 t = new Token(); /* current token */
|
||||||
final Token lookahead = new Token(); /* look ahead token */
|
final Token lookahead = new Token(); /* look ahead token */
|
||||||
FuncState fs; /* `FuncState' is private to the parser */
|
FuncState fs; /* `FuncState' is private to the parser */
|
||||||
LuaC L;
|
LuaC.CompileState L;
|
||||||
InputStream z; /* input stream */
|
InputStream z; /* input stream */
|
||||||
char[] buff; /* buffer for tokens */
|
char[] buff; /* buffer for tokens */
|
||||||
int nbuff; /* length of buffer */
|
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.z = stream;
|
||||||
this.buff = new char[32];
|
this.buff = new char[32];
|
||||||
this.L = state;
|
this.L = state;
|
||||||
@@ -229,7 +228,7 @@ public class LexState {
|
|||||||
|
|
||||||
void save(int c) {
|
void save(int c) {
|
||||||
if ( buff == null || nbuff + 1 > buff.length )
|
if ( buff == null || nbuff + 1 > buff.length )
|
||||||
buff = LuaC.realloc( buff, nbuff*2+1 );
|
buff = realloc( buff, nbuff*2+1 );
|
||||||
buff[nbuff++] = (char) c;
|
buff[nbuff++] = (char) c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,7 +281,7 @@ public class LexState {
|
|||||||
|
|
||||||
void inclinenumber() {
|
void inclinenumber() {
|
||||||
int old = current;
|
int old = current;
|
||||||
LuaC._assert( currIsNewline() );
|
_assert( currIsNewline() );
|
||||||
nextChar(); /* skip '\n' or '\r' */
|
nextChar(); /* skip '\n' or '\r' */
|
||||||
if ( currIsNewline() && current != old )
|
if ( currIsNewline() && current != old )
|
||||||
nextChar(); /* skip '\n\r' or '\r\n' */
|
nextChar(); /* skip '\n\r' or '\r\n' */
|
||||||
@@ -290,7 +289,7 @@ public class LexState {
|
|||||||
syntaxerror("chunk has too many lines");
|
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.decpoint = '.';
|
||||||
this.L = L;
|
this.L = L;
|
||||||
this.lookahead.token = TK_EOS; /* no look-ahead token */
|
this.lookahead.token = TK_EOS; /* no look-ahead token */
|
||||||
@@ -397,7 +396,7 @@ public class LexState {
|
|||||||
void read_numeral(SemInfo seminfo) {
|
void read_numeral(SemInfo seminfo) {
|
||||||
String expo = "Ee";
|
String expo = "Ee";
|
||||||
int first = current;
|
int first = current;
|
||||||
LuaC._assert (isdigit(current));
|
_assert (isdigit(current));
|
||||||
save_and_next();
|
save_and_next();
|
||||||
if (first == '0' && check_next("Xx"))
|
if (first == '0' && check_next("Xx"))
|
||||||
expo = "Pp";
|
expo = "Pp";
|
||||||
@@ -417,7 +416,7 @@ public class LexState {
|
|||||||
int skip_sep() {
|
int skip_sep() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int s = current;
|
int s = current;
|
||||||
LuaC._assert (s == '[' || s == ']');
|
_assert (s == '[' || s == ']');
|
||||||
save_and_next();
|
save_and_next();
|
||||||
while (current == '=') {
|
while (current == '=') {
|
||||||
save_and_next();
|
save_and_next();
|
||||||
@@ -690,7 +689,7 @@ public class LexState {
|
|||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
if (isspace(current)) {
|
if (isspace(current)) {
|
||||||
LuaC._assert (!currIsNewline());
|
_assert (!currIsNewline());
|
||||||
nextChar();
|
nextChar();
|
||||||
continue;
|
continue;
|
||||||
} else if (isdigit(current)) {
|
} else if (isdigit(current)) {
|
||||||
@@ -729,7 +728,7 @@ public class LexState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void lookahead() {
|
void lookahead() {
|
||||||
LuaC._assert (lookahead.token == TK_EOS);
|
_assert (lookahead.token == TK_EOS);
|
||||||
lookahead.token = llex(lookahead.seminfo);
|
lookahead.token = llex(lookahead.seminfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -841,7 +840,7 @@ public class LexState {
|
|||||||
|
|
||||||
void anchor_token () {
|
void anchor_token () {
|
||||||
/* last token from outer function must be EOS */
|
/* 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) {
|
if (t.token == TK_NAME || t.token == TK_STRING) {
|
||||||
LuaString ts = t.seminfo.ts;
|
LuaString ts = t.seminfo.ts;
|
||||||
// TODO: is this necessary?
|
// TODO: is this necessary?
|
||||||
@@ -916,7 +915,7 @@ public class LexState {
|
|||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
Prototype f = fs.f;
|
Prototype f = fs.f;
|
||||||
if (f.locvars == null || fs.nlocvars + 1 > f.locvars.length)
|
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);
|
f.locvars[fs.nlocvars] = new LocVars(varname,0,0);
|
||||||
return fs.nlocvars++;
|
return fs.nlocvars++;
|
||||||
}
|
}
|
||||||
@@ -925,7 +924,7 @@ public class LexState {
|
|||||||
int reg = registerlocalvar(name);
|
int reg = registerlocalvar(name);
|
||||||
fs.checklimit(dyd.n_actvar + 1, FuncState.LUAI_MAXVARS, "local variables");
|
fs.checklimit(dyd.n_actvar + 1, FuncState.LUAI_MAXVARS, "local variables");
|
||||||
if (dyd.actvar == null || dyd.n_actvar + 1 > dyd.actvar.length)
|
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);
|
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? */
|
if (FuncState.singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */
|
||||||
expdesc key = new expdesc();
|
expdesc key = new expdesc();
|
||||||
FuncState.singlevaraux(fs, this.envn, var, 1); /* get environment variable */
|
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 */
|
this.codestring(key, varname); /* key is variable name */
|
||||||
fs.indexed(var, key); /* env[varname] */
|
fs.indexed(var, key); /* env[varname] */
|
||||||
}
|
}
|
||||||
@@ -997,7 +996,7 @@ public class LexState {
|
|||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
Labeldesc[] gl = this.dyd.gt;
|
Labeldesc[] gl = this.dyd.gt;
|
||||||
Labeldesc gt = gl[g];
|
Labeldesc gt = gl[g];
|
||||||
LuaC._assert(gt.name.eq_b(label.name));
|
_assert(gt.name.eq_b(label.name));
|
||||||
if (gt.nactvar < label.nactvar) {
|
if (gt.nactvar < label.nactvar) {
|
||||||
LuaString vname = fs.getlocvar(gt.nactvar).varname;
|
LuaString vname = fs.getlocvar(gt.nactvar).varname;
|
||||||
String msg = L.pushfstring("<goto " + gt.name + "> at line "
|
String msg = L.pushfstring("<goto " + gt.name + "> at line "
|
||||||
@@ -1033,7 +1032,7 @@ public class LexState {
|
|||||||
return false; /* label not found; cannot close goto */
|
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) {
|
int newlabelentry(Labeldesc[] l, int index, LuaString name, int line, int pc) {
|
||||||
l[index] = new Labeldesc(name, pc, line, fs.nactvar);
|
l[index] = new Labeldesc(name, pc, line, fs.nactvar);
|
||||||
return index;
|
return index;
|
||||||
@@ -1060,7 +1059,7 @@ public class LexState {
|
|||||||
*/
|
*/
|
||||||
void breaklabel () {
|
void breaklabel () {
|
||||||
LuaString n = LuaString.valueOf("break");
|
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]);
|
findgotos(dyd.label[l]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1079,7 +1078,7 @@ public class LexState {
|
|||||||
Prototype clp;
|
Prototype clp;
|
||||||
Prototype f = fs.f; /* prototype of current function */
|
Prototype f = fs.f; /* prototype of current function */
|
||||||
if (f.p == null || fs.np >= f.p.length) {
|
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();
|
f.p[fs.np++] = clp = new Prototype();
|
||||||
return clp;
|
return clp;
|
||||||
@@ -1087,7 +1086,7 @@ public class LexState {
|
|||||||
|
|
||||||
void codeclosure (expdesc v) {
|
void codeclosure (expdesc v) {
|
||||||
FuncState fs = this.fs.prev;
|
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) */
|
fs.exp2nextreg(v); /* fix it at stack top (for GC) */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1116,13 +1115,13 @@ public class LexState {
|
|||||||
Prototype f = fs.f;
|
Prototype f = fs.f;
|
||||||
fs.ret(0, 0); /* final return */
|
fs.ret(0, 0); /* final return */
|
||||||
fs.leaveblock();
|
fs.leaveblock();
|
||||||
f.code = LuaC.realloc(f.code, fs.pc);
|
f.code = realloc(f.code, fs.pc);
|
||||||
f.lineinfo = LuaC.realloc(f.lineinfo, fs.pc);
|
f.lineinfo = realloc(f.lineinfo, fs.pc);
|
||||||
f.k = LuaC.realloc(f.k, fs.nk);
|
f.k = realloc(f.k, fs.nk);
|
||||||
f.p = LuaC.realloc(f.p, fs.np);
|
f.p = realloc(f.p, fs.np);
|
||||||
f.locvars = LuaC.realloc(f.locvars, fs.nlocvars);
|
f.locvars = realloc(f.locvars, fs.nlocvars);
|
||||||
f.upvalues = LuaC.realloc(f.upvalues, fs.nups);
|
f.upvalues = realloc(f.upvalues, fs.nups);
|
||||||
LuaC._assert (fs.bl == null);
|
_assert (fs.bl == null);
|
||||||
this.fs = fs.prev;
|
this.fs = fs.prev;
|
||||||
// last token read was anchored in defunct function; must reanchor it
|
// last token read was anchored in defunct function; must reanchor it
|
||||||
// ls.anchor_token();
|
// ls.anchor_token();
|
||||||
@@ -1209,7 +1208,7 @@ public class LexState {
|
|||||||
fs.exp2nextreg(t); /* fix it at stack top (for gc) */
|
fs.exp2nextreg(t); /* fix it at stack top (for gc) */
|
||||||
this.checknext('{');
|
this.checknext('{');
|
||||||
do {
|
do {
|
||||||
LuaC._assert (cc.v.k == VVOID || cc.tostore > 0);
|
_assert (cc.v.k == VVOID || cc.tostore > 0);
|
||||||
if (this.t.token == '}')
|
if (this.t.token == '}')
|
||||||
break;
|
break;
|
||||||
fs.closelistfield(cc);
|
fs.closelistfield(cc);
|
||||||
@@ -1235,8 +1234,8 @@ public class LexState {
|
|||||||
this.check_match('}', '{', line);
|
this.check_match('}', '{', line);
|
||||||
fs.lastlistfield(cc);
|
fs.lastlistfield(cc);
|
||||||
InstructionPtr i = new InstructionPtr(fs.f.code, pc);
|
InstructionPtr i = new InstructionPtr(fs.f.code, pc);
|
||||||
LuaC.SETARG_B(i, luaO_int2fb(cc.na)); /* set initial array size */
|
SETARG_B(i, luaO_int2fb(cc.na)); /* set initial array size */
|
||||||
LuaC.SETARG_C(i, luaO_int2fb(cc.nh)); /* set initial table size */
|
SETARG_C(i, luaO_int2fb(cc.nh)); /* set initial table size */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1350,7 +1349,7 @@ public class LexState {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LuaC._assert (f.k == VNONRELOC);
|
_assert (f.k == VNONRELOC);
|
||||||
base = f.u.info; /* base register for call */
|
base = f.u.info; /* base register for call */
|
||||||
if (hasmultret(args.k))
|
if (hasmultret(args.k))
|
||||||
nparams = Lua.LUA_MULTRET; /* open call */
|
nparams = Lua.LUA_MULTRET; /* open call */
|
||||||
@@ -1727,7 +1726,7 @@ public class LexState {
|
|||||||
next(); /* skip break */
|
next(); /* skip break */
|
||||||
label = LuaString.valueOf("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 */
|
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 */
|
fs.checkrepeated(dyd.label, dyd.n_label, label); /* check for repeated labels */
|
||||||
checknext(TK_DBCOLON); /* skip double colon */
|
checknext(TK_DBCOLON); /* skip double colon */
|
||||||
/* create new entry for this label */
|
/* 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 */
|
skipnoopstat(); /* skip other no-op statements */
|
||||||
if (block_follow(false)) { /* label is last no-op statement in the block? */
|
if (block_follow(false)) { /* label is last no-op statement in the block? */
|
||||||
/* assume that locals are already out of scope */
|
/* assume that locals are already out of scope */
|
||||||
@@ -2014,7 +2013,7 @@ public class LexState {
|
|||||||
}
|
}
|
||||||
else { /* stat -> func */
|
else { /* stat -> func */
|
||||||
check_condition(v.v.k == VCALL, "syntax error");
|
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)) {
|
if (hasmultret(e.k)) {
|
||||||
fs.setmultret(e);
|
fs.setmultret(e);
|
||||||
if (e.k == VCALL && nret == 1) { /* tail call? */
|
if (e.k == VCALL && nret == 1) { /* tail call? */
|
||||||
LuaC.SET_OPCODE(fs.getcodePtr(e), Lua.OP_TAILCALL);
|
SET_OPCODE(fs.getcodePtr(e), Lua.OP_TAILCALL);
|
||||||
LuaC._assert (Lua.GETARG_A(fs.getcode(e)) == fs.nactvar);
|
_assert (Lua.GETARG_A(fs.getcode(e)) == fs.nactvar);
|
||||||
}
|
}
|
||||||
first = fs.nactvar;
|
first = fs.nactvar;
|
||||||
nret = Lua.LUA_MULTRET; /* return all values */
|
nret = Lua.LUA_MULTRET; /* return all values */
|
||||||
@@ -2041,7 +2040,7 @@ public class LexState {
|
|||||||
else {
|
else {
|
||||||
fs.exp2nextreg(e); /* values must go to the `stack' */
|
fs.exp2nextreg(e); /* values must go to the `stack' */
|
||||||
first = fs.nactvar; /* return all `active' values */
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LuaC._assert(fs.f.maxstacksize >= fs.freereg
|
_assert(fs.f.maxstacksize >= fs.freereg
|
||||||
&& fs.freereg >= fs.nactvar);
|
&& fs.freereg >= fs.nactvar);
|
||||||
fs.freereg = fs.nactvar; /* free registers */
|
fs.freereg = fs.nactvar; /* free registers */
|
||||||
leavelevel();
|
leavelevel();
|
||||||
|
|||||||
@@ -26,15 +26,11 @@ import java.io.InputStream;
|
|||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
|
||||||
import org.luaj.vm2.Globals;
|
import org.luaj.vm2.Globals;
|
||||||
import org.luaj.vm2.LocVars;
|
|
||||||
import org.luaj.vm2.Lua;
|
|
||||||
import org.luaj.vm2.LuaClosure;
|
import org.luaj.vm2.LuaClosure;
|
||||||
import org.luaj.vm2.LuaError;
|
|
||||||
import org.luaj.vm2.LuaFunction;
|
import org.luaj.vm2.LuaFunction;
|
||||||
import org.luaj.vm2.LuaString;
|
import org.luaj.vm2.LuaString;
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Prototype;
|
import org.luaj.vm2.Prototype;
|
||||||
import org.luaj.vm2.Upvaldesc;
|
|
||||||
import org.luaj.vm2.lib.BaseLib;
|
import org.luaj.vm2.lib.BaseLib;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,7 +73,7 @@ import org.luaj.vm2.lib.BaseLib;
|
|||||||
* @see LuaCompiler
|
* @see LuaCompiler
|
||||||
* @see Prototype
|
* @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. */
|
/** A sharable instance of the LuaC compiler. */
|
||||||
public static final LuaC instance = new LuaC();
|
public static final LuaC instance = new LuaC();
|
||||||
@@ -92,157 +88,8 @@ public class LuaC extends Lua implements Globals.Compiler, Globals.Loader {
|
|||||||
globals.loader = instance;
|
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() {}
|
protected LuaC() {}
|
||||||
|
|
||||||
private LuaC(Hashtable strings) {
|
|
||||||
this.strings = strings;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Compile lua source into a Prototype.
|
/** Compile lua source into a Prototype.
|
||||||
* @param stream InputStream representing the text source conforming to lua source syntax.
|
* @param stream InputStream representing the text source conforming to lua source syntax.
|
||||||
* @param chunkname String name of the chunk to use.
|
* @param chunkname String name of the chunk to use.
|
||||||
@@ -250,59 +97,64 @@ public class LuaC extends Lua implements Globals.Compiler, Globals.Loader {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public Prototype compile(InputStream stream, String chunkname) throws IOException {
|
public Prototype compile(InputStream stream, String chunkname) throws IOException {
|
||||||
return (new LuaC(new Hashtable())).luaY_parser(stream, chunkname);
|
return (new CompileState()).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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaFunction load(Prototype prototype, String chunkname, LuaValue env) throws IOException {
|
public LuaFunction load(Prototype prototype, String chunkname, LuaValue env) throws IOException {
|
||||||
return new LuaClosure(prototype, env);
|
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;
|
int r;
|
||||||
if ( ( r = f.read(b,0,b.length) ) < 0 )
|
if ( ( r = f.read(b,0,b.length) ) < 0 )
|
||||||
return NIL;
|
return NIL;
|
||||||
return LuaString.valueOf(b, 0, r);
|
return LuaString.valueUsing(b, 0, r);
|
||||||
}
|
}
|
||||||
public static LuaValue freaduntil(File f,boolean lineonly) throws IOException {
|
public static LuaValue freaduntil(File f,boolean lineonly) throws IOException {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
@@ -580,7 +580,7 @@ public class IoLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
return ( c < 0 && baos.size() == 0 )?
|
return ( c < 0 && baos.size() == 0 )?
|
||||||
(LuaValue) NIL:
|
(LuaValue) NIL:
|
||||||
(LuaValue) LuaString.valueOf(baos.toByteArray());
|
(LuaValue) LuaString.valueUsing(baos.toByteArray());
|
||||||
}
|
}
|
||||||
public static LuaValue freadline(File f) throws IOException {
|
public static LuaValue freadline(File f) throws IOException {
|
||||||
return freaduntil(f,true);
|
return freaduntil(f,true);
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ public class StringLib extends TwoArgFunction {
|
|||||||
if (c<0 || c>=256) argerror(a, "invalid value");
|
if (c<0 || c>=256) argerror(a, "invalid value");
|
||||||
bytes[i] = (byte) c;
|
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();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
try {
|
try {
|
||||||
DumpState.dump( ((LuaClosure)f).p, baos, true );
|
DumpState.dump( ((LuaClosure)f).p, baos, true );
|
||||||
return LuaString.valueOf(baos.toByteArray());
|
return LuaString.valueUsing(baos.toByteArray());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
return error( e.getMessage() );
|
return error( e.getMessage() );
|
||||||
}
|
}
|
||||||
@@ -658,7 +658,7 @@ public class StringLib extends TwoArgFunction {
|
|||||||
for ( int offset = 0; offset < bytes.length; offset += len ) {
|
for ( int offset = 0; offset < bytes.length; offset += len ) {
|
||||||
s.copyInto( 0, bytes, 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];
|
byte[] b = new byte[n];
|
||||||
for ( int i=0, j=n-1; i<n; i++, j-- )
|
for ( int i=0, j=n-1; i<n; i++, j-- )
|
||||||
b[j] = (byte) s.luaByte(i);
|
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) {
|
public static LuaString quoteString(String image) {
|
||||||
String s = image.substring(1, image.length()-1);
|
String s = image.substring(1, image.length()-1);
|
||||||
byte[] bytes = unquote(s);
|
byte[] bytes = unquote(s);
|
||||||
return LuaString.valueOf(bytes);
|
return LuaString.valueUsing(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LuaString charString(String image) {
|
public static LuaString charString(String image) {
|
||||||
String s = image.substring(1, image.length()-1);
|
String s = image.substring(1, image.length()-1);
|
||||||
byte[] bytes = unquote(s);
|
byte[] bytes = unquote(s);
|
||||||
return LuaString.valueOf(bytes);
|
return LuaString.valueUsing(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LuaString longString(String image) {
|
public static LuaString longString(String image) {
|
||||||
int i = image.indexOf('[', image.indexOf('[')+1)+1;
|
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);
|
byte[] b = iso88591bytes(s);
|
||||||
return LuaString.valueOf(b);
|
return LuaString.valueUsing(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] iso88591bytes( String s ) {
|
public static byte[] iso88591bytes( String s ) {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
version: 3.0
|
version: 3.0.1
|
||||||
Reference in New Issue
Block a user