diff --git a/src/core/org/luaj/vm2/Buffer.java b/src/core/org/luaj/vm2/Buffer.java index ca875646..319449b5 100644 --- a/src/core/org/luaj/vm2/Buffer.java +++ b/src/core/org/luaj/vm2/Buffer.java @@ -104,6 +104,18 @@ public final class Buffer { return this; } + public Buffer concatTo(LuaValue lhs) { + return setvalue(lhs.concat(value())); + } + + public Buffer concatTo(LuaString lhs) { + return value!=null? setvalue(lhs.concat(value)): prepend(lhs); + } + + public Buffer concatTo(LuaNumber lhs) { + return value!=null? setvalue(lhs.concat(value)): prepend(lhs.strvalue()); + } + public Buffer prepend(LuaString s) { int n = s.m_length; makeroom( n, 0 ); diff --git a/src/core/org/luaj/vm2/LuaNumber.java b/src/core/org/luaj/vm2/LuaNumber.java index dfe972e8..d8d19a66 100644 --- a/src/core/org/luaj/vm2/LuaNumber.java +++ b/src/core/org/luaj/vm2/LuaNumber.java @@ -63,7 +63,7 @@ public class LuaNumber extends LuaValue { } public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); } - public Buffer concat(Buffer rhs) { return concat(rhs.value()).buffer(); } + public Buffer concat(Buffer rhs) { return rhs.concatTo(this); } public LuaValue concatTo(LuaNumber lhs) { return strvalue().concatTo(lhs.strvalue()); } public LuaValue concatTo(LuaString lhs) { return strvalue().concatTo(lhs); } diff --git a/src/core/org/luaj/vm2/LuaString.java b/src/core/org/luaj/vm2/LuaString.java index 0d8a596b..5a90ff95 100644 --- a/src/core/org/luaj/vm2/LuaString.java +++ b/src/core/org/luaj/vm2/LuaString.java @@ -156,7 +156,7 @@ public class LuaString extends LuaValue { // concatenation public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); } - public Buffer concat(Buffer rhs) { return rhs.prepend(this); } + public Buffer concat(Buffer rhs) { return rhs.concatTo(this); } public LuaValue concatTo(LuaNumber lhs) { return concatTo(lhs.strvalue()); } public LuaValue concatTo(LuaString lhs) { byte[] b = new byte[lhs.m_length+this.m_length]; diff --git a/src/core/org/luaj/vm2/LuaValue.java b/src/core/org/luaj/vm2/LuaValue.java index bca79457..abc30fbf 100644 --- a/src/core/org/luaj/vm2/LuaValue.java +++ b/src/core/org/luaj/vm2/LuaValue.java @@ -350,7 +350,7 @@ public class LuaValue extends Varargs { public LuaValue concatTo(LuaNumber lhs) { return lhs.concatmt(this); } public LuaValue concatTo(LuaString lhs) { return lhs.concatmt(this); } public Buffer buffer() { return new Buffer(this); } - public Buffer concat(Buffer rhs) { return rhs.setvalue(concat(rhs.value())); } + public Buffer concat(Buffer rhs) { return rhs.concatTo(this); } public LuaValue concatmt(LuaValue rhs) { LuaValue h=metatag(CONCAT); if ( h.isnil() && (h=rhs.metatag(CONCAT)).isnil()) diff --git a/src/jse/org/luaj/vm2/lua2java/JavaCodeGen.java b/src/jse/org/luaj/vm2/lua2java/JavaCodeGen.java index 7b59c45b..0cc63cda 100644 --- a/src/jse/org/luaj/vm2/lua2java/JavaCodeGen.java +++ b/src/jse/org/luaj/vm2/lua2java/JavaCodeGen.java @@ -583,14 +583,19 @@ public class JavaCodeGen { case Lua.OP_NEQ: out(evalLuaValue(exp.lhs)+".neq("+evalLuaValue(exp.rhs)+")"); return; case Lua.OP_CONCAT: if ( isConcatExp(exp.rhs) ) { - out( "new Buffer().append("+evalLuaValue(exp.lhs)+")" ); + out( evalLuaValue(exp.lhs) ); Exp e = exp.rhs; - for ( ; isConcatExp(e); e=((BinopExp)e).rhs ) - out( ".append("+evalLuaValue(((BinopExp)e).lhs)+")" ); - out( ".append("+evalLuaValue(e)+")" ); - out( ".tostring()" ); - } else - out(evalLuaValue(exp.lhs)+".concat("+evalLuaValue(exp.rhs)+")"); + String close = ""; + for ( ; isConcatExp(e); e=((BinopExp)e).rhs ) { + out( ".concat("+evalLuaValue(((BinopExp)e).lhs) ); + close += ')'; + } + out( ".concat("+evalLuaValue(e)+".buffer())" ); + out( close ); + out( ".value()" ); + } else { + out(evalLuaValue(exp.lhs)+".concat("+evalLuaValue(exp.rhs)+")"); + } return; default: throw new IllegalStateException("unknown bin op:"+exp.op); } diff --git a/src/jse/org/luaj/vm2/luajc/JavaBuilder.java b/src/jse/org/luaj/vm2/luajc/JavaBuilder.java index 267fb2b5..2a79bb6e 100644 --- a/src/jse/org/luaj/vm2/luajc/JavaBuilder.java +++ b/src/jse/org/luaj/vm2/luajc/JavaBuilder.java @@ -109,7 +109,6 @@ public class JavaBuilder { private static final Type[] ARG_TYPES_STRING = { Type.STRING }; private static final Type[] ARG_TYPES_CHARARRAY = { TYPE_CHARARRAY }; private static final Type[] ARG_TYPES_VARARGS_INT = { TYPE_VARARGS, Type.INT }; - private static final Type[] ARG_TYPES_LUASTRING = { TYPE_LUASTRING }; private static final Type[] ARG_TYPES_INT_LUAVALUE = { Type.INT, TYPE_LUAVALUE }; private static final Type[] ARG_TYPES_INT_VARARGS = { Type.INT, TYPE_VARARGS }; private static final Type[] ARG_TYPES_LUAVALUE_VARARGS = { TYPE_LUAVALUE, TYPE_VARARGS }; @@ -121,6 +120,7 @@ public class JavaBuilder { private static final Type[] ARG_TYPES_LUAVALUE_LUAVALUE = { TYPE_LUAVALUE, TYPE_LUAVALUE }; private static final Type[] ARG_TYPES_INT_INT = { Type.INT, Type.INT }; private static final Type[] ARG_TYPES_LUAVALUE = { TYPE_LUAVALUE }; + private static final Type[] ARG_TYPES_BUFFER = { TYPE_BUFFER }; // names, arg types for main prototype classes private static final String[] SUPER_NAME_N = { STR_FUNC0, STR_FUNC1, STR_FUNC2, STR_FUNC3, STR_FUNCV, }; @@ -773,14 +773,19 @@ public class JavaBuilder { append(factory.createInvoke(STR_LUAVALUE, "rawsetlist", Type.VOID, ARG_TYPES_INT_VARARGS, Constants.INVOKEVIRTUAL)); } - public void newBuffer() { - append(factory.createNew(TYPE_BUFFER)); - append(InstructionConstants.DUP); - append(factory.createInvoke(STR_BUFFER, "", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); + public void concatvalue() { + append(factory.createInvoke(STR_LUAVALUE, "concat", TYPE_LUAVALUE, ARG_TYPES_LUAVALUE, Constants.INVOKEVIRTUAL)); + } + + public void concatbuffer() { + append(factory.createInvoke(STR_LUAVALUE, "concat", TYPE_BUFFER, ARG_TYPES_BUFFER, Constants.INVOKEVIRTUAL)); } - public void appendBuffer() { - append(factory.createInvoke(STR_LUAVALUE, "checkstring", TYPE_LUASTRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); - append(factory.createInvoke(STR_BUFFER, "append", TYPE_BUFFER, ARG_TYPES_LUASTRING, Constants.INVOKEVIRTUAL)); + public void tobuffer() { + append(factory.createInvoke(STR_LUAVALUE, "buffer", TYPE_BUFFER, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); + } + + public void tovalue() { + append(factory.createInvoke(STR_BUFFER, "value", TYPE_LUAVALUE, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); } } diff --git a/src/jse/org/luaj/vm2/luajc/JavaGen.java b/src/jse/org/luaj/vm2/luajc/JavaGen.java index 7d56dbab..95ec1b11 100644 --- a/src/jse/org/luaj/vm2/luajc/JavaGen.java +++ b/src/jse/org/luaj/vm2/luajc/JavaGen.java @@ -21,6 +21,7 @@ ******************************************************************************/ package org.luaj.vm2.luajc; +import org.luaj.vm2.Buffer; import org.luaj.vm2.Lua; import org.luaj.vm2.Prototype; @@ -180,12 +181,16 @@ public class JavaGen { break; case Lua.OP_CONCAT: /* A B C R(A):= R(B).. ... ..R(C) */ - builder.newBuffer(); - while ( b<=c ) { - builder.loadLocal(pc, b++); - builder.appendBuffer(); + for ( int k=b; k<=c; k++ ) + builder.loadLocal(pc, k); + if ( c > b+1 ) { + builder.tobuffer(); + for ( int k=c; --k>=b; ) + builder.concatbuffer(); + builder.tovalue(); + } else { + builder.concatvalue(); } - builder.tostring(); builder.storeLocal(pc, a); break;