+= for strings
This commit is contained in:
@@ -828,25 +828,44 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
private void generateAugmentedAssignment(JetBinaryExpression expression) {
|
private void generateAugmentedAssignment(JetBinaryExpression expression) {
|
||||||
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference());
|
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference());
|
||||||
final JetExpression lhs = expression.getLeft();
|
final JetExpression lhs = expression.getLeft();
|
||||||
Type asmType = expressionType(lhs);
|
Type lhsType = expressionType(lhs);
|
||||||
StackValue value = generateIntermediateValue(lhs);
|
if (isNumberPrimitive(lhsType)) {
|
||||||
value.dupReceiver(v);
|
StackValue value = generateIntermediateValue(lhs); // receiver
|
||||||
value.put(asmType, v);
|
value.dupReceiver(v, 0); // receiver receiver
|
||||||
genToJVMStack(expression.getRight());
|
value.put(lhsType, v); // receiver lhs
|
||||||
v.visitInsn(asmType.getOpcode(opcodeForMethod(op.getName())));
|
genToJVMStack(expression.getRight()); // receiver lhs rhs
|
||||||
value.store(v);
|
v.visitInsn(lhsType.getOpcode(opcodeForMethod(op.getName()))); // receiver result
|
||||||
|
value.store(v);
|
||||||
|
}
|
||||||
|
else if ("java.lang.String".equals(lhsType.getClassName()) && op.getName().equals("plus")) {
|
||||||
|
generateStringBuilderConstructor(); // StringBuilder
|
||||||
|
StackValue value = generateIntermediateValue(lhs); // StringBuilder receiver
|
||||||
|
value.dupReceiver(v, 1); // receiver StringBuilder receiver
|
||||||
|
value.put(lhsType, v); // receiver StringBuilder value
|
||||||
|
invokeAppendMethod(lhsType); // receiver StringBuilder
|
||||||
|
invokeAppend(expression.getRight()); // receiver StringBuilder
|
||||||
|
v.invokevirtual(CLASS_STRING_BUILDER, "toString", "()Ljava/lang/String;");
|
||||||
|
value.store(v);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException("Augmented assignment for non-primitive types not yet implemented");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateConcatenation(JetBinaryExpression expression) {
|
private void generateConcatenation(JetBinaryExpression expression) {
|
||||||
|
generateStringBuilderConstructor();
|
||||||
|
invokeAppend(expression.getLeft());
|
||||||
|
invokeAppend(expression.getRight());
|
||||||
|
v.invokevirtual(CLASS_STRING_BUILDER, "toString", "()Ljava/lang/String;");
|
||||||
|
myStack.push(StackValue.onStack(Type.getObjectType(CLASS_STRING)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateStringBuilderConstructor() {
|
||||||
Type type = Type.getObjectType(CLASS_STRING_BUILDER);
|
Type type = Type.getObjectType(CLASS_STRING_BUILDER);
|
||||||
v.anew(type);
|
v.anew(type);
|
||||||
v.dup();
|
v.dup();
|
||||||
Method method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
|
Method method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
|
||||||
v.invokespecial(CLASS_STRING_BUILDER, method.getName(), method.getDescriptor());
|
v.invokespecial(CLASS_STRING_BUILDER, method.getName(), method.getDescriptor());
|
||||||
invokeAppend(expression.getLeft());
|
|
||||||
invokeAppend(expression.getRight());
|
|
||||||
v.invokevirtual(CLASS_STRING_BUILDER, "toString", "()Ljava/lang/String;");
|
|
||||||
myStack.push(StackValue.onStack(Type.getObjectType(CLASS_STRING)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void invokeAppend(final JetExpression expr) {
|
private void invokeAppend(final JetExpression expr) {
|
||||||
@@ -860,6 +879,10 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
}
|
}
|
||||||
Type exprType = expressionType(expr);
|
Type exprType = expressionType(expr);
|
||||||
gen(expr, exprType);
|
gen(expr, exprType);
|
||||||
|
invokeAppendMethod(exprType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void invokeAppendMethod(Type exprType) {
|
||||||
Method appendDescriptor = new Method("append", Type.getObjectType(CLASS_STRING_BUILDER),
|
Method appendDescriptor = new Method("append", Type.getObjectType(CLASS_STRING_BUILDER),
|
||||||
new Type[] { exprType.getSort() == Type.OBJECT ? JetTypeMapper.TYPE_OBJECT : exprType});
|
new Type[] { exprType.getSort() == Type.OBJECT ? JetTypeMapper.TYPE_OBJECT : exprType});
|
||||||
v.invokevirtual(CLASS_STRING_BUILDER, "append", appendDescriptor.getDescriptor());
|
v.invokevirtual(CLASS_STRING_BUILDER, "append", appendDescriptor.getDescriptor());
|
||||||
@@ -934,7 +957,7 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
StackValue value = generateIntermediateValue(operand);
|
StackValue value = generateIntermediateValue(operand);
|
||||||
value.dupReceiver(v);
|
value.dupReceiver(v, 0);
|
||||||
value.put(asmType, v);
|
value.put(asmType, v);
|
||||||
if (asmType == Type.LONG_TYPE) {
|
if (asmType == Type.LONG_TYPE) {
|
||||||
v.aconst(Long.valueOf(increment));
|
v.aconst(Long.valueOf(increment));
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public abstract class StackValue {
|
|||||||
throw new UnsupportedOperationException("cannot store to value " + this);
|
throw new UnsupportedOperationException("cannot store to value " + this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dupReceiver(InstructionAdapter v) {
|
public void dupReceiver(InstructionAdapter v, int below) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
|
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
|
||||||
@@ -341,8 +341,13 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dupReceiver(InstructionAdapter v) {
|
public void dupReceiver(InstructionAdapter v, int below) {
|
||||||
v.dup2(); // array and index
|
if (below == 1) {
|
||||||
|
v.dup2X1();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v.dup2(); // array and index
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,8 +369,15 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dupReceiver(InstructionAdapter v) {
|
public void dupReceiver(InstructionAdapter v, int below) {
|
||||||
if (!isStatic) v.dup();
|
if (!isStatic) {
|
||||||
|
if (below == 1) {
|
||||||
|
v.dupX1();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v.dup();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
var collector: String = ""
|
||||||
|
set(it) { $collector += it }
|
||||||
|
|
||||||
|
fun append(s: String): String {
|
||||||
|
collector = s;
|
||||||
|
return collector;
|
||||||
|
}
|
||||||
@@ -259,6 +259,13 @@ public class NamespaceGenTest extends CodegenTestCase {
|
|||||||
assertEquals("jet Lang", main.invoke(null, "jet", " ", "Lang"));
|
assertEquals("jet Lang", main.invoke(null, "jet", " ", "Lang"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testStringPlusEq() throws Exception {
|
||||||
|
loadText("fun foo(s: String) { val result = s; result += s; return result; } ");
|
||||||
|
System.out.println(generateToText());
|
||||||
|
final Method main = generateFunction();
|
||||||
|
assertEquals("JarJar", main.invoke(null, "Jar"));
|
||||||
|
}
|
||||||
|
|
||||||
public void testStringCompare() throws Exception {
|
public void testStringCompare() throws Exception {
|
||||||
loadText("fun foo(s1: String, s2: String) = s1 < s2");
|
loadText("fun foo(s1: String, s2: String) = s1 < s2");
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
|
|||||||
@@ -81,6 +81,15 @@ public class PropertyGenTest extends CodegenTestCase {
|
|||||||
assertEquals(value, "IntelliJ IDEA");
|
assertEquals(value, "IntelliJ IDEA");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFieldSetterPlusEq() throws Exception {
|
||||||
|
loadFile("fieldSetterPlusEq.jet");
|
||||||
|
System.out.println(generateToText());
|
||||||
|
final Method method = generateFunction("append");
|
||||||
|
method.invoke(null, "IntelliJ ");
|
||||||
|
String value = (String) method.invoke(null, "IDEA");
|
||||||
|
assertEquals(value, "IntelliJ IDEA");
|
||||||
|
}
|
||||||
|
|
||||||
public void testAccessorsWithoutBody() throws Exception {
|
public void testAccessorsWithoutBody() throws Exception {
|
||||||
loadText("class AccessorsWithoutBody() { public var foo: Int = 349\n get\n private set\n fun setter() { foo = 610; } } ");
|
loadText("class AccessorsWithoutBody() { public var foo: Int = 349\n get\n private set\n fun setter() { foo = 610; } } ");
|
||||||
final Class aClass = loadImplementationClass(generateClassesInFile(), "AccessorsWithoutBody");
|
final Class aClass = loadImplementationClass(generateClassesInFile(), "AccessorsWithoutBody");
|
||||||
|
|||||||
Reference in New Issue
Block a user