Refactor concat, add __concat metatag
This commit is contained in:
@@ -28,9 +28,12 @@ package org.luaj.vm2;
|
|||||||
*/
|
*/
|
||||||
public final class Buffer {
|
public final class Buffer {
|
||||||
private static final int DEFAULT_CAPACITY = 64;
|
private static final int DEFAULT_CAPACITY = 64;
|
||||||
|
private static final byte[] NOBYTES = {};
|
||||||
|
|
||||||
private byte[] bytes;
|
private byte[] bytes;
|
||||||
private int length;
|
private int length;
|
||||||
|
private int offset;
|
||||||
|
private LuaValue value;
|
||||||
|
|
||||||
public Buffer() {
|
public Buffer() {
|
||||||
this(DEFAULT_CAPACITY);
|
this(DEFAULT_CAPACITY);
|
||||||
@@ -39,63 +42,98 @@ public final class Buffer {
|
|||||||
public Buffer( int initialCapacity ) {
|
public Buffer( int initialCapacity ) {
|
||||||
bytes = new byte[ initialCapacity ];
|
bytes = new byte[ initialCapacity ];
|
||||||
length = 0;
|
length = 0;
|
||||||
|
offset = 0;
|
||||||
|
value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final String tojstring() {
|
public Buffer(LuaValue value) {
|
||||||
return LuaString.valueOf(bytes, 0, length).tojstring();
|
bytes = NOBYTES;
|
||||||
|
length = offset = 0;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LuaValue value() {
|
||||||
|
return value != null? value: this.tostring();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Buffer setvalue(LuaValue value) {
|
||||||
|
bytes = NOBYTES;
|
||||||
|
offset = length = 0;
|
||||||
|
this.value = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final LuaString tostring() {
|
||||||
|
realloc( length, 0 );
|
||||||
|
return LuaString.valueOf( bytes, offset, length );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String tojstring() {
|
||||||
|
return value().tojstring();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return tojstring();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Buffer append( byte b ) {
|
public final Buffer append( byte b ) {
|
||||||
ensureCapacity( length + 1 );
|
makeroom( 0, 1 );
|
||||||
bytes[ length++ ] = b;
|
bytes[ offset + length++ ] = b;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Buffer append( LuaValue val ) {
|
public final Buffer append( LuaValue val ) {
|
||||||
if ( ! val.isstring() )
|
|
||||||
val.error("attempt to concatenate a '"+val.typename()+"' value");
|
|
||||||
append( val.strvalue() );
|
append( val.strvalue() );
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Buffer append( LuaString str ) {
|
public final Buffer append( LuaString str ) {
|
||||||
final int alen = str.length();
|
final int n = str.m_length;
|
||||||
ensureCapacity( length + alen );
|
makeroom( 0, n );
|
||||||
str.copyInto( 0, bytes, length, alen );
|
str.copyInto( 0, bytes, offset + length, n );
|
||||||
length += alen;
|
length += n;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Buffer append( String str ) {
|
public final Buffer append( String str ) {
|
||||||
char[] chars = str.toCharArray();
|
char[] chars = str.toCharArray();
|
||||||
final int alen = LuaString.lengthAsUtf8( chars );
|
final int n = LuaString.lengthAsUtf8( chars );
|
||||||
ensureCapacity( length + alen );
|
makeroom( 0, n );
|
||||||
LuaString.encodeToUtf8( chars, bytes, length );
|
LuaString.encodeToUtf8( chars, bytes, offset + length );
|
||||||
length += alen;
|
length += n;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setLength( int length ) {
|
public Buffer prepend(LuaString s) {
|
||||||
ensureCapacity( length );
|
int n = s.m_length;
|
||||||
this.length = length;
|
makeroom( n, 0 );
|
||||||
|
System.arraycopy( s.m_bytes, s.m_offset, bytes, offset-n, n );
|
||||||
|
offset -= n;
|
||||||
|
length += n;
|
||||||
|
value = null;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final LuaString tostring() {
|
public final void makeroom( int nbefore, int nafter ) {
|
||||||
return LuaString.valueOf( realloc( bytes, length ) );
|
if ( value != null ) {
|
||||||
|
LuaString s = value.strvalue();
|
||||||
|
value = null;
|
||||||
|
bytes = new byte[nbefore+s.m_length+nafter];
|
||||||
|
length = s.m_length;
|
||||||
|
offset = nbefore;
|
||||||
|
System.arraycopy(s.m_bytes, s.m_offset, bytes, offset, length);
|
||||||
|
} else if ( offset+length+nafter > bytes.length || offset<nbefore ) {
|
||||||
|
realloc( Math.max(nbefore+length+nafter,length*2), nbefore );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void ensureCapacity( int minSize ) {
|
private final void realloc( int newSize, int newOffset ) {
|
||||||
if ( minSize > bytes.length )
|
if ( newSize != bytes.length ) {
|
||||||
realloc( minSize );
|
|
||||||
}
|
|
||||||
|
|
||||||
private final void realloc( int minSize ) {
|
|
||||||
bytes = realloc( bytes, Math.max( bytes.length * 2, minSize ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
private final static byte[] realloc( byte[] b, int newSize ) {
|
|
||||||
byte[] newBytes = new byte[ newSize ];
|
byte[] newBytes = new byte[ newSize ];
|
||||||
System.arraycopy( b, 0, newBytes, 0, Math.min( b.length, newSize ) );
|
System.arraycopy( bytes, offset, newBytes, newOffset, length );
|
||||||
return newBytes;
|
bytes = newBytes;
|
||||||
|
offset = newOffset;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -236,10 +236,14 @@ public class LuaClosure extends LuaFunction {
|
|||||||
b = i>>>23;
|
b = i>>>23;
|
||||||
c = (i>>14)&0x1ff;
|
c = (i>>14)&0x1ff;
|
||||||
{
|
{
|
||||||
Buffer sb = new Buffer();
|
LuaValue r = stack[c-1].concat(stack[c]);
|
||||||
for ( ; b<=c; )
|
if ( (c-=2) >= b ) {
|
||||||
sb.append( stack[b++] );
|
Buffer sb = r.buffer();
|
||||||
stack[a] = sb.tostring();
|
while ( c>=b )
|
||||||
|
sb = stack[c--].concat(sb);
|
||||||
|
r = sb.value();
|
||||||
|
}
|
||||||
|
stack[a] = r;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -149,10 +149,6 @@ public class LuaDouble extends LuaNumber {
|
|||||||
// string comparison
|
// string comparison
|
||||||
public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; }
|
public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; }
|
||||||
|
|
||||||
// concatenation
|
|
||||||
public String concat_s(LuaValue rhs) { return rhs.concatTo_s(Double.toString(v)); }
|
|
||||||
public String concatTo_s(String lhs) { return lhs + v; }
|
|
||||||
|
|
||||||
public String tojstring() {
|
public String tojstring() {
|
||||||
/*
|
/*
|
||||||
if ( v == 0.0 ) { // never occurs in J2me
|
if ( v == 0.0 ) { // never occurs in J2me
|
||||||
|
|||||||
@@ -165,10 +165,6 @@ public class LuaInteger extends LuaNumber {
|
|||||||
// string comparison
|
// string comparison
|
||||||
public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; }
|
public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; }
|
||||||
|
|
||||||
// concatenation
|
|
||||||
public String concat_s(LuaValue rhs) { return rhs.concatTo_s(Integer.toString(v)); }
|
|
||||||
public String concatTo_s(String lhs) { return lhs + v; }
|
|
||||||
|
|
||||||
public int checkint() {
|
public int checkint() {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,4 +61,10 @@ public class LuaNumber extends LuaValue {
|
|||||||
public LuaValue getmetatable() {
|
public LuaValue getmetatable() {
|
||||||
return s_metatable;
|
return s_metatable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); }
|
||||||
|
public Buffer concat(Buffer rhs) { return rhs.prepend(this.strvalue()); }
|
||||||
|
public LuaValue concatTo(LuaNumber lhs) { return strvalue().concatTo(lhs.strvalue()); }
|
||||||
|
public LuaValue concatTo(LuaString lhs) { return strvalue().concatTo(lhs); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,8 +155,15 @@ public class LuaString extends LuaValue {
|
|||||||
public boolean gteq_b( double rhs ) { typerror("attempt to compare string with number"); return false; }
|
public boolean gteq_b( double rhs ) { typerror("attempt to compare string with number"); return false; }
|
||||||
|
|
||||||
// concatenation
|
// concatenation
|
||||||
public String concat_s(LuaValue rhs) { return rhs.concatTo_s(tojstring()); }
|
public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); }
|
||||||
public String concatTo_s(String lhs) { return lhs + tojstring(); }
|
public Buffer concat(Buffer rhs) { return rhs.prepend(this); }
|
||||||
|
public LuaValue concatTo(LuaNumber lhs) { return concatTo(lhs.strvalue()); }
|
||||||
|
public LuaValue concatTo(LuaString lhs) {
|
||||||
|
byte[] b = new byte[lhs.m_length+this.m_length];
|
||||||
|
System.arraycopy(lhs.m_bytes, lhs.m_offset, b, 0, lhs.m_length);
|
||||||
|
System.arraycopy(this.m_bytes, this.m_offset, b, lhs.m_length, this.m_length);
|
||||||
|
return new LuaString(b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
// string comparison
|
// string comparison
|
||||||
public int strcmp(LuaValue lhs) { return -lhs.strcmp(this); }
|
public int strcmp(LuaValue lhs) { return -lhs.strcmp(this); }
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ public class LuaValue extends Varargs {
|
|||||||
public static final LuaString LT = valueOf("__lt");
|
public static final LuaString LT = valueOf("__lt");
|
||||||
public static final LuaString LE = valueOf("__le");
|
public static final LuaString LE = valueOf("__le");
|
||||||
public static final LuaString TOSTRING = valueOf("__tostring");
|
public static final LuaString TOSTRING = valueOf("__tostring");
|
||||||
|
public static final LuaString CONCAT = valueOf("__concat");
|
||||||
public static final LuaString EMPTYSTRING = valueOf("");
|
public static final LuaString EMPTYSTRING = valueOf("");
|
||||||
|
|
||||||
private static int MAXSTACK = 250;
|
private static int MAXSTACK = 250;
|
||||||
@@ -343,9 +344,20 @@ public class LuaValue extends Varargs {
|
|||||||
public int strcmp( LuaString rhs ) { error("attempt to compare "+typename()); return 0; }
|
public int strcmp( LuaString rhs ) { error("attempt to compare "+typename()); return 0; }
|
||||||
|
|
||||||
// concatenation
|
// concatenation
|
||||||
public LuaValue concat( LuaValue rhs ) { return valueOf(concat_s(rhs)); }
|
public LuaValue concat(LuaValue rhs) { return this.concatmt(rhs); }
|
||||||
public String concat_s( LuaValue rhs ) { error("attempt to concatenate "+this.typename()); return null; }
|
public LuaValue concatTo(LuaNumber lhs) { return lhs.concatmt(this); }
|
||||||
public String concatTo_s( String lhs ) { error("attempt to concatenate "+this.typename()); return null; }
|
public LuaValue concatTo(LuaString lhs) { return lhs.concatmt(this); }
|
||||||
|
public Buffer buffer() { return new Buffer(this); }
|
||||||
|
public Buffer concat(Buffer rhs) {
|
||||||
|
return rhs.setvalue(checkmetatag(CONCAT,"attempt to concatenate ").call(this, rhs.value()));
|
||||||
|
}
|
||||||
|
public LuaValue concatmt(LuaValue rhs) {
|
||||||
|
LuaValue h=metatag(CONCAT);
|
||||||
|
LuaValue v=this;
|
||||||
|
if ( h.isnil() || (h=(v=rhs).metatag(CONCAT)).isnil())
|
||||||
|
v.typerror("attempt to concatenate ");
|
||||||
|
return h.call(this,rhs);
|
||||||
|
}
|
||||||
|
|
||||||
// boolean operators
|
// boolean operators
|
||||||
public LuaValue and( LuaValue rhs ) { return this.toboolean()? rhs: this; }
|
public LuaValue and( LuaValue rhs ) { return this.toboolean()? rhs: this; }
|
||||||
@@ -577,5 +589,4 @@ public class LuaValue extends Varargs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1116,23 +1116,23 @@ public class TypeTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testCheckJavaString() {
|
public void testCheckJavaString() {
|
||||||
throwsErrorReq( somenil, "checkString" );
|
throwsErrorReq( somenil, "checkjstring" );
|
||||||
throwsErrorReq( sometrue, "checkString" );
|
throwsErrorReq( sometrue, "checkjstring" );
|
||||||
throwsErrorReq( somefalse, "checkString" );
|
throwsErrorReq( somefalse, "checkjstring" );
|
||||||
assertEquals( String.valueOf(zero), zero.checkjstring() );
|
assertEquals( String.valueOf(zero), zero.checkjstring() );
|
||||||
assertEquals( String.valueOf(intint), intint.checkjstring() );
|
assertEquals( String.valueOf(intint), intint.checkjstring() );
|
||||||
assertEquals( String.valueOf(longdouble), longdouble.checkjstring() );
|
assertEquals( String.valueOf(longdouble), longdouble.checkjstring() );
|
||||||
assertEquals( String.valueOf(doubledouble), doubledouble.checkjstring() );
|
assertEquals( String.valueOf(doubledouble), doubledouble.checkjstring() );
|
||||||
throwsErrorReq( somefunc, "checkString" );
|
throwsErrorReq( somefunc, "checkjstring" );
|
||||||
throwsErrorReq( someclosure, "checkString" );
|
throwsErrorReq( someclosure, "checkjstring" );
|
||||||
assertEquals( samplestringstring, stringstring.checkjstring() );
|
assertEquals( samplestringstring, stringstring.checkjstring() );
|
||||||
assertEquals( samplestringint, stringint.checkjstring() );
|
assertEquals( samplestringint, stringint.checkjstring() );
|
||||||
assertEquals( samplestringlong, stringlong.checkjstring() );
|
assertEquals( samplestringlong, stringlong.checkjstring() );
|
||||||
assertEquals( samplestringdouble, stringdouble.checkjstring() );
|
assertEquals( samplestringdouble, stringdouble.checkjstring() );
|
||||||
throwsErrorReq( thread, "checkString" );
|
throwsErrorReq( thread, "checkjstring" );
|
||||||
throwsErrorReq( table, "checkString" );
|
throwsErrorReq( table, "checkjstring" );
|
||||||
throwsErrorReq( userdataobj, "checkString" );
|
throwsErrorReq( userdataobj, "checkjstring" );
|
||||||
throwsErrorReq( userdatacls, "checkString" );
|
throwsErrorReq( userdatacls, "checkjstring" );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCheckLuaString() {
|
public void testCheckLuaString() {
|
||||||
|
|||||||
@@ -572,4 +572,78 @@ public class UnaryBinaryOperatorsTest extends TestCase {
|
|||||||
assertEquals(t, aaa.lteq(aaa));
|
assertEquals(t, aaa.lteq(aaa));
|
||||||
assertEquals(t, aaa.gteq(aaa));
|
assertEquals(t, aaa.gteq(aaa));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testBuffer() {
|
||||||
|
LuaValue abc = LuaValue.valueOf("abcdefghi").substring(0,3);
|
||||||
|
LuaValue def = LuaValue.valueOf("abcdefghi").substring(3,6);
|
||||||
|
LuaValue ghi = LuaValue.valueOf("abcdefghi").substring(6,9);
|
||||||
|
LuaValue n123 = LuaValue.valueOf(123);
|
||||||
|
|
||||||
|
// basic append
|
||||||
|
Buffer b = new Buffer(); assertEquals( "", b.value().tojstring() );
|
||||||
|
b.append(def); assertEquals( "def", b.value().tojstring() );
|
||||||
|
b.append(abc); assertEquals( "defabc", b.value().tojstring() );
|
||||||
|
b.append(ghi); assertEquals( "defabcghi", b.value().tojstring() );
|
||||||
|
b.append(n123); assertEquals( "defabcghi123", b.value().tojstring() );
|
||||||
|
|
||||||
|
// basic prepend
|
||||||
|
b = new Buffer(); assertEquals( "", b.value().tojstring() );
|
||||||
|
b.prepend(def.strvalue()); assertEquals( "def", b.value().tojstring() );
|
||||||
|
b.prepend(ghi.strvalue()); assertEquals( "ghidef", b.value().tojstring() );
|
||||||
|
b.prepend(abc.strvalue()); assertEquals( "abcghidef", b.value().tojstring() );
|
||||||
|
b.prepend(n123.strvalue()); assertEquals( "123abcghidef", b.value().tojstring() );
|
||||||
|
|
||||||
|
// mixed append, prepend
|
||||||
|
b = new Buffer(); assertEquals( "", b.value().tojstring() );
|
||||||
|
b.append(def); assertEquals( "def", b.value().tojstring() );
|
||||||
|
b.append(abc); assertEquals( "defabc", b.value().tojstring() );
|
||||||
|
b.prepend(ghi.strvalue()); assertEquals( "ghidefabc", b.value().tojstring() );
|
||||||
|
b.prepend(n123.strvalue()); assertEquals( "123ghidefabc", b.value().tojstring() );
|
||||||
|
b.append(def); assertEquals( "123ghidefabcdef", b.value().tojstring() );
|
||||||
|
b.append(abc); assertEquals( "123ghidefabcdefabc", b.value().tojstring() );
|
||||||
|
b.prepend(ghi.strvalue()); assertEquals( "ghi123ghidefabcdefabc", b.value().tojstring() );
|
||||||
|
b.prepend(n123.strvalue()); assertEquals( "123ghi123ghidefabcdefabc", b.value().tojstring() );
|
||||||
|
|
||||||
|
// value
|
||||||
|
b = new Buffer(def); assertEquals( "def", b.value().tojstring() );
|
||||||
|
b.append(abc); assertEquals( "defabc", b.value().tojstring() );
|
||||||
|
b.prepend(ghi.strvalue()); assertEquals( "ghidefabc", b.value().tojstring() );
|
||||||
|
b.setvalue(def); assertEquals( "def", b.value().tojstring() );
|
||||||
|
b.prepend(ghi.strvalue()); assertEquals( "ghidef", b.value().tojstring() );
|
||||||
|
b.append(abc); assertEquals( "ghidefabc", b.value().tojstring() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConcat() {
|
||||||
|
LuaValue abc = LuaValue.valueOf("abcdefghi").substring(0,3);
|
||||||
|
LuaValue def = LuaValue.valueOf("abcdefghi").substring(3,6);
|
||||||
|
LuaValue ghi = LuaValue.valueOf("abcdefghi").substring(6,9);
|
||||||
|
LuaValue n123 = LuaValue.valueOf(123);
|
||||||
|
|
||||||
|
assertEquals( "abc", abc.tojstring() );
|
||||||
|
assertEquals( "def", def.tojstring() );
|
||||||
|
assertEquals( "ghi", ghi.tojstring() );
|
||||||
|
assertEquals( "123", n123.tojstring() );
|
||||||
|
assertEquals( "abcabc", abc.concat(abc).tojstring() );
|
||||||
|
assertEquals( "defghi", def.concat(ghi).tojstring() );
|
||||||
|
assertEquals( "ghidef", ghi.concat(def).tojstring() );
|
||||||
|
assertEquals( "ghidefabcghi", ghi.concat(def).concat(abc).concat(ghi).tojstring() );
|
||||||
|
assertEquals( "123def", n123.concat(def).tojstring() );
|
||||||
|
assertEquals( "def123", def.concat(n123).tojstring() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConcatBuffer() {
|
||||||
|
LuaValue abc = LuaValue.valueOf("abcdefghi").substring(0,3);
|
||||||
|
LuaValue def = LuaValue.valueOf("abcdefghi").substring(3,6);
|
||||||
|
LuaValue ghi = LuaValue.valueOf("abcdefghi").substring(6,9);
|
||||||
|
LuaValue n123 = LuaValue.valueOf(123);
|
||||||
|
Buffer b;
|
||||||
|
|
||||||
|
b = new Buffer(def); assertEquals( "def", b.value().tojstring() );
|
||||||
|
b = ghi.concat(b); assertEquals( "ghidef", b.value().tojstring() );
|
||||||
|
b = abc.concat(b); assertEquals( "abcghidef", b.value().tojstring() );
|
||||||
|
b = n123.concat(b); assertEquals( "123abcghidef", b.value().tojstring() );
|
||||||
|
b.setvalue(n123);
|
||||||
|
b = def.concat(b); assertEquals( "def123", b.value().tojstring() );
|
||||||
|
b = abc.concat(b); assertEquals( "abcdef123", b.value().tojstring() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ local mt = {
|
|||||||
__metatable={},
|
__metatable={},
|
||||||
__index=buildop('index'),
|
__index=buildop('index'),
|
||||||
__newindex=buildop('newindex'),
|
__newindex=buildop('newindex'),
|
||||||
|
__concat=buildop('concat'),
|
||||||
}
|
}
|
||||||
|
|
||||||
-- pcall a function and check for a pattern in the error string
|
-- pcall a function and check for a pattern in the error string
|
||||||
@@ -118,8 +119,9 @@ end
|
|||||||
print( '---- __eq, __lt, __le, same types' )
|
print( '---- __eq, __lt, __le, same types' )
|
||||||
local bfunction = function() end
|
local bfunction = function() end
|
||||||
local bthread = coroutine.create( bfunction )
|
local bthread = coroutine.create( bfunction )
|
||||||
|
local btable = {}
|
||||||
local groups
|
local groups
|
||||||
groups = { {afunction, bfunction}, {true, true}, {true, false}, {afunction, bfunction}, {athread, bthread}, {atable, atable}, {atable, {}} }
|
groups = { {true, true}, {true, false}, {afunction, bfunction}, {athread, bthread}, {atable, atable}, {atable, btable} }
|
||||||
for i=1,#groups do
|
for i=1,#groups do
|
||||||
local a,b = groups[i][1], groups[i][2]
|
local a,b = groups[i][1], groups[i][2]
|
||||||
print( type(a), type(b), 'before', pcall( function() return a==b end ) )
|
print( type(a), type(b), 'before', pcall( function() return a==b end ) )
|
||||||
@@ -199,3 +201,32 @@ for i=1,#values do
|
|||||||
print( debug.setmetatable( a, nil ) )
|
print( debug.setmetatable( a, nil ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
print( '---- __concat' )
|
||||||
|
groups = { {atable, afunction}, {afunction, atable}, {123, nil}, {nil, 123} }
|
||||||
|
local s,t,u = 'sss',777
|
||||||
|
local concatresult = setmetatable( { '__concat-result' }, {
|
||||||
|
__tostring=function()
|
||||||
|
return 'concat-string-result'
|
||||||
|
end } )
|
||||||
|
local concatmt = {
|
||||||
|
__concat=function(a,b)
|
||||||
|
print( 'mt.__concat('..type(a)..','..type(b)..')', a, b )
|
||||||
|
return concatresult
|
||||||
|
end
|
||||||
|
}
|
||||||
|
for i=1,#groups do
|
||||||
|
local a,b = groups[i][1], groups[i][2]
|
||||||
|
print( type(a), type(b), 'before', ecall( 'attempt to concatenate ', function() return a..b end ) )
|
||||||
|
print( type(a), type(b), 'before', ecall( 'attempt to concatenate ', function() return b..a end ) )
|
||||||
|
print( type(a), type(s), type(t), 'before', ecall( 'attempt to concatenate ', function() return a..s..t end ) )
|
||||||
|
print( type(s), type(a), type(t), 'before', ecall( 'attempt to concatenate ', function() return s..a..t end ) )
|
||||||
|
print( type(s), type(t), type(a), 'before', ecall( 'attempt to concatenate ', function() return s..t..a end ) )
|
||||||
|
print( debug.setmetatable( a, concatmt ) )
|
||||||
|
print( type(a), type(b), 'after', pcall( function() return a..b end ) )
|
||||||
|
print( type(a), type(b), 'after', pcall( function() return b..a end ) )
|
||||||
|
print( type(a), type(s), type(t), 'before', pcall( function() return a..s..t end ) )
|
||||||
|
print( type(s), type(a), type(t), 'before', ecall( 'attempt to concatenate ', function() return s..a..t end ) )
|
||||||
|
print( type(s), type(t), type(a), 'before', ecall( 'attempt to concatenate ', function() return s..t..a end ) )
|
||||||
|
print( debug.setmetatable( a, nil ) )
|
||||||
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user