diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java index 25800b0e85c..787436e23b1 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java @@ -382,4 +382,15 @@ public class CodegenUtil { new Type[] {exprType.getSort() == Type.OBJECT ? (exprType.equals(JAVA_STRING_TYPE) ? JAVA_STRING_TYPE : OBJECT_TYPE) : exprType}); v.invokevirtual("java/lang/StringBuilder", "append", appendDescriptor.getDescriptor()); } + + public static StackValue genToString(InstructionAdapter v, StackValue receiver) { + final int sort = receiver.type.getSort(); + + final Type type = sort == Type.OBJECT || sort == Type.ARRAY + ? AsmTypeConstants.OBJECT_TYPE + : sort == Type.BYTE || sort == Type.SHORT ? Type.INT_TYPE : receiver.type; + receiver.put(type, v); + v.invokestatic("java/lang/String", "valueOf", "(" + type.getDescriptor() + ")Ljava/lang/String;"); + return StackValue.onStack(JAVA_STRING_TYPE); + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 71b7a052b25..7e3b4d1b104 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -968,7 +968,13 @@ public class ExpressionCodegen extends JetVisitor implem @Override public StackValue visitStringTemplateExpression(JetStringTemplateExpression expression, StackValue receiver) { StringBuilder constantValue = new StringBuilder(""); - for (JetStringTemplateEntry entry : expression.getEntries()) { + final JetStringTemplateEntry[] entries = expression.getEntries(); + + if (entries.length == 1 && entries[0] instanceof JetStringTemplateEntryWithExpression) { + return genToString(v, gen(entries[0].getExpression())); + } + + for (JetStringTemplateEntry entry : entries) { if (entry instanceof JetLiteralStringTemplateEntry) { constantValue.append(entry.getText()); } @@ -986,7 +992,7 @@ public class ExpressionCodegen extends JetVisitor implem } else { generateStringBuilderConstructor(v); - for (JetStringTemplateEntry entry : expression.getEntries()) { + for (JetStringTemplateEntry entry : entries) { if (entry instanceof JetStringTemplateEntryWithExpression) { invokeAppend(entry.getExpression()); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index ac8c9aea936..ed4749b5556 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -62,8 +62,11 @@ public class IntrinsicMethods { public static final String KOTLIN_JAVA_CLASS_FUNCTION = "kotlin.javaClass.function"; public static final String KOTLIN_ARRAYS_ARRAY = "kotlin.arrays.array"; private static final String KOTLIN_JAVA_CLASS_PROPERTY = "kotlin.javaClass.property"; + private static final String KOTLIN_TO_STRING = "kotlin.toString"; + private static final String KOTLIN_HASH_CODE = "kotlin.hashCode"; private static final EnumValues ENUM_VALUES = new EnumValues(); private static final EnumValueOf ENUM_VALUE_OF = new EnumValueOf(); + public static final ToString TO_STRING = new ToString(); private final Map namedMethods = new HashMap(); private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator(); @@ -75,6 +78,8 @@ public class IntrinsicMethods { namedMethods.put(KOTLIN_JAVA_CLASS_FUNCTION, new JavaClassFunction()); namedMethods.put(KOTLIN_JAVA_CLASS_PROPERTY, new JavaClassProperty()); namedMethods.put(KOTLIN_ARRAYS_ARRAY, new JavaClassArray()); + namedMethods.put(KOTLIN_HASH_CODE, HASH_CODE); + namedMethods.put(KOTLIN_TO_STRING, TO_STRING); ImmutableList primitiveCastMethods = OperatorConventions.NUMBER_CONVERSIONS.asList(); for (Name method : primitiveCastMethods) { @@ -117,7 +122,7 @@ public class IntrinsicMethods { intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("name"), 0, new EnumName()); intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("ordinal"), 0, new EnumOrdinal()); - intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("toString"), 0, new ToString()); + intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("toString"), 0, TO_STRING); intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("equals"), 1, EQUALS); intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("identityEquals"), 1, IDENTITY_EQUALS); intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("plus"), 1, STRING_PLUS); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ToString.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ToString.java index 35fe44d2e60..32add939d89 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ToString.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ToString.java @@ -20,11 +20,11 @@ import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.asm4.Type; import org.jetbrains.asm4.commons.InstructionAdapter; +import org.jetbrains.jet.codegen.CodegenUtil; import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants; import java.util.List; @@ -42,14 +42,6 @@ public class ToString implements IntrinsicMethod { StackValue receiver, @NotNull GenerationState state ) { - if (receiver.type.getSort() == Type.OBJECT || receiver.type.getSort() == Type.ARRAY) { - receiver.put(AsmTypeConstants.OBJECT_TYPE, v); - v.invokestatic("java/lang/String", "valueOf", "(Ljava/lang/Object;)Ljava/lang/String;"); - } - else { - receiver.put(receiver.type, v); - v.invokestatic("java/lang/String", "valueOf", "(" + receiver.type.getDescriptor() + ")Ljava/lang/String;"); - } - return StackValue.onStack(AsmTypeConstants.JAVA_STRING_TYPE); + return CodegenUtil.genToString(v, receiver); } } diff --git a/compiler/testData/codegen/intrinsics/tostring.kt b/compiler/testData/codegen/intrinsics/tostring.kt index c3294b9d81a..d2d1280dede 100644 --- a/compiler/testData/codegen/intrinsics/tostring.kt +++ b/compiler/testData/codegen/intrinsics/tostring.kt @@ -2,10 +2,24 @@ fun box(): String { if (239.toByte().toString() != (239.toByte() as Byte?).toString()) return "byte failed" if (239.toShort().toString() != (239.toShort() as Short?).toString()) return "short failed" if (239.toInt().toString() != (239.toInt() as Int?).toString()) return "int failed" + if (239.toFloat().toString() != (239.toFloat() as Float?).toString()) return "float failed" if (239.toLong().toString() != (239.toLong() as Long?).toString()) return "long failed" if (239.toDouble().toString() != (239.toDouble() as Double?).toString()) return "double failed" if (true.toString() != (true as Boolean?).toString()) return "boolean failed" if ('a'.toChar().toString() != ('a'.toChar() as Char?).toString()) return "char failed" - + + if ("${239.toByte()}" != (239.toByte() as Byte?).toString()) return "byte template failed" + if ("${239.toShort()}" != (239.toShort() as Short?).toString()) return "short template failed" + if ("${239.toInt()}" != (239.toInt() as Int?).toString()) return "int template failed" + if ("${239.toFloat()}" != (239.toFloat() as Float?).toString()) return "float template failed" + if ("${239.toLong()}" != (239.toLong() as Long?).toString()) return "long template failed" + if ("${239.toDouble()}" != (239.toDouble() as Double?).toString()) return "double template failed" + if ("${true}" != (true as Boolean?).toString()) return "boolean template failed" + if ("${'a'.toChar()}" != ('a'.toChar() as Char?).toString()) return "char template failed" + + for(b in 0..255) { + if("${b.toByte()}" != (b.toByte() as Byte?).toString()) return "byte conversion failed" + } + return "OK" } \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java b/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java index b086dfd3407..878d143fd4c 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java @@ -119,7 +119,7 @@ public class PrimitiveTypesTest extends CodegenTestCase { public void testByteLess() throws Exception { binOpTest("fun foo(a: Byte, b: Byte): Boolean = a < b", - Byte.valueOf((byte) 126), Byte.valueOf((byte) 127), true); + Byte.valueOf((byte) 126), Byte.valueOf((byte) 127), true); } public void testBooleanConstant() throws Exception { @@ -448,8 +448,4 @@ public class PrimitiveTypesTest extends CodegenTestCase { public void testEmptyRanges() throws Exception { blackBoxFile("emptyRanges.kt"); } - - public void testToString() throws Exception { - blackBoxFile("intrinsics/tostring.kt"); - } } diff --git a/libraries/stdlib/src/kotlin/JLangJVM.kt b/libraries/stdlib/src/kotlin/JLangJVM.kt index 24201d0e005..15d1f642cff 100644 --- a/libraries/stdlib/src/kotlin/JLangJVM.kt +++ b/libraries/stdlib/src/kotlin/JLangJVM.kt @@ -9,3 +9,58 @@ public val T.javaClass : Class [Intrinsic("kotlin.javaClass.property")] get() = (this as java.lang.Object).getClass() as Class [Intrinsic("kotlin.javaClass.function")] fun javaClass() : Class = null as Class + + +/** + * A helper method for calling hashCode() on Kotlin objects + * TODO remove when Any supports equals() and hashCode() + */ +[Intrinsic("kotlin.hashCode")] public inline fun Any.hashCode(): Int = (this as java.lang.Object).hashCode() + +/** + * A helper method for calling toString() on Kotlin primitives + * TODO remove when Any supports toString() + */ +[Intrinsic("kotlin.toString")] public fun Boolean.toString(): String = (null as String) + +/** + * A helper method for calling toString() on Kotlin primitives + * TODO remove when Any supports toString() + */ +[Intrinsic("kotlin.toString")] public fun Byte.toString(): String = (null as String) + +/** + * A helper method for calling toString() on Kotlin primitives + * TODO remove when Any supports toString() + */ +[Intrinsic("kotlin.toString")] public fun Short.toString(): String = (null as String) + +/** + * A helper method for calling toString() on Kotlin primitives + * TODO remove when Any supports toString() + */ +[Intrinsic("kotlin.toString")] public fun Char.toString(): String = (null as String) + +/** + * A helper method for calling toString() on Kotlin primitives + * TODO remove when Any supports toString() + */ +[Intrinsic("kotlin.toString")] public fun Int.toString(): String = (null as String) + +/** + * A helper method for calling toString() on Kotlin primitives + * TODO remove when Any supports toString() + */ +[Intrinsic("kotlin.toString")] public fun Float.toString(): String = (null as String) + +/** + * A helper method for calling toString() on Kotlin primitives + * TODO remove when Any supports toString() + */ +[Intrinsic("kotlin.toString")] public fun Long.toString(): String = (null as String) + +/** + * A helper method for calling toString() on Kotlin primitives + * TODO remove when Any supports toString() + */ +[Intrinsic("kotlin.toString")] public fun Double.toString(): String = (null as String) diff --git a/libraries/stdlib/src/kotlin/StandardJVM.kt b/libraries/stdlib/src/kotlin/StandardJVM.kt index e6f2e1f0f2c..97691e789dd 100644 --- a/libraries/stdlib/src/kotlin/StandardJVM.kt +++ b/libraries/stdlib/src/kotlin/StandardJVM.kt @@ -47,9 +47,3 @@ public inline fun callable(action: ()-> T): Callable { public override fun call() = action() } } - -/** - * A helper method for calling hashCode() on Kotlin objects - * TODO remove when Any supports equals() and hashCode() - */ - public inline fun Any.hashCode(): Int = (this as java.lang.Object).hashCode()