diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/interpreter/IrInterpreterAfterFir2IrTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/interpreter/IrInterpreterAfterFir2IrTestGenerated.java new file mode 100644 index 00000000000..f77a83af90b --- /dev/null +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/interpreter/IrInterpreterAfterFir2IrTestGenerated.java @@ -0,0 +1,697 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.test.runners.ir.interpreter; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.kotlin.test.TargetBackend; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link GenerateNewCompilerTests.kt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("compiler/testData/ir/interpreter") +@TestDataPath("$PROJECT_ROOT") +public class IrInterpreterAfterFir2IrTestGenerated extends AbstractIrInterpreterAfterFir2IrTest { + @Test + @TestMetadata("abstract1.kt") + public void testAbstract1() throws Exception { + runTest("compiler/testData/ir/interpreter/abstract1.kt"); + } + + @Test + @TestMetadata("abstract2.kt") + public void testAbstract2() throws Exception { + runTest("compiler/testData/ir/interpreter/abstract2.kt"); + } + + @Test + @TestMetadata("abstract3.kt") + public void testAbstract3() throws Exception { + runTest("compiler/testData/ir/interpreter/abstract3.kt"); + } + + @Test + @TestMetadata("abstract4.kt") + public void testAbstract4() throws Exception { + runTest("compiler/testData/ir/interpreter/abstract4.kt"); + } + + @Test + public void testAllFilesPresentInInterpreter() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/interpreter"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true, "helpers"); + } + + @Test + @TestMetadata("arrayClassCast.kt") + public void testArrayClassCast() throws Exception { + runTest("compiler/testData/ir/interpreter/arrayClassCast.kt"); + } + + @Test + @TestMetadata("branches.kt") + public void testBranches() throws Exception { + runTest("compiler/testData/ir/interpreter/branches.kt"); + } + + @Test + @TestMetadata("companionOverride.kt") + public void testCompanionOverride() throws Exception { + runTest("compiler/testData/ir/interpreter/companionOverride.kt"); + } + + @Test + @TestMetadata("complexReturn.kt") + public void testComplexReturn() throws Exception { + runTest("compiler/testData/ir/interpreter/complexReturn.kt"); + } + + @Test + @TestMetadata("composition.kt") + public void testComposition() throws Exception { + runTest("compiler/testData/ir/interpreter/composition.kt"); + } + + @Test + @TestMetadata("copyReceivedValue.kt") + public void testCopyReceivedValue() throws Exception { + runTest("compiler/testData/ir/interpreter/copyReceivedValue.kt"); + } + + @Test + @TestMetadata("dataClass.kt") + public void testDataClass() throws Exception { + runTest("compiler/testData/ir/interpreter/dataClass.kt"); + } + + @Test + @TestMetadata("defaultArgs.kt") + public void testDefaultArgs() throws Exception { + runTest("compiler/testData/ir/interpreter/defaultArgs.kt"); + } + + @Test + @TestMetadata("defaultEquals.kt") + public void testDefaultEquals() throws Exception { + runTest("compiler/testData/ir/interpreter/defaultEquals.kt"); + } + + @Test + @TestMetadata("defaultHashCode.kt") + public void testDefaultHashCode() throws Exception { + runTest("compiler/testData/ir/interpreter/defaultHashCode.kt"); + } + + @Test + @TestMetadata("defaultToString.kt") + public void testDefaultToString() throws Exception { + runTest("compiler/testData/ir/interpreter/defaultToString.kt"); + } + + @Test + @TestMetadata("doWhileLoop.kt") + public void testDoWhileLoop() throws Exception { + runTest("compiler/testData/ir/interpreter/doWhileLoop.kt"); + } + + @Test + @TestMetadata("doubleArrayOf.kt") + public void testDoubleArrayOf() throws Exception { + runTest("compiler/testData/ir/interpreter/doubleArrayOf.kt"); + } + + @Test + @TestMetadata("elvis.kt") + public void testElvis() throws Exception { + runTest("compiler/testData/ir/interpreter/elvis.kt"); + } + + @Test + @TestMetadata("enums1.kt") + public void testEnums1() throws Exception { + runTest("compiler/testData/ir/interpreter/enums1.kt"); + } + + @Test + @TestMetadata("enums2.kt") + public void testEnums2() throws Exception { + runTest("compiler/testData/ir/interpreter/enums2.kt"); + } + + @Test + @TestMetadata("enums3.kt") + public void testEnums3() throws Exception { + runTest("compiler/testData/ir/interpreter/enums3.kt"); + } + + @Test + @TestMetadata("extensionReceiver.kt") + public void testExtensionReceiver() throws Exception { + runTest("compiler/testData/ir/interpreter/extensionReceiver.kt"); + } + + @Test + @TestMetadata("fib.kt") + public void testFib() throws Exception { + runTest("compiler/testData/ir/interpreter/fib.kt"); + } + + @Test + @TestMetadata("genericListOfPairs.kt") + public void testGenericListOfPairs() throws Exception { + runTest("compiler/testData/ir/interpreter/genericListOfPairs.kt"); + } + + @Test + @TestMetadata("inKeyword.kt") + public void testInKeyword() throws Exception { + runTest("compiler/testData/ir/interpreter/inKeyword.kt"); + } + + @Test + @TestMetadata("inlineReturn.kt") + public void testInlineReturn() throws Exception { + runTest("compiler/testData/ir/interpreter/inlineReturn.kt"); + } + + @Test + @TestMetadata("innerClass.kt") + public void testInnerClass() throws Exception { + runTest("compiler/testData/ir/interpreter/innerClass.kt"); + } + + @Test + @TestMetadata("instanceOf.kt") + public void testInstanceOf() throws Exception { + runTest("compiler/testData/ir/interpreter/instanceOf.kt"); + } + + @Test + @TestMetadata("instanceOfWithTypeParameters.kt") + public void testInstanceOfWithTypeParameters() throws Exception { + runTest("compiler/testData/ir/interpreter/instanceOfWithTypeParameters.kt"); + } + + @Test + @TestMetadata("interface.kt") + public void testInterface() throws Exception { + runTest("compiler/testData/ir/interpreter/interface.kt"); + } + + @Test + @TestMetadata("interfaceDefault.kt") + public void testInterfaceDefault() throws Exception { + runTest("compiler/testData/ir/interpreter/interfaceDefault.kt"); + } + + @Test + @TestMetadata("lambda.kt") + public void testLambda() throws Exception { + runTest("compiler/testData/ir/interpreter/lambda.kt"); + } + + @Test + @TestMetadata("localFunction.kt") + public void testLocalFunction() throws Exception { + runTest("compiler/testData/ir/interpreter/localFunction.kt"); + } + + @Test + @TestMetadata("localObject.kt") + public void testLocalObject() throws Exception { + runTest("compiler/testData/ir/interpreter/localObject.kt"); + } + + @Test + @TestMetadata("logIntrinsic.kt") + public void testLogIntrinsic() throws Exception { + runTest("compiler/testData/ir/interpreter/logIntrinsic.kt"); + } + + @Test + @TestMetadata("loop.kt") + public void testLoop() throws Exception { + runTest("compiler/testData/ir/interpreter/loop.kt"); + } + + @Test + @TestMetadata("multipleOverridden.kt") + public void testMultipleOverridden() throws Exception { + runTest("compiler/testData/ir/interpreter/multipleOverridden.kt"); + } + + @Test + @TestMetadata("object.kt") + public void testObject() throws Exception { + runTest("compiler/testData/ir/interpreter/object.kt"); + } + + @Test + @TestMetadata("objectOverride.kt") + public void testObjectOverride() throws Exception { + runTest("compiler/testData/ir/interpreter/objectOverride.kt"); + } + + @Test + @TestMetadata("overrideDifferentName.kt") + public void testOverrideDifferentName() throws Exception { + runTest("compiler/testData/ir/interpreter/overrideDifferentName.kt"); + } + + @Test + @TestMetadata("overrideExtension.kt") + public void testOverrideExtension() throws Exception { + runTest("compiler/testData/ir/interpreter/overrideExtension.kt"); + } + + @Test + @TestMetadata("progressionFromClosedRange.kt") + public void testProgressionFromClosedRange() throws Exception { + runTest("compiler/testData/ir/interpreter/progressionFromClosedRange.kt"); + } + + @Test + @TestMetadata("rangeTo.kt") + public void testRangeTo() throws Exception { + runTest("compiler/testData/ir/interpreter/rangeTo.kt"); + } + + @Test + @TestMetadata("regex.kt") + public void testRegex() throws Exception { + runTest("compiler/testData/ir/interpreter/regex.kt"); + } + + @Test + @TestMetadata("safeClassCast.kt") + public void testSafeClassCast() throws Exception { + runTest("compiler/testData/ir/interpreter/safeClassCast.kt"); + } + + @Test + @TestMetadata("scopeFunctions.kt") + public void testScopeFunctions() throws Exception { + runTest("compiler/testData/ir/interpreter/scopeFunctions.kt"); + } + + @Test + @TestMetadata("secondaryConstructor.kt") + public void testSecondaryConstructor() throws Exception { + runTest("compiler/testData/ir/interpreter/secondaryConstructor.kt"); + } + + @Test + @TestMetadata("spreadOperator.kt") + public void testSpreadOperator() throws Exception { + runTest("compiler/testData/ir/interpreter/spreadOperator.kt"); + } + + @Test + @TestMetadata("stringBuilder.kt") + public void testStringBuilder() throws Exception { + runTest("compiler/testData/ir/interpreter/stringBuilder.kt"); + } + + @Test + @TestMetadata("stringConcatenation.kt") + public void testStringConcatenation() throws Exception { + runTest("compiler/testData/ir/interpreter/stringConcatenation.kt"); + } + + @Test + @TestMetadata("superClass.kt") + public void testSuperClass() throws Exception { + runTest("compiler/testData/ir/interpreter/superClass.kt"); + } + + @Test + @TestMetadata("vararg.kt") + public void testVararg() throws Exception { + runTest("compiler/testData/ir/interpreter/vararg.kt"); + } + + @Test + @TestMetadata("variableShadowing.kt") + public void testVariableShadowing() throws Exception { + runTest("compiler/testData/ir/interpreter/variableShadowing.kt"); + } + + @Test + @TestMetadata("variables.kt") + public void testVariables() throws Exception { + runTest("compiler/testData/ir/interpreter/variables.kt"); + } + + @Test + @TestMetadata("withReceivers.kt") + public void testWithReceivers() throws Exception { + runTest("compiler/testData/ir/interpreter/withReceivers.kt"); + } + + @Nested + @TestMetadata("compiler/testData/ir/interpreter/collections") + @TestDataPath("$PROJECT_ROOT") + public class Collections { + @Test + public void testAllFilesPresentInCollections() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/interpreter/collections"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("arrayConstructor.kt") + public void testArrayConstructor() throws Exception { + runTest("compiler/testData/ir/interpreter/collections/arrayConstructor.kt"); + } + + @Test + @TestMetadata("arrayOf.kt") + public void testArrayOf() throws Exception { + runTest("compiler/testData/ir/interpreter/collections/arrayOf.kt"); + } + + @Test + @TestMetadata("doubleList.kt") + public void testDoubleList() throws Exception { + runTest("compiler/testData/ir/interpreter/collections/doubleList.kt"); + } + + @Test + @TestMetadata("listOf.kt") + public void testListOf() throws Exception { + runTest("compiler/testData/ir/interpreter/collections/listOf.kt"); + } + + @Test + @TestMetadata("mapOf.kt") + public void testMapOf() throws Exception { + runTest("compiler/testData/ir/interpreter/collections/mapOf.kt"); + } + + @Test + @TestMetadata("matrixArray.kt") + public void testMatrixArray() throws Exception { + runTest("compiler/testData/ir/interpreter/collections/matrixArray.kt"); + } + + @Test + @TestMetadata("matrixList.kt") + public void testMatrixList() throws Exception { + runTest("compiler/testData/ir/interpreter/collections/matrixList.kt"); + } + + @Test + @TestMetadata("mutableListOf.kt") + public void testMutableListOf() throws Exception { + runTest("compiler/testData/ir/interpreter/collections/mutableListOf.kt"); + } + + @Test + @TestMetadata("mutableMapOf.kt") + public void testMutableMapOf() throws Exception { + runTest("compiler/testData/ir/interpreter/collections/mutableMapOf.kt"); + } + + @Test + @TestMetadata("mutableSetOf.kt") + public void testMutableSetOf() throws Exception { + runTest("compiler/testData/ir/interpreter/collections/mutableSetOf.kt"); + } + + @Test + @TestMetadata("sequenceOf.kt") + public void testSequenceOf() throws Exception { + runTest("compiler/testData/ir/interpreter/collections/sequenceOf.kt"); + } + + @Test + @TestMetadata("setOf.kt") + public void testSetOf() throws Exception { + runTest("compiler/testData/ir/interpreter/collections/setOf.kt"); + } + } + + @Nested + @TestMetadata("compiler/testData/ir/interpreter/exceptions") + @TestDataPath("$PROJECT_ROOT") + public class Exceptions { + @Test + public void testAllFilesPresentInExceptions() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/interpreter/exceptions"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("arithmeticExceptionThrow.kt") + public void testArithmeticExceptionThrow() throws Exception { + runTest("compiler/testData/ir/interpreter/exceptions/arithmeticExceptionThrow.kt"); + } + + @Test + @TestMetadata("arithmeticExceptionTryBlock.kt") + public void testArithmeticExceptionTryBlock() throws Exception { + runTest("compiler/testData/ir/interpreter/exceptions/arithmeticExceptionTryBlock.kt"); + } + + @Test + @TestMetadata("arithmeticExceptionTryCatchFinally.kt") + public void testArithmeticExceptionTryCatchFinally() throws Exception { + runTest("compiler/testData/ir/interpreter/exceptions/arithmeticExceptionTryCatchFinally.kt"); + } + + @Test + @TestMetadata("classCastException.kt") + public void testClassCastException() throws Exception { + runTest("compiler/testData/ir/interpreter/exceptions/classCastException.kt"); + } + + @Test + @TestMetadata("commandsOutException.kt") + public void testCommandsOutException() throws Exception { + runTest("compiler/testData/ir/interpreter/exceptions/commandsOutException.kt"); + } + + @Test + @TestMetadata("divideByZero.kt") + public void testDivideByZero() throws Exception { + runTest("compiler/testData/ir/interpreter/exceptions/divideByZero.kt"); + } + + @Test + @TestMetadata("exceptionFromWrapper.kt") + public void testExceptionFromWrapper() throws Exception { + runTest("compiler/testData/ir/interpreter/exceptions/exceptionFromWrapper.kt"); + } + + @Test + @TestMetadata("exceptionWithCause.kt") + public void testExceptionWithCause() throws Exception { + runTest("compiler/testData/ir/interpreter/exceptions/exceptionWithCause.kt"); + } + + @Test + @TestMetadata("getCauseMessage.kt") + public void testGetCauseMessage() throws Exception { + runTest("compiler/testData/ir/interpreter/exceptions/getCauseMessage.kt"); + } + + @Test + @TestMetadata("multifileStackTrace.kt") + public void testMultifileStackTrace() throws Exception { + runTest("compiler/testData/ir/interpreter/exceptions/multifileStackTrace.kt"); + } + + @Test + @TestMetadata("nullPointerException.kt") + public void testNullPointerException() throws Exception { + runTest("compiler/testData/ir/interpreter/exceptions/nullPointerException.kt"); + } + + @Test + @TestMetadata("stackOverflow.kt") + public void testStackOverflow() throws Exception { + runTest("compiler/testData/ir/interpreter/exceptions/stackOverflow.kt"); + } + + @Test + @TestMetadata("stackTrace.kt") + public void testStackTrace() throws Exception { + runTest("compiler/testData/ir/interpreter/exceptions/stackTrace.kt"); + } + + @Test + @TestMetadata("tryFinally.kt") + public void testTryFinally() throws Exception { + runTest("compiler/testData/ir/interpreter/exceptions/tryFinally.kt"); + } + } + + @Nested + @TestMetadata("compiler/testData/ir/interpreter/generatedStdlib") + @TestDataPath("$PROJECT_ROOT") + public class GeneratedStdlib { + @Test + public void testAllFilesPresentInGeneratedStdlib() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/interpreter/generatedStdlib"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("contains.kt") + public void testContains() throws Exception { + runTest("compiler/testData/ir/interpreter/generatedStdlib/contains.kt"); + } + + @Test + @TestMetadata("elementAtOrElse.kt") + public void testElementAtOrElse() throws Exception { + runTest("compiler/testData/ir/interpreter/generatedStdlib/elementAtOrElse.kt"); + } + + @Test + @TestMetadata("first.kt") + public void testFirst() throws Exception { + runTest("compiler/testData/ir/interpreter/generatedStdlib/first.kt"); + } + + @Test + @TestMetadata("joinToString.kt") + public void testJoinToString() throws Exception { + runTest("compiler/testData/ir/interpreter/generatedStdlib/joinToString.kt"); + } + + @Test + @TestMetadata("toList.kt") + public void testToList() throws Exception { + runTest("compiler/testData/ir/interpreter/generatedStdlib/toList.kt"); + } + + @Test + @TestMetadata("trim.kt") + public void testTrim() throws Exception { + runTest("compiler/testData/ir/interpreter/generatedStdlib/trim.kt"); + } + } + + @Nested + @TestMetadata("compiler/testData/ir/interpreter/jvm") + @TestDataPath("$PROJECT_ROOT") + public class Jvm { + @Test + public void testAllFilesPresentInJvm() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/interpreter/jvm"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("classReference.kt") + public void testClassReference() throws Exception { + runTest("compiler/testData/ir/interpreter/jvm/classReference.kt"); + } + + @Test + @TestMetadata("javaStatic.kt") + public void testJavaStatic() throws Exception { + runTest("compiler/testData/ir/interpreter/jvm/javaStatic.kt"); + } + + @Test + @TestMetadata("kProperty2.kt") + public void testKProperty2() throws Exception { + runTest("compiler/testData/ir/interpreter/jvm/kProperty2.kt"); + } + + @Test + @TestMetadata("parameterReference.kt") + public void testParameterReference() throws Exception { + runTest("compiler/testData/ir/interpreter/jvm/parameterReference.kt"); + } + } + + @Nested + @TestMetadata("compiler/testData/ir/interpreter/primitives") + @TestDataPath("$PROJECT_ROOT") + public class Primitives { + @Test + public void testAllFilesPresentInPrimitives() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/interpreter/primitives"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("charMethods.kt") + public void testCharMethods() throws Exception { + runTest("compiler/testData/ir/interpreter/primitives/charMethods.kt"); + } + + @Test + @TestMetadata("intMethods.kt") + public void testIntMethods() throws Exception { + runTest("compiler/testData/ir/interpreter/primitives/intMethods.kt"); + } + + @Test + @TestMetadata("longMethods.kt") + public void testLongMethods() throws Exception { + runTest("compiler/testData/ir/interpreter/primitives/longMethods.kt"); + } + + @Test + @TestMetadata("uInt.kt") + public void testUInt() throws Exception { + runTest("compiler/testData/ir/interpreter/primitives/uInt.kt"); + } + } + + @Nested + @TestMetadata("compiler/testData/ir/interpreter/proxy") + @TestDataPath("$PROJECT_ROOT") + public class Proxy { + @Test + public void testAllFilesPresentInProxy() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/interpreter/proxy"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("customCharSequence.kt") + public void testCustomCharSequence() throws Exception { + runTest("compiler/testData/ir/interpreter/proxy/customCharSequence.kt"); + } + + @Test + @TestMetadata("customEquals.kt") + public void testCustomEquals() throws Exception { + runTest("compiler/testData/ir/interpreter/proxy/customEquals.kt"); + } + + @Test + @TestMetadata("proxyPair.kt") + public void testProxyPair() throws Exception { + runTest("compiler/testData/ir/interpreter/proxy/proxyPair.kt"); + } + + @Test + @TestMetadata("superWrapper.kt") + public void testSuperWrapper() throws Exception { + runTest("compiler/testData/ir/interpreter/proxy/superWrapper.kt"); + } + } + + @Nested + @TestMetadata("compiler/testData/ir/interpreter/reference") + @TestDataPath("$PROJECT_ROOT") + public class Reference { + @Test + public void testAllFilesPresentInReference() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/interpreter/reference"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("propertyReference.kt") + public void testPropertyReference() throws Exception { + runTest("compiler/testData/ir/interpreter/reference/propertyReference.kt"); + } + } +} diff --git a/compiler/testData/ir/interpreter/abstract1.kt b/compiler/testData/ir/interpreter/abstract1.kt new file mode 100644 index 00000000000..ae39f8ab6b3 --- /dev/null +++ b/compiler/testData/ir/interpreter/abstract1.kt @@ -0,0 +1,51 @@ +abstract class A @CompileTimeCalculation constructor() { + @CompileTimeCalculation + abstract fun getIntNum(): Int +} + +open class B @CompileTimeCalculation constructor(@CompileTimeCalculation val b: Int) : A() { + @CompileTimeCalculation + override fun getIntNum(): Int { + return b + } +} + +class C @CompileTimeCalculation constructor(@CompileTimeCalculation val c: Int) : B(c + 1) { + @CompileTimeCalculation + override fun getIntNum(): Int { + return c + } +} + +@CompileTimeCalculation +fun getAClassImplementation(num: Int): A { + return B(num) +} + +@CompileTimeCalculation +fun getBClassImplementation(num: Int): B { + return B(num) +} + +@CompileTimeCalculation +fun getClassCAsA(num: Int): A { + return C(num) +} + +@CompileTimeCalculation +fun getClassCAsB(num: Int): B { + return C(num) +} + +@CompileTimeCalculation +fun getClassCAsC(num: Int): C { + return C(num) +} + +const val num1 = getAClassImplementation(1).getIntNum() +const val num2 = getBClassImplementation(2).getIntNum() + +// all `getIntNum` methods are from class C +const val num3 = getClassCAsA(3).getIntNum() +const val num4 = getClassCAsB(4).getIntNum() +const val num5 = getClassCAsC(5).getIntNum() diff --git a/compiler/testData/ir/interpreter/abstract2.kt b/compiler/testData/ir/interpreter/abstract2.kt new file mode 100644 index 00000000000..623d9626ed7 --- /dev/null +++ b/compiler/testData/ir/interpreter/abstract2.kt @@ -0,0 +1,43 @@ +abstract class A @CompileTimeCalculation constructor() { + @CompileTimeCalculation + abstract fun getIntNum(): Int + + @CompileTimeCalculation + abstract fun getIntNumInverse(): Int +} + +abstract class B @CompileTimeCalculation constructor(@CompileTimeCalculation val b: Int) : A() { + @CompileTimeCalculation + override fun getIntNum(): Int { + return b + } +} + +class C @CompileTimeCalculation constructor(@CompileTimeCalculation val c: Int) : B(c + 1) { + @CompileTimeCalculation + override fun getIntNum(): Int { + return c + } + + @CompileTimeCalculation + override fun getIntNumInverse(): Int { + return -c + } +} + +@CompileTimeCalculation +fun getClassCAsA(num: Int): A { + return C(num) +} + +@CompileTimeCalculation +fun getClassCAsB(num: Int): B { + return C(num) +} + +// all methods call from C +const val num1 = getClassCAsA(1).getIntNum() +const val num2 = getClassCAsB(2).getIntNum() + +const val num3 = getClassCAsA(3).getIntNumInverse() +const val num4 = getClassCAsB(4).getIntNumInverse() diff --git a/compiler/testData/ir/interpreter/abstract3.kt b/compiler/testData/ir/interpreter/abstract3.kt new file mode 100644 index 00000000000..b407f9a837a --- /dev/null +++ b/compiler/testData/ir/interpreter/abstract3.kt @@ -0,0 +1,49 @@ +abstract class A @CompileTimeCalculation constructor() { + @CompileTimeCalculation + abstract fun getInt(): Int +} + +open class B @CompileTimeCalculation constructor(@CompileTimeCalculation val b: Int) : A() { + @CompileTimeCalculation + override fun getInt(): Int { + return b + } +} + +abstract class C @CompileTimeCalculation constructor(@CompileTimeCalculation val c: Int) : B(c + 1) { + @CompileTimeCalculation + abstract fun getString(): String +} + +class D @CompileTimeCalculation constructor(@CompileTimeCalculation val d: Int) : C(d + 1) { + @CompileTimeCalculation + override fun getString(): String { + return d.toString() + } +} +@CompileTimeCalculation +fun getClassDAsA(num: Int): A { + return D(num) +} + +@CompileTimeCalculation +fun getClassDAsB(num: Int): B { + return D(num) +} + +@CompileTimeCalculation +fun getClassDAsC(num: Int): C { + return D(num) +} + +@CompileTimeCalculation +fun getClassDAsD(num: Int): D { + return D(num) +} + +const val numA1 = getClassDAsA(1).getInt() +const val numB1 = getClassDAsB(1).getInt() +const val numC1 = getClassDAsC(1).getInt() +const val numC2 = getClassDAsC(1).getString() +const val numD1 = getClassDAsD(1).getInt() +const val numD2 = getClassDAsD(1).getString() diff --git a/compiler/testData/ir/interpreter/abstract4.kt b/compiler/testData/ir/interpreter/abstract4.kt new file mode 100644 index 00000000000..e8900e4085a --- /dev/null +++ b/compiler/testData/ir/interpreter/abstract4.kt @@ -0,0 +1,37 @@ +@CompileTimeCalculation +abstract class BaseIterator(var baseStart: Int) { + fun baseNext(): Int { + baseStart += 1 + return base() + } + + abstract fun base(): Int +} + +@CompileTimeCalculation +abstract class ComplexIterator(var complexStart: Int) : BaseIterator(complexStart) { + fun complexNext() = abstractCall() + + private fun abstractCall(): Int { + complexStart *= 2 + return complex() + baseNext() + } + + abstract fun complex(): Int +} + +@CompileTimeCalculation +class ImplementIterator constructor(val i: Int) : ComplexIterator(i) { + override fun complex(): Int { + return complexStart + } + + override fun base(): Int { + return baseStart + } +} + +@CompileTimeCalculation +fun getIterator(i: Int): ComplexIterator = ImplementIterator(i) + +const val next = getIterator(10).complexNext() diff --git a/compiler/testData/ir/interpreter/arrayClassCast.kt b/compiler/testData/ir/interpreter/arrayClassCast.kt new file mode 100644 index 00000000000..5489937b848 --- /dev/null +++ b/compiler/testData/ir/interpreter/arrayClassCast.kt @@ -0,0 +1,31 @@ +@CompileTimeCalculation +fun getArray(array: Array) = array + +const val a1 = getArray(arrayOf(1, 2.0, "3")) as? Array == null +const val a2 = getArray(arrayOf(1, 2, 3)) as? Array == null +const val a3 = getArray(arrayOf(1, 2, 3)) as? Array == null +const val a4 = getArray(arrayOf(1, 2, 3)) as? Array == null + +const val b1 = arrayOf(arrayOf(1, 2, 3)) as? Array> == null +const val b2 = arrayOf(arrayOf(1, 2, 3)) as? Array> == null +const val b3 = arrayOf(arrayOf(1, 2, 3)) as? Array> == null + +const val c1 = arrayOf(arrayOf(1, 2, 3), arrayOf("1", "2", "3"))[0] as? Array == null +const val c2 = arrayOf(arrayOf(1, 2, 3), arrayOf("1", "2", "3"))[1] as? Array == null + +@CompileTimeCalculation +fun combineArrays(array1: Array, array2: Array) = arrayOf(array1, array2) + +const val d1 = combineArrays(arrayOf(1, 2, 3), arrayOf(1, 2, 3)) as? Array> == null +const val d2 = combineArrays(arrayOf(1, 2, 3), arrayOf(1, 2, 3)) as? Array> == null +const val d3 = combineArrays(arrayOf(1, 2, 3), arrayOf(1, 2, 3)) as? Array> == null +const val d4 = combineArrays(arrayOf(1, 2, 3), arrayOf(1, 2, 3)) as? Array> == null +const val d5 = combineArrays(arrayOf(1, 2, 3), arrayOf("1", "2", "3"))[0] as? Array == null +const val d6 = combineArrays(arrayOf(1, 2, 3), arrayOf("1", "2", "3"))[1] as? Array == null +const val d7 = combineArrays(arrayOf(1, 2, 3), arrayOf("1", "2", "3"))[1] as? Array == null + +@CompileTimeCalculation +fun echo(array: T) = array +const val e1 = echo(arrayOf(1, 2, 3)) as? Array == null +const val e2 = echo(arrayOf(arrayOf(1, 2, 3))) as? Array> == null +const val e3 = echo(arrayOf(echo(1), echo(2), echo(3))) as? Array == null diff --git a/compiler/testData/ir/interpreter/branches.kt b/compiler/testData/ir/interpreter/branches.kt new file mode 100644 index 00000000000..494f7ddbf69 --- /dev/null +++ b/compiler/testData/ir/interpreter/branches.kt @@ -0,0 +1,65 @@ +@CompileTimeCalculation fun ifGreaterOrEqualToZero(a: Int): Boolean { + return if (a >= 0) { + true + } else { + false + } +} + +@CompileTimeCalculation fun whenGreaterOrEqualToZero(a: Int): Boolean { + return when { + a >= 0 -> true + else -> false + } +} + +@CompileTimeCalculation fun whenMultiBranch(a: Int): Int { + return when (a) { + 1 -> -1 + 2 -> -2 + 3 -> -3 + 4 -> -4 + else -> 0 + } +} + +class A @CompileTimeCalculation constructor(@CompileTimeCalculation var a: Int) + +@CompileTimeCalculation fun whenWithoutReturn(aObj: A): Int { + when (aObj.a) { + 1 -> aObj.a = -1 + 2 -> aObj.a = -2 + 3 -> aObj.a = -3 + 4 -> aObj.a = -4 + else -> aObj.a = 0 + } + + return aObj.a +} + +@CompileTimeCalculation fun whenWithoutElse(aObj: A): Int { + when (aObj.a) { + 1 -> aObj.a = -1 + 2 -> aObj.a = -2 + 3 -> aObj.a = -3 + 4 -> aObj.a = -4 + } + + return aObj.a +} + +const val a = ifGreaterOrEqualToZero(10) +const val b = whenGreaterOrEqualToZero(-10) +const val constIf = if (a == true) "True" else "False" + +const val multi1 = whenMultiBranch(2) +const val multi2 = whenMultiBranch(4) +const val multi3 = whenMultiBranch(10) + +const val c1 = whenWithoutReturn(A(1)) +const val c2 = whenWithoutReturn(A(3)) +const val c3 = whenWithoutReturn(A(10)) + +const val d1 = whenWithoutElse(A(1)) +const val d2 = whenWithoutElse(A(4)) +const val d3 = whenWithoutElse(A(10)) diff --git a/compiler/testData/ir/interpreter/collections/arrayConstructor.kt b/compiler/testData/ir/interpreter/collections/arrayConstructor.kt new file mode 100644 index 00000000000..2a59aae462f --- /dev/null +++ b/compiler/testData/ir/interpreter/collections/arrayConstructor.kt @@ -0,0 +1,21 @@ +import kotlin.* + +const val intArray1 = IntArray(42).size +const val intArray2 = IntArray(42)[0] +const val intArray3 = IntArray(10) { 42 }[0] +const val intArray4 = IntArray(10) { it -> it }[7] + +const val floatArray1 = FloatArray(42).size +const val floatArray2 = FloatArray(42)[0] +const val floatArray3 = FloatArray(10) { 42.5f }[0] +const val floatArray4 = FloatArray(10) { it -> it.toFloat() }[7] + +const val array = Array(4) { + when(it) { + 0 -> 1 + 1 -> 2.0 + 2 -> "3" + 3 -> null + else -> throw IllegalArgumentException("$it is wrong") + } +}.let { it[0].toString() + " " + it[1] + " " + it[2] + " " + it[3] } diff --git a/compiler/testData/ir/interpreter/collections/arrayOf.kt b/compiler/testData/ir/interpreter/collections/arrayOf.kt new file mode 100644 index 00000000000..ef5503d0cae --- /dev/null +++ b/compiler/testData/ir/interpreter/collections/arrayOf.kt @@ -0,0 +1,23 @@ +@CompileTimeCalculation +class A(val value: Int) + +@CompileTimeCalculation +fun changeAndReturnSum(intArray: IntArray, index: Int, newValue: Int): Int { + intArray[index] = newValue + var sum = 0 + for (i in intArray) sum += i + return sum +} + +@CompileTimeCalculation +fun changeAndReturnSumForObject(array: Array, index: Int, newValue: A): Int { + array[index] = newValue + var sum = 0 + for (aObject in array) sum += aObject.value + return sum +} + +const val a = arrayOf(1, 2, 3).size +const val b = changeAndReturnSum(intArrayOf(1, 2, 3), 0, 10) +const val c = emptyArray().size +const val d = changeAndReturnSumForObject(arrayOf(A(1), A(2), A(3)), 0, A(10)) diff --git a/compiler/testData/ir/interpreter/collections/doubleList.kt b/compiler/testData/ir/interpreter/collections/doubleList.kt new file mode 100644 index 00000000000..e34d871057e --- /dev/null +++ b/compiler/testData/ir/interpreter/collections/doubleList.kt @@ -0,0 +1,25 @@ +import kotlin.collections.* + +const val doubleListSize = listOf( + listOf("1", "2", "3"), + listOf("4", "5", "6"), + listOf("7", "8", "9") +).size + +const val doubleListSizeOfList = listOf( + listOf("1"), + listOf("4", "5"), + listOf("7", "8", "9") +)[2].size + +const val doubleListGetSingleElement = listOf( + listOf("1"), + listOf("4", "5"), + listOf("7", "8", "9") +)[2][2] + +const val doubleListElements = listOf( + listOf("1"), + listOf("4", "5"), + listOf("7", "8", "9") +).joinToString(separator = "; ") { it.joinToString() } diff --git a/compiler/testData/ir/interpreter/collections/listOf.kt b/compiler/testData/ir/interpreter/collections/listOf.kt new file mode 100644 index 00000000000..423457901d8 --- /dev/null +++ b/compiler/testData/ir/interpreter/collections/listOf.kt @@ -0,0 +1,16 @@ +import kotlin.collections.* + +const val a = listOf(1, 2, 3).size +const val b = emptyList().size +const val c = listOf().hashCode() + +@CompileTimeCalculation +fun getSum(list: List): Int { + var sum: Int = 0 + for (element in list) { + sum += element + } + return sum +} + +const val sum = getSum(listOf(1, 3, 5, 7)) diff --git a/compiler/testData/ir/interpreter/collections/mapOf.kt b/compiler/testData/ir/interpreter/collections/mapOf.kt new file mode 100644 index 00000000000..6ba746d7418 --- /dev/null +++ b/compiler/testData/ir/interpreter/collections/mapOf.kt @@ -0,0 +1,18 @@ +import kotlin.* +import kotlin.collections.* + +const val a = mapOf(1 to "1", 2 to "2", 3 to "3").size +const val b = emptyMap().size + +const val contains1 = mapOf(1 to "1", 2 to "2", 3 to "3").containsKey(1) +const val contains2 = mapOf(1 to "1", 2 to "2", 3 to "3").contains(1) +const val contains3 = mapOf(1 to "1", 2 to "2", 3 to "3").contains("1") +const val contains4 = mapOf(1 to "1", 2 to "2", 3 to "3").containsValue("1") + +const val get1 = mapOf(1 to "1", 2 to "2", 3 to "3").get(1)!! +const val get2 = mapOf(1 to "1", 2 to "2", 3 to "3")[2]!! +const val get3 = mapOf(1 to "1", 2 to "2", 3 to "3")[0].toString() + +const val keys = mapOf(1 to "1", 2 to "2", 3 to "3").keys.size +const val values = mapOf(1 to "1", 2 to "2", 3 to "3").values.size +const val entries = mapOf(1 to "1", 2 to "2", 3 to "3").entries.size diff --git a/compiler/testData/ir/interpreter/collections/matrixArray.kt b/compiler/testData/ir/interpreter/collections/matrixArray.kt new file mode 100644 index 00000000000..153f52c275d --- /dev/null +++ b/compiler/testData/ir/interpreter/collections/matrixArray.kt @@ -0,0 +1,40 @@ +import kotlin.* +import kotlin.ranges.* + +@CompileTimeCalculation +class MatrixNN(val values: Array>) { + val size = values.size + operator fun times(other: MatrixNN): MatrixNN { + val matrix = Array>(size) { Array(size) { 0.0 } } + for (i in 0 until size) { + for (j in 0 until size) { + for (k in 0 until size) { + matrix[i][j] += this.values[i][k] * other.values[k][j] + } + } + } + return MatrixNN(matrix) + } +} + +@CompileTimeCalculation +fun demo(): Double { + val m1 = MatrixNN( + arrayOf( + arrayOf(3.0, 1.0, 0.0), + arrayOf(1.0, 1.0, 0.0), + arrayOf(0.0, 0.0, 1.0) + ) + ) + val m2 = MatrixNN( + arrayOf( + arrayOf(3.0, 1.0, 1.0), + arrayOf(1.0, 1.0, 1.0), + arrayOf(1.0, 1.0, 1.0) + ) + ) + + return (m1 * m2).values[0][0] +} + +const val temp = demo() diff --git a/compiler/testData/ir/interpreter/collections/matrixList.kt b/compiler/testData/ir/interpreter/collections/matrixList.kt new file mode 100644 index 00000000000..d9df757a369 --- /dev/null +++ b/compiler/testData/ir/interpreter/collections/matrixList.kt @@ -0,0 +1,41 @@ +import kotlin.* +import kotlin.ranges.* +import kotlin.collections.* + +@CompileTimeCalculation +class MatrixNN(val values: List>) { + val size = values.size + operator fun times(other: MatrixNN): MatrixNN { + val matrix = List>(size) { MutableList(size) { 0.0 } } + for (i in 0 until size) { + for (j in 0 until size) { + for (k in 0 until size) { + matrix[i][j] = matrix[i][j] + (this.values[i][k] * other.values[k][j]) + } + } + } + return MatrixNN(matrix) + } +} + +@CompileTimeCalculation +fun demo(): Double { + val m1 = MatrixNN( + listOf( + listOf(3.0, 1.0, 0.0), + listOf(1.0, 1.0, 0.0), + listOf(0.0, 0.0, 1.0) + ) + ) + val m2 = MatrixNN( + listOf( + listOf(3.0, 1.0, 1.0), + listOf(1.0, 1.0, 1.0), + listOf(1.0, 1.0, 1.0) + ) + ) + + return (m1 * m2).values[0][0] +} + +const val temp = demo() diff --git a/compiler/testData/ir/interpreter/collections/mutableListOf.kt b/compiler/testData/ir/interpreter/collections/mutableListOf.kt new file mode 100644 index 00000000000..20b68166440 --- /dev/null +++ b/compiler/testData/ir/interpreter/collections/mutableListOf.kt @@ -0,0 +1,37 @@ +import kotlin.collections.* + +@CompileTimeCalculation +fun testAdd(mutableList: MutableList, newElem: Int): String { + mutableList.add(newElem) + return "After add new size is " + mutableList.size +} + +@CompileTimeCalculation +fun testRemove(mutableList: MutableList, toRemove: T): String { + mutableList.remove(toRemove) + return "After remove new size is " + mutableList.size +} + +@CompileTimeCalculation +fun testAddAll(mutableList: MutableList, toAdd: List): String { + mutableList.addAll(toAdd) + return "After addAll new size is " + mutableList.size +} + +@CompileTimeCalculation +fun testIterator(mutableList: MutableList): String { + var sum = 0 + for (byte in mutableList) { + sum += byte + } + return "Sum = " + sum +} + +const val emptyMutableListSize = mutableListOf().size +const val mutableListSize = mutableListOf(1, 2, 3).size +const val mutableListAdd = testAdd(mutableListOf(1, 2, 3), 4) +const val mutableListRemove1 = testRemove(mutableListOf("1", "2", "3"), "1") +const val mutableListRemove2 = testRemove(mutableListOf("1", "2", "3"), "4") +const val mutableListAddAll = testAddAll(mutableListOf(1.0, 2.0, 3.0), listOf(4.333, -5.5)) +const val mutableListSum = testIterator(mutableListOf(1, (-2).toByte(), 127, 10, 0)) +const val mutableListSubList = mutableListOf(1, 2, 3, 4).subList(0, 2).size diff --git a/compiler/testData/ir/interpreter/collections/mutableMapOf.kt b/compiler/testData/ir/interpreter/collections/mutableMapOf.kt new file mode 100644 index 00000000000..6e5720fddf6 --- /dev/null +++ b/compiler/testData/ir/interpreter/collections/mutableMapOf.kt @@ -0,0 +1,6 @@ +import kotlin.* +import kotlin.collections.* + +const val a1 = mutableMapOf(1 to "1", 2 to "2", 3 to "3").size +const val a2 = mutableMapOf(1 to "1", 2 to "2", 3 to "3").apply { remove(1) }.size + diff --git a/compiler/testData/ir/interpreter/collections/mutableSetOf.kt b/compiler/testData/ir/interpreter/collections/mutableSetOf.kt new file mode 100644 index 00000000000..cfcff25c8bd --- /dev/null +++ b/compiler/testData/ir/interpreter/collections/mutableSetOf.kt @@ -0,0 +1,36 @@ +import kotlin.collections.* + +@CompileTimeCalculation +fun testAdd(mutableSet: MutableSet, newElem: Int): String { + mutableSet.add(newElem) + return "After add new size is " + mutableSet.size +} + +@CompileTimeCalculation +fun testRemove(mutableSet: MutableSet, toRemove: T): String { + mutableSet.remove(toRemove) + return "After remove new size is " + mutableSet.size +} + +@CompileTimeCalculation +fun testAddAll(mutableSet: MutableSet, toAdd: Set): String { + mutableSet.addAll(toAdd) + return "After addAll new size is " + mutableSet.size +} + +@CompileTimeCalculation +fun testIterator(mutableSet: MutableSet): String { + var sum = 0 + for (byte in mutableSet) { + sum += byte + } + return "Sum = " + sum +} + +const val emptyMutableSetSize = mutableSetOf().size +const val mutableSetSize = mutableSetOf(1, 2, 3).size +const val mutableSetAdd = testAdd(mutableSetOf(1, 2, 3), 4) +const val mutableSetRemove1 = testRemove(mutableSetOf("1", "2", "3"), "1") +const val mutableSetRemove2 = testRemove(mutableSetOf("1", "2", "3"), "4") +const val mutableSetAddAll = testAddAll(mutableSetOf(1.0, 2.0, 3.0), setOf(4.333, -5.5)) +const val mutableSetSum = testIterator(mutableSetOf(1, (-2).toByte(), 127, 10, 0)) diff --git a/compiler/testData/ir/interpreter/collections/sequenceOf.kt b/compiler/testData/ir/interpreter/collections/sequenceOf.kt new file mode 100644 index 00000000000..40dfa2ffb16 --- /dev/null +++ b/compiler/testData/ir/interpreter/collections/sequenceOf.kt @@ -0,0 +1,6 @@ +import kotlin.sequences.* + +const val a = sequenceOf(1, 2, 3).iterator().next() +const val b = sequenceOf(2, 3).iterator().next() +const val c = sequenceOf().iterator().hasNext() +const val d = generateSequence() { 42 }.iterator().next() diff --git a/compiler/testData/ir/interpreter/collections/setOf.kt b/compiler/testData/ir/interpreter/collections/setOf.kt new file mode 100644 index 00000000000..336dcdda7c1 --- /dev/null +++ b/compiler/testData/ir/interpreter/collections/setOf.kt @@ -0,0 +1,17 @@ +import kotlin.collections.* + +const val a1 = setOf(1, 2, 3).size +const val a2 = setOf(1, 2, 3, 3, 2, 1).size +const val b = emptySet().size +const val c = setOf().hashCode() + +@CompileTimeCalculation +fun getSum(set: Set): Int { + var sum: Int = 0 + for (element in set) { + sum += element + } + return sum +} + +const val sum = getSum(setOf(1, 3, 5, 7, 7, 5)) diff --git a/compiler/testData/ir/interpreter/companionOverride.kt b/compiler/testData/ir/interpreter/companionOverride.kt new file mode 100644 index 00000000000..196842a82d0 --- /dev/null +++ b/compiler/testData/ir/interpreter/companionOverride.kt @@ -0,0 +1,32 @@ +@CompileTimeCalculation +interface Object { + fun get(): String + + //@CompileTimeCalculation + fun defaultGet() = "Object" +} + +@CompileTimeCalculation +open class A { + companion object : Object { + @CompileTimeCalculation + override fun get() = "A" + } +} + +@CompileTimeCalculation +abstract class B : Object { + fun str() = "B" +} + +@CompileTimeCalculation +class C { + companion object : B() { + @CompileTimeCalculation + override fun get() = "Default: " + super.defaultGet() + "; from super B: " + super.str() + "; from current: " + " companion C" + } +} + +const val a = A.get() +const val c1 = C.defaultGet() +const val c2 = C.get() diff --git a/compiler/testData/ir/interpreter/complexReturn.kt b/compiler/testData/ir/interpreter/complexReturn.kt new file mode 100644 index 00000000000..9f7978706be --- /dev/null +++ b/compiler/testData/ir/interpreter/complexReturn.kt @@ -0,0 +1,19 @@ +import kotlin.collections.* + +@CompileTimeCalculation +fun firstNotNull(list: List): T { + for (elem in list) { + return (elem ?: continue) + } + + throw kotlin.NoSuchElementException("All elements are null") +} + +const val a = firstNotNull(listOf(1, 2, 3)) +const val b = firstNotNull(listOf(1, null, 3)) +const val c = firstNotNull(listOf(null, 2, 3)) +const val d = firstNotNull(listOf(null, null, 3)) +const val e = (complexReturn.kt:16)`!>firstNotNull(listOf(null, null, null)) diff --git a/compiler/testData/ir/interpreter/composition.kt b/compiler/testData/ir/interpreter/composition.kt new file mode 100644 index 00000000000..011772c9dbc --- /dev/null +++ b/compiler/testData/ir/interpreter/composition.kt @@ -0,0 +1,71 @@ +open class A @CompileTimeCalculation constructor(@CompileTimeCalculation var a: Int) { + @CompileTimeCalculation + fun get(): Int { + return a + } + + @CompileTimeCalculation + open fun openGet(): Int { + return a + } + + @CompileTimeCalculation + fun setA(a: Int): A { + this.a = a + return this + } +} + +open class B @CompileTimeCalculation constructor(@CompileTimeCalculation val b: Int) { + @CompileTimeCalculation val aObj = A(b + 1) + + @CompileTimeCalculation + fun getAFromB(): Int { + return aObj.a + } + + @CompileTimeCalculation + fun getFromProperty(): Int { + return aObj.get() + } +} + +open class C @CompileTimeCalculation constructor(@CompileTimeCalculation val c: Int) { + @CompileTimeCalculation val aObj = A(c + 2) + @CompileTimeCalculation val bObj = B(c + 1) + + @CompileTimeCalculation + fun getAFromC(): Int { + return aObj.a + } + + @CompileTimeCalculation + fun getBFromC(): Int { + return bObj.b + } + + @CompileTimeCalculation + fun openGet(): Int { + return aObj.openGet() + } +} + +const val a1 = A(1).get() +const val a2 = A(1).setA(2).get() +const val a3 = A(1).openGet() + +const val b1 = B(1).getAFromB() +const val b2 = B(1).getFromProperty() +const val b3 = B(1).aObj.get() +const val b4 = B(1).aObj.setA(-1).get() +const val b5 = B(1).aObj.a + +const val c1 = C(1).getAFromC() +const val c2 = C(1).getBFromC() +const val c3 = C(1).aObj.get() +const val c4 = C(1).openGet() +const val c5 = C(1).bObj.getAFromB() +const val c6 = C(1).bObj.getFromProperty() +const val c7 = C(1).bObj.aObj.setA(-2).get() +const val c8 = C(1).bObj.b +const val c9 = C(1).aObj.a diff --git a/compiler/testData/ir/interpreter/copyReceivedValue.kt b/compiler/testData/ir/interpreter/copyReceivedValue.kt new file mode 100644 index 00000000000..fe01f61add1 --- /dev/null +++ b/compiler/testData/ir/interpreter/copyReceivedValue.kt @@ -0,0 +1,8 @@ +@CompileTimeCalculation +fun Int.minusOne(): Int { + var value = this + value = value - 1 + return this +} + +const val a = 5.minusOne() diff --git a/compiler/testData/ir/interpreter/dataClass.kt b/compiler/testData/ir/interpreter/dataClass.kt new file mode 100644 index 00000000000..14f4a87a9cd --- /dev/null +++ b/compiler/testData/ir/interpreter/dataClass.kt @@ -0,0 +1,19 @@ +@CompileTimeCalculation +data class Person(val name: String, val phone: Int) + +@CompileTimeCalculation +fun Person.getAsString(): String { + val (name, phone) = this + return "Person name is $name and his phone is $phone" +} + +const val a1 = Person("John", 123456).name +const val a2 = Person("John", 123456).component1() +const val a3 = Person("John", 123456).phone +const val a4 = Person("John", 123456).component2() + +const val b1 = Person("John", 789).copy("Adam").toString() +const val b2 = Person("John", 789).copy("Adam", 123).toString() + +const val c = Person("John", 123456).equals(Person("John", 123456)) +const val d = Person("John", 123456).getAsString() diff --git a/compiler/testData/ir/interpreter/defaultArgs.kt b/compiler/testData/ir/interpreter/defaultArgs.kt new file mode 100644 index 00000000000..1ec374036f6 --- /dev/null +++ b/compiler/testData/ir/interpreter/defaultArgs.kt @@ -0,0 +1,12 @@ +@CompileTimeCalculation +fun sum(a: Int = 1, b: Int = 2, c: Int = 3) = a + b + c + +@CompileTimeCalculation +fun sumBasedOnPrevious(a: Int = 1, b: Int = a * 2, c: Int = b * 2) = a + b + c + +const val sum1 = sum() +const val sum2 = sum(b = -3) +const val sum3 = sum(c = 1, a = 1, b = 1) + +const val sumBasedOnPrevious1 = sumBasedOnPrevious() +const val sumBasedOnPrevious2 = sumBasedOnPrevious(b = 1, c = 1) diff --git a/compiler/testData/ir/interpreter/defaultEquals.kt b/compiler/testData/ir/interpreter/defaultEquals.kt new file mode 100644 index 00000000000..84617eae19a --- /dev/null +++ b/compiler/testData/ir/interpreter/defaultEquals.kt @@ -0,0 +1,13 @@ +@CompileTimeCalculation +class A + +@CompileTimeCalculation +fun getTheSameValue(a: Any): Any = a + +@CompileTimeCalculation +fun theSameObjectEquals(value: Any): Boolean { + return value == getTheSameValue(value) && value === getTheSameValue(value) +} + +const val equals1 = A().equals(A()) +const val equals2 = theSameObjectEquals(A()) diff --git a/compiler/testData/ir/interpreter/defaultHashCode.kt b/compiler/testData/ir/interpreter/defaultHashCode.kt new file mode 100644 index 00000000000..983fb5f3cf4 --- /dev/null +++ b/compiler/testData/ir/interpreter/defaultHashCode.kt @@ -0,0 +1,59 @@ +@CompileTimeCalculation +open class A + +class B @CompileTimeCalculation constructor() { + @CompileTimeCalculation + override fun hashCode(): Int { + return super.hashCode() + } +} + +class C + +class D : A() + +@CompileTimeCalculation +fun checkHashCodeCorrectness(value: Any): Boolean { + val hashCode = value.hashCode() + return hashCode.toHex().length == 8 && hashCode == value.hashCode() +} + +@CompileTimeCalculation +fun getTheSameValue(a: Any): Any = a + +@CompileTimeCalculation +fun theSameObjectHashCode(value: Any): Boolean { + return value.hashCode() == getTheSameValue(value).hashCode() +} + +@CompileTimeCalculation +fun Int.toHex(): String { + val sb = StringBuilder() + val hexDigits = charArrayOf( + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + ) + var value = this + + var i = 8 + while (i > 0) { + i -= 1 + val j = value.and(0x0F) + sb.append(hexDigits[j]) + value = value.shr(4) + } + + return sb.reverse().toString() +} + +const val aHashCode = checkHashCodeCorrectness(A()) +const val bHashCode = checkHashCodeCorrectness(B()) +val cHashCode = C().hashCode() // must not be calculated +val dHashCode = D().hashCode() // must not be calculated + +const val arrayHashCode = checkHashCodeCorrectness(arrayOf(A(), B())) +const val intArrayHashCode = checkHashCodeCorrectness(arrayOf(1, 2, 3)) + +const val checkA = theSameObjectHashCode(A()) +const val checkStringBuilder1 = theSameObjectHashCode(StringBuilder()) +const val checkStringBuilder2 = theSameObjectHashCode(StringBuilder("Some Builder")) diff --git a/compiler/testData/ir/interpreter/defaultToString.kt b/compiler/testData/ir/interpreter/defaultToString.kt new file mode 100644 index 00000000000..94e77427aa6 --- /dev/null +++ b/compiler/testData/ir/interpreter/defaultToString.kt @@ -0,0 +1,39 @@ +@CompileTimeCalculation +open class A + +class B @CompileTimeCalculation constructor() { + @CompileTimeCalculation + override fun toString(): String { + return super.toString() + } +} + +class C + +class D : A() + +@CompileTimeCalculation +fun checkToStringCorrectness(value: Any, startStr: String): Boolean { + val string = value.toString() + return string.subSequence(0, startStr.length) == startStr && string.get(startStr.length) == '@' && string.length <= startStr.length + 9 +} + +@CompileTimeCalculation +fun getTheSameValue(a: Any): Any = a + +@CompileTimeCalculation +fun theSameObjectToString(value: Any): Boolean { + return value.toString() == getTheSameValue(value).toString() +} + +const val aString = checkToStringCorrectness(A(), "A") +const val bString = checkToStringCorrectness(B(), "B") +val cString = C().toString() // must not be calculated +val dString = D().toString() // must not be calculated + +const val arrayString = checkToStringCorrectness(arrayOf(A(), B()).toString(), "[Ljava.lang.Object;") +const val intArrayString = checkToStringCorrectness(intArrayOf(1, 2, 3).toString(), "[I") + +const val checkA = theSameObjectToString(A()) +const val checkStringBuilder1 = theSameObjectToString(StringBuilder()) +const val checkStringBuilder2 = theSameObjectToString(StringBuilder("Some Builder")) diff --git a/compiler/testData/ir/interpreter/doWhileLoop.kt b/compiler/testData/ir/interpreter/doWhileLoop.kt new file mode 100644 index 00000000000..5fc3b4267cc --- /dev/null +++ b/compiler/testData/ir/interpreter/doWhileLoop.kt @@ -0,0 +1,34 @@ +@CompileTimeCalculation +fun factorialDoWhile(num: Int): Int { + var number = num + var factorial = 1 + + do { + factorial *= number + number-- + } while (number > 0) + + return factorial +} + +@CompileTimeCalculation +fun firstNotNull(array: Array): Int { + var i = 0 + + do { + val y = array[i++] + } while (y == null) + + return array[i - 1]!! +} + +@CompileTimeCalculation +fun singleExpressionLoop(incrementTo: Int): Int { + var i = 0 + do i++ while (i < incrementTo) + return i +} + +const val a = factorialDoWhile(6) +const val b = firstNotNull(arrayOf(null, null, 1, 2, null)) +const val c = singleExpressionLoop(10) diff --git a/compiler/testData/ir/interpreter/doubleArrayOf.kt b/compiler/testData/ir/interpreter/doubleArrayOf.kt new file mode 100644 index 00000000000..ae535a7ef81 --- /dev/null +++ b/compiler/testData/ir/interpreter/doubleArrayOf.kt @@ -0,0 +1,13 @@ +import kotlin.collections.* + +const val doubleArray = arrayOf( + arrayOf(1, 2, 3), + arrayOf(4, 5), + arrayOf(6) +).joinToString(separator = "; ") { it.joinToString() } + +const val doubleUintArray = arrayOf( + arrayOf(1u, 2u, 3u), + arrayOf(4u, 5u), + arrayOf(6u) +).joinToString(separator = "; ") { it.joinToString() } diff --git a/compiler/testData/ir/interpreter/elvis.kt b/compiler/testData/ir/interpreter/elvis.kt new file mode 100644 index 00000000000..b0e1a5ba08e --- /dev/null +++ b/compiler/testData/ir/interpreter/elvis.kt @@ -0,0 +1,5 @@ +@CompileTimeCalculation +fun getLenght(value: String?): Int = value?.length ?: -1 + +const val a1 = getLenght("Elvis") +const val a2 = getLenght(null) diff --git a/compiler/testData/ir/interpreter/enums1.kt b/compiler/testData/ir/interpreter/enums1.kt new file mode 100644 index 00000000000..b1a518fd548 --- /dev/null +++ b/compiler/testData/ir/interpreter/enums1.kt @@ -0,0 +1,25 @@ +import kotlin.* +import kotlin.collections.* + +@CompileTimeCalculation +enum class EnumClass { + VALUE1, VALUE2 +} + +const val a = EnumClass.VALUE1.name +const val b = EnumClass.values().size +const val c = EnumClass.valueOf("VALUE1").ordinal +const val d = EnumClass.valueOf("VALUE3").(enums1.kt:12)`!>ordinal + +const val e1 = EnumClass.VALUE1.hashCode().let { it is Int && it > 0 && it == EnumClass.VALUE1.hashCode() } +const val e2 = EnumClass.VALUE1.toString() +const val e3 = EnumClass.VALUE1 == EnumClass.VALUE1 +const val e4 = EnumClass.VALUE1 == EnumClass.VALUE2 + +const val f1 = enumValues().size +const val f2 = enumValueOf("VALUE1").name + +const val j1 = enumValues().joinToString { it.name } diff --git a/compiler/testData/ir/interpreter/enums2.kt b/compiler/testData/ir/interpreter/enums2.kt new file mode 100644 index 00000000000..ca376511252 --- /dev/null +++ b/compiler/testData/ir/interpreter/enums2.kt @@ -0,0 +1,26 @@ +@CompileTimeCalculation +enum class Empty + +@CompileTimeCalculation +enum class Color(val rgb: Int) { + BLACK() { override fun getColorAsString() = "0x000000" }, + RED(0xFF0000) { override fun getColorAsString() = "0xFF0000" }, + GREEN(0x00FF00) { override fun getColorAsString() = "0x00FF00" }, + BLUE(0x0000FF) { override fun getColorAsString() = "0x0000FF" }; + + constructor() : this(0x000000) {} + + abstract fun getColorAsString(): String + + fun getColorAsInt(): Int = rgb +} + +const val a1 = Empty.values().size +const val a2 = enumValues().size + +const val b1 = Color.BLACK.name +const val b2 = Color.BLACK.getColorAsString() +const val b3 = Color.RED.getColorAsString() + +const val c1 = Color.BLACK.getColorAsInt() +const val c2 = Color.RED.getColorAsInt() diff --git a/compiler/testData/ir/interpreter/enums3.kt b/compiler/testData/ir/interpreter/enums3.kt new file mode 100644 index 00000000000..dbd5741e83d --- /dev/null +++ b/compiler/testData/ir/interpreter/enums3.kt @@ -0,0 +1,9 @@ +import kotlin.text.* + +const val a = RegexOption.IGNORE_CASE.name +const val b = RegexOption.IGNORE_CASE.ordinal +const val c = RegexOption.MULTILINE.name +const val d = RegexOption.MULTILINE.ordinal +const val e = RegexOption.IGNORE_CASE == RegexOption.IGNORE_CASE +const val f = RegexOption.IGNORE_CASE != RegexOption.MULTILINE +const val g = RegexOption.IGNORE_CASE.toString() diff --git a/compiler/testData/ir/interpreter/exceptions/arithmeticExceptionThrow.kt b/compiler/testData/ir/interpreter/exceptions/arithmeticExceptionThrow.kt new file mode 100644 index 00000000000..44694b5d733 --- /dev/null +++ b/compiler/testData/ir/interpreter/exceptions/arithmeticExceptionThrow.kt @@ -0,0 +1,88 @@ +@CompileTimeCalculation +fun throwExample(a: Int, b: Int): Int { + if (b == 0) throw ArithmeticException("Divide by zero") + return a / b +} + +@CompileTimeCalculation +fun throwNullMessage(a: Int, b: Int): Int { + if (b == 0) throw ArithmeticException(null) + return a / b +} + +const val a1 = try { + throwExample(10, 0) + true +} catch (e: ArithmeticException) { + false +} +const val a2 = try { + throwExample(10, 1) + true +} catch (e: ArithmeticException) { + false +} + +const val b1 = try { + throwExample(10, 0) + true +} catch (e: Exception) { + false +} +const val b2 = try { + throwExample(10, 1) + true +} catch (e: Exception) { + false +} +const val b3 = try { + throwExample(10, 0) + true +} catch (e: Throwable) { + false +} + +const val c1 = try { + throwExample(10, 0) + 0 +} catch (e: ArithmeticException) { + 1 +} catch (e: Exception) { + 2 +} +const val c2 = try { + throwExample(10, 0) + 0 +} catch (e: Exception) { + 1 +} catch (e: ArithmeticException) { + 2 +} +const val c3 = try { + throwExample(10, 0) + 0 +} catch (e: NullPointerException) { + 1 +} catch (e: ArithmeticException) { + 2 +} + +const val d1 = try { + throwExample(10, 0) + "Without exception" +} catch (e: ArithmeticException) { + e.message ?: "Exception without message" +} +const val d2 = try { + throwExample(10, 1) + "Without exception" +} catch (e: ArithmeticException) { + e.message ?: "Exception without message" +} + +const val nullMessage = try { + throwNullMessage(10, 0) + "Without exception" +} catch (e: ArithmeticException) { + e.message ?: "Exception without message" +} diff --git a/compiler/testData/ir/interpreter/exceptions/arithmeticExceptionTryBlock.kt b/compiler/testData/ir/interpreter/exceptions/arithmeticExceptionTryBlock.kt new file mode 100644 index 00000000000..3d45fe0213d --- /dev/null +++ b/compiler/testData/ir/interpreter/exceptions/arithmeticExceptionTryBlock.kt @@ -0,0 +1,28 @@ +@CompileTimeCalculation +fun tryCatch(integer: Int): Boolean { + try { + val a = 10 / integer + return true + } catch (e: ArithmeticException) { + return false + } +} + +const val a1 = tryCatch(0) +const val a2 = tryCatch(1) +const val a3 = tryCatch(100) + +@CompileTimeCalculation +fun multiTryCatch(integer: Int): String { + return try { + val a = 10 / integer + "Normal" + } catch (e: AssertionError) { + "AssertionError" + } catch (e: ArithmeticException) { + "ArithmeticException" + } +} + +const val b1 = multiTryCatch(0) +const val b2 = multiTryCatch(1) diff --git a/compiler/testData/ir/interpreter/exceptions/arithmeticExceptionTryCatchFinally.kt b/compiler/testData/ir/interpreter/exceptions/arithmeticExceptionTryCatchFinally.kt new file mode 100644 index 00000000000..0e8cb3dbc8c --- /dev/null +++ b/compiler/testData/ir/interpreter/exceptions/arithmeticExceptionTryCatchFinally.kt @@ -0,0 +1,27 @@ +@CompileTimeCalculation +fun tryCatch(integer: Int): String { + var str = "" + try { + str += "Start dividing\n" + val a = 10 / integer + str += "Without exception\n" + } catch (e: ArithmeticException) { + str += "Exception\n" + } finally { + str += "Finally\n" + } + return str +} + +const val a1 = tryCatch(0) +const val a2 = tryCatch(1) +const val a3 = tryCatch(100) diff --git a/compiler/testData/ir/interpreter/exceptions/classCastException.kt b/compiler/testData/ir/interpreter/exceptions/classCastException.kt new file mode 100644 index 00000000000..e820402b767 --- /dev/null +++ b/compiler/testData/ir/interpreter/exceptions/classCastException.kt @@ -0,0 +1,73 @@ +import kotlin.* +import kotlin.collections.* + +@CompileTimeCalculation +fun classCastWithException(a: Any): String { + return try { + a as Int + "Given value is $a and its doubled value is ${2 * a}" + } catch (e: ClassCastException) { + "Given value isnt't Int; Exception message: \"${e.message}\"" + } +} + +@CompileTimeCalculation +fun safeClassCast(a: Any): Int { + return (a as? String)?.length ?: -1 +} + +@CompileTimeCalculation +fun unsafeClassCast(): T { + return 1 as T +} + +@CompileTimeCalculation +fun getIntList() = listOf(1, 2) as T + +@CompileTimeCalculation +fun getStringNullableList() = listOf(null, "1") as T + +@CompileTimeCalculation +fun getLength(str: String) = str.length + +@CompileTimeCalculation +class A() { + fun unsafeCast(): T { + return 1 as T + } +} + +const val a1 = classCastWithException(10) +const val a2 = classCastWithException("10") + +const val b1 = safeClassCast(10) +const val b2 = safeClassCast("10") + +// in this example all unsafe cast will be "successful", but will fall when trying to assign +const val c1 = unsafeClassCast() +const val c2 = (classCastException.kt:48)`!>unsafeClassCast() + +const val d1 = A().unsafeCast() +const val d2 = A().(classCastException.kt:51)`!>unsafeCast() + +const val stringList = getIntList>().(classCastException.kt:54) + at StandardKt.kotlin.let(Standard.kt:32) + at ClassCastExceptionKt.(classCastException.kt:53)`!>let { + it[0].length +} +const val nullableStringList = getStringNullableList>().(classCastException.kt) + at StandardKt.kotlin.let(Standard.kt:32) + at ClassCastExceptionKt.(classCastException.kt:56)`!>let { it[0].length } +const val nullableStringLength = (classCastException.kt:31)`!>getLength(getStringNullableList>()[0]) diff --git a/compiler/testData/ir/interpreter/exceptions/commandsOutException.kt b/compiler/testData/ir/interpreter/exceptions/commandsOutException.kt new file mode 100644 index 00000000000..8aded041aa8 --- /dev/null +++ b/compiler/testData/ir/interpreter/exceptions/commandsOutException.kt @@ -0,0 +1,10 @@ +@CompileTimeCalculation +fun infinityWhile(): Int { + while (true) {} + return 0 +} + +const val a = (commandsOutException.kt:7)`!>infinityWhile() diff --git a/compiler/testData/ir/interpreter/exceptions/divideByZero.kt b/compiler/testData/ir/interpreter/exceptions/divideByZero.kt new file mode 100644 index 00000000000..2ee3b6f6c2d --- /dev/null +++ b/compiler/testData/ir/interpreter/exceptions/divideByZero.kt @@ -0,0 +1,15 @@ +const val a = try { + 10 / 0 + 0 +} catch (e: RuntimeException) { + 1 +} + +const val b = (divideByZero.kt:8)`!>10 / 0 + +// not working for now, but maybe will be supported +//fun someFunWithCompileTimeInside() { +// val exceptionExpected = 1 / 0 +//} \ No newline at end of file diff --git a/compiler/testData/ir/interpreter/exceptions/exceptionFromWrapper.kt b/compiler/testData/ir/interpreter/exceptions/exceptionFromWrapper.kt new file mode 100644 index 00000000000..307e0d3f4fb --- /dev/null +++ b/compiler/testData/ir/interpreter/exceptions/exceptionFromWrapper.kt @@ -0,0 +1,12 @@ +@CompileTimeCalculation +fun append(sb: StringBuilder, value: CharSequence, start: Int, end: Int): String { + return sb.append(value, start, end).toString() +} + +const val a = append(StringBuilder("Some string with not zero length"), "!!!", 0, 3) +const val b = (exceptionFromWrapper.kt:7)`!>append(StringBuilder("Some string with not zero length"), "!!!", -1, 0) diff --git a/compiler/testData/ir/interpreter/exceptions/exceptionWithCause.kt b/compiler/testData/ir/interpreter/exceptions/exceptionWithCause.kt new file mode 100644 index 00000000000..ecbea650c07 --- /dev/null +++ b/compiler/testData/ir/interpreter/exceptions/exceptionWithCause.kt @@ -0,0 +1,49 @@ +// https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Throwable.html#printStackTrace() +@CompileTimeCalculation +class HighLevelException(cause: Throwable?) : Exception(cause) +@CompileTimeCalculation +class MidLevelException(cause: Throwable?) : Exception(cause) +@CompileTimeCalculation +class LowLevelException : Exception() + +@CompileTimeCalculation +class Junk { + public fun a(): Nothing { + try { + b() + } catch (e: MidLevelException) { + throw HighLevelException(e) + } + } + + private fun b(): Nothing = c() + + private fun c(): Nothing { + try { + d() + } catch (e: LowLevelException) { + throw MidLevelException(e) + } + } + + private fun d(): Nothing = e() + + private fun e(): Nothing = throw LowLevelException() +} + +const val exceptionWithCause = Junk().a().(exceptionWithCause.kt:34) +Caused by: MidLevelException: LowLevelException + at ExceptionWithCauseKt.Junk.c(exceptionWithCause.kt:25) + at ExceptionWithCauseKt.Junk.b(exceptionWithCause.kt:19) + at ExceptionWithCauseKt.Junk.a(exceptionWithCause.kt:13) + at ExceptionWithCauseKt.(exceptionWithCause.kt:34) +Caused by: LowLevelException + at ExceptionWithCauseKt.Junk.e(exceptionWithCause.kt:31) + at ExceptionWithCauseKt.Junk.d(exceptionWithCause.kt:29) + at ExceptionWithCauseKt.Junk.c(exceptionWithCause.kt:23) + at ExceptionWithCauseKt.Junk.b(exceptionWithCause.kt:19) + at ExceptionWithCauseKt.Junk.a(exceptionWithCause.kt:13) + at ExceptionWithCauseKt.(exceptionWithCause.kt:34)`!>toString() diff --git a/compiler/testData/ir/interpreter/exceptions/getCauseMessage.kt b/compiler/testData/ir/interpreter/exceptions/getCauseMessage.kt new file mode 100644 index 00000000000..5a760fde85a --- /dev/null +++ b/compiler/testData/ir/interpreter/exceptions/getCauseMessage.kt @@ -0,0 +1,22 @@ +import kotlin.* + +@CompileTimeCalculation +fun getArrayElement(array: IntArray, index: Int): Int { + try { + return array[index] + } catch (e: IndexOutOfBoundsException) { + throw IllegalArgumentException("Index must be less than array size and greater than zero", e) + } +} + +const val a = try { + getArrayElement(intArrayOf(1, 2, 3), -1).let { "Element at given index is " + it } +} catch (e: Exception) { + e.cause?.message ?: "Exception without message" +} + +const val b = try { + getArrayElement(intArrayOf(1, 2, 3), 0).let { "Element at given index is " + it } +} catch (e: Exception) { + e.cause?.message ?: "Exception without message" +} diff --git a/compiler/testData/ir/interpreter/exceptions/multifileStackTrace.kt b/compiler/testData/ir/interpreter/exceptions/multifileStackTrace.kt new file mode 100644 index 00000000000..dc394d6620f --- /dev/null +++ b/compiler/testData/ir/interpreter/exceptions/multifileStackTrace.kt @@ -0,0 +1,20 @@ +// FILE: main.kt + +@CompileTimeCalculation +fun callToOtherFile(mustThrowException: Boolean, message: String): Int { + if (mustThrowException) throwException(message) + return 0 +} + +const val a = (main.kt:9)`!>callToOtherFile(true, "Exception from file1.kt") + +// FILE: file1.kt + +@CompileTimeCalculation +fun throwException(message: String) { + throw Exception(message) +} diff --git a/compiler/testData/ir/interpreter/exceptions/nullPointerException.kt b/compiler/testData/ir/interpreter/exceptions/nullPointerException.kt new file mode 100644 index 00000000000..cc5471ae1bb --- /dev/null +++ b/compiler/testData/ir/interpreter/exceptions/nullPointerException.kt @@ -0,0 +1,48 @@ +@CompileTimeCalculation +class A + +@CompileTimeCalculation +fun notNullAssertion(value: Int?): String { + return try { + value!! + "Value isn't null" + } catch (e: NullPointerException) { + "Value is null" + } +} + +@CompileTimeCalculation +fun notNullAssertionForObject(value: A?): String { + return try { + value!! + "Value isn't null" + } catch (e: NullPointerException) { + "Value is null" + } +} + +@CompileTimeCalculation +fun notNullAssertionForSomeWrapper(value: StringBuilder?): String { + return try { + value!!.toString() + } catch (e: NullPointerException) { + "Value is null" + } +} + +@CompileTimeCalculation +fun notNullLambda(lambda: (() -> String)?): String { + return when { + lambda != null -> lambda() + else -> "Lambda is null" + } +} + +const val a1 = notNullAssertion(1) +const val a2 = notNullAssertion(null) +const val b1 = notNullAssertionForObject(A()) +const val b2 = notNullAssertionForObject(null) +const val c1 = notNullAssertionForSomeWrapper(StringBuilder("Some text")) +const val c2 = notNullAssertionForSomeWrapper(null) +const val d1 = notNullLambda { "Not null lambda" } +const val d2 = notNullLambda(null) diff --git a/compiler/testData/ir/interpreter/exceptions/stackOverflow.kt b/compiler/testData/ir/interpreter/exceptions/stackOverflow.kt new file mode 100644 index 00000000000..5a07b3ecaff --- /dev/null +++ b/compiler/testData/ir/interpreter/exceptions/stackOverflow.kt @@ -0,0 +1,22 @@ +@CompileTimeCalculation +fun foo(i: Int): Int = foo(i + 1) +const val overflow = foo(0) + +@CompileTimeCalculation +fun withPossibleOverflow(x: Int): Int { + if (x == 0) return 0 + return withPossibleOverflow(x - 1) + 1 +} +const val notOverflow = withPossibleOverflow(5_000) diff --git a/compiler/testData/ir/interpreter/exceptions/stackTrace.kt b/compiler/testData/ir/interpreter/exceptions/stackTrace.kt new file mode 100644 index 00000000000..0b6bbeeec5b --- /dev/null +++ b/compiler/testData/ir/interpreter/exceptions/stackTrace.kt @@ -0,0 +1,27 @@ +@CompileTimeCalculation +fun divide(a: Int, b: Int) = a / b + +@CompileTimeCalculation +fun echo(a : Int, b: Int) = divide(a, b) + +@CompileTimeCalculation +fun getLengthOrThrowException(str: String?): Int { + try { + return str!!.length + } catch (e: NullPointerException) { + throw UnsupportedOperationException(e) + } +} + +const val a = (stackTrace.kt:16)`!>echo(1, 0) +const val b = (stackTrace.kt:17) +Caused by: java.lang.NullPointerException + at StackTraceKt.getLengthOrThrowException(stackTrace.kt:10) + at StackTraceKt.(stackTrace.kt:17)`!>getLengthOrThrowException(null) diff --git a/compiler/testData/ir/interpreter/exceptions/tryFinally.kt b/compiler/testData/ir/interpreter/exceptions/tryFinally.kt new file mode 100644 index 00000000000..d5ebadb753d --- /dev/null +++ b/compiler/testData/ir/interpreter/exceptions/tryFinally.kt @@ -0,0 +1,215 @@ +@CompileTimeCalculation +fun tryFinally(initValue: Int): Int { + var x = initValue + try { + return x + } finally { + x = x + 1 // result is never used + } +} + +@CompileTimeCalculation +fun tryFinally2(): String { + var str: String = "" + try { + str += "Inside try block; " + } finally { + str += "Inside finally; " + } + str += "Outside try; " + return str +} + +@CompileTimeCalculation +fun outerReturnTryFinally(n: Int): Int { + return try { + n + } finally { + -1 + } +} + +@CompileTimeCalculation +fun exceptionInFinally(divideBy: Int): Int { + return try { + 0 + } finally { + 1 / divideBy + } +} + +@CompileTimeCalculation +fun tryCatchFinally(): Int { + try { + throw IllegalArgumentException("In try") + } catch (e: IllegalArgumentException) { + throw IllegalArgumentException("In catch") + } finally { + throw IllegalArgumentException("In finally") + } + return 0 +} + +@CompileTimeCalculation +fun returnTryFinally(): String { + return try { "OK" } finally { "NOT OK" } // result from finally is never used +} + +@CompileTimeCalculation +fun tryCatchReturnFinally(divideBy: Int): Int { + var y = 0 + try { + 1 / divideBy + } catch (e: ArithmeticException) { + return y + } finally { + y++ + } + + return y +} + +@CompileTimeCalculation +fun tryFinallyContinue(): Int { + var y = 0 + while (y < 10) { + try { + continue + } finally { + y++ + } + + throw IllegalStateException("\"continue\" must drop remaining frame") + } + + return y +} + +@CompileTimeCalculation +fun tryFinallyBreak(): Int { + var y = 0 + while (y < 10) { + try { + break + } finally { + y++ + } + } + + return y +} + +@CompileTimeCalculation +fun tryCatchFinallyContinue(divideBy: Int): Int { + var y = 0 + while (y < 10) { + try { + 1 / divideBy + } catch (e: ArithmeticException) { + continue + } finally { + y++ + } + + throw IllegalStateException("\"continue\" must drop remaining frame") + } + + return y +} + +@CompileTimeCalculation +fun innerTryFinally(n: Int): Int { + try { + try { + return 1 + } finally { + n + 1 + } + return 2 + } finally { + n + 10 + } + return 3 +} + +@CompileTimeCalculation +fun innerTryFinallyReturn(n: Int): Int { + //return n / 0 + try { + try { + return 1 + } finally { + n + 1 + } + return 2 + } finally { + return n + 10 + } + return 3 +} + +@CompileTimeCalculation +fun tryCatch(n: Int): Int { + return try { + delete(n) + } catch (e: ArithmeticException) { + -1 + } finally { + -2 + } +} + +@CompileTimeCalculation +fun delete(n: Int): Int { + return try { + 1 / n + } catch (e: NullPointerException) { + -1 + } finally { + -2 + } +} + +@CompileTimeCalculation +fun tryTryFinally(): Int { + val zero = 0 + val nullable: Int? = null + try { + try { + 1 / zero + } finally { + nullable!! + } + } catch (e: NullPointerException) { + return -1 + } finally { + + } + + return 0 +} + +const val a1 = tryFinally(0) +const val a2 = tryFinally(10) +//const val a3 = outerReturnTryFinally(10) TODO -> `10` +const val b1 = tryFinally2() +const val c1 = (tryFinally.kt:196)`!>tryCatchFinally() +const val c2 = exceptionInFinally(10) +const val c3 = (tryFinally.kt:198)`!>exceptionInFinally(0) +//const val d1 = returnTryFinally() TODO -> `OK` +const val d2 = tryCatchReturnFinally(10) +const val d3 = tryCatchReturnFinally(0) +const val e1 = tryFinallyContinue() +const val e2 = tryFinallyBreak() +const val e3 = tryCatchFinallyContinue(0) +//const val f1 = innerTryFinally(10) TODO -> `1` +const val f2 = innerTryFinallyReturn(10) +//const val g1 = tryCatch(10) TODO -> `0` +//const val g2 = tryCatch(0) TODO -> `-1` +//const val h1 = tryTryFinally() TODO -> `-1` diff --git a/compiler/testData/ir/interpreter/extensionReceiver.kt b/compiler/testData/ir/interpreter/extensionReceiver.kt new file mode 100644 index 00000000000..65b6d41c16d --- /dev/null +++ b/compiler/testData/ir/interpreter/extensionReceiver.kt @@ -0,0 +1,19 @@ +@CompileTimeCalculation +fun Int.get(): Int { + return this +} + +@CompileTimeCalculation +class A(val length: Int) { + fun String.hasRightLength(): Boolean { + return this@hasRightLength.length == this@A.length + } + + fun check(string: String): Boolean { + return string.hasRightLength() + } +} + +const val simple = 1.get() +const val right = A(3).check("123") +const val wrong = A(2).check("123") diff --git a/compiler/testData/ir/interpreter/fib.kt b/compiler/testData/ir/interpreter/fib.kt new file mode 100644 index 00000000000..e333b34c786 --- /dev/null +++ b/compiler/testData/ir/interpreter/fib.kt @@ -0,0 +1,9 @@ +@CompileTimeCalculation +fun fib(n: Int) : Int { + if (n <= 1) return n + return fib(n - 1) + fib(n - 2) +} + +const val n2 = fib(2) +const val n10 = fib(10) +const val n18 = fib(18) diff --git a/compiler/testData/ir/interpreter/generatedStdlib/contains.kt b/compiler/testData/ir/interpreter/generatedStdlib/contains.kt new file mode 100644 index 00000000000..7110def158a --- /dev/null +++ b/compiler/testData/ir/interpreter/generatedStdlib/contains.kt @@ -0,0 +1,7 @@ +import kotlin.collections.* +import kotlin.sequences.* + +const val a = intArrayOf(1, 2, 3).contains(1) +const val b = intArrayOf(1, 2, 3).contains(4) +const val c = arrayOf(1, "2", 3.0).contains("2") +const val d = sequenceOf(1, 2, 3).contains(2) diff --git a/compiler/testData/ir/interpreter/generatedStdlib/elementAtOrElse.kt b/compiler/testData/ir/interpreter/generatedStdlib/elementAtOrElse.kt new file mode 100644 index 00000000000..0b45c5bdb36 --- /dev/null +++ b/compiler/testData/ir/interpreter/generatedStdlib/elementAtOrElse.kt @@ -0,0 +1,9 @@ +import kotlin.* +import kotlin.collections.* +import kotlin.text.* + +const val a = listOf(1, 2, 3).elementAtOrElse(1) { -1 } +const val b = listOf(1, 2, 3).elementAtOrElse(4) { -1 } +const val c = uintArrayOf(1u, 2u, 3u, 4u).elementAtOrElse(2) { 0u } +const val d = "abcd".elementAtOrElse(2) { '0' } +const val e = "abcd".elementAtOrElse(4) { '0' } diff --git a/compiler/testData/ir/interpreter/generatedStdlib/first.kt b/compiler/testData/ir/interpreter/generatedStdlib/first.kt new file mode 100644 index 00000000000..4f6af978191 --- /dev/null +++ b/compiler/testData/ir/interpreter/generatedStdlib/first.kt @@ -0,0 +1,11 @@ +import kotlin.* +import kotlin.collections.* +import kotlin.text.* + +const val a = "abcs".first() +const val b = UIntArray(3) { it.toUInt() }.first() +const val c = listOf(1, "2", 3.0).first() as Int +const val d = listOf().(first.kt:8)`!>first() diff --git a/compiler/testData/ir/interpreter/generatedStdlib/joinToString.kt b/compiler/testData/ir/interpreter/generatedStdlib/joinToString.kt new file mode 100644 index 00000000000..b72e5c2d77a --- /dev/null +++ b/compiler/testData/ir/interpreter/generatedStdlib/joinToString.kt @@ -0,0 +1,5 @@ +import kotlin.collections.* +import kotlin.sequences.* + +const val a = listOf(1, 2, 3).joinToString() +const val b = sequenceOf(-1, -2, -3).joinToString(separator = ".") diff --git a/compiler/testData/ir/interpreter/generatedStdlib/toList.kt b/compiler/testData/ir/interpreter/generatedStdlib/toList.kt new file mode 100644 index 00000000000..bcd6166f419 --- /dev/null +++ b/compiler/testData/ir/interpreter/generatedStdlib/toList.kt @@ -0,0 +1,16 @@ +import kotlin.* +import kotlin.collections.* +import kotlin.text.* +import kotlin.sequences.* + +const val zeroElementIntArrayToList = intArrayOf().toList().size +const val singleElementIntArrayToList = intArrayOf(1).toList().size +const val intArrayToList = intArrayOf(1, 2, 3).toList().size +const val customArrayToList = arrayOf(1, "2", 3.0, "Some other value").toList()[3] as String + +const val listFromSet = setOf(1, 2, 2, 3, 3).toList().joinToString() +const val listFromIterable = mapOf(1 to "One", 2 to "Two", 3 to "Three").entries.toList().joinToString() + +const val stringToList = "String".toList().joinToString() + +const val sequenceToList = sequenceOf(3, 2, 1).toList().joinToString() diff --git a/compiler/testData/ir/interpreter/generatedStdlib/trim.kt b/compiler/testData/ir/interpreter/generatedStdlib/trim.kt new file mode 100644 index 00000000000..0fa3c91dfc3 --- /dev/null +++ b/compiler/testData/ir/interpreter/generatedStdlib/trim.kt @@ -0,0 +1,5 @@ +import kotlin.text.* + +const val trimmed = " 1 ".trim() +const val trimmedWithPredicate = (" 2 " as CharSequence).trim { it.isWhitespace() }.toString() +const val charSequenceTrim = (" 3 " as CharSequence).trim().toString() diff --git a/compiler/testData/ir/interpreter/genericListOfPairs.kt b/compiler/testData/ir/interpreter/genericListOfPairs.kt new file mode 100644 index 00000000000..7e8178991a1 --- /dev/null +++ b/compiler/testData/ir/interpreter/genericListOfPairs.kt @@ -0,0 +1,11 @@ +import kotlin.* +import kotlin.collections.* + +@CompileTimeCalculation +fun listOfPairs(): String { + val list = mutableListOf>() + list.add((1 to 100) as Pair) + list.add(("2" to "200") as Pair) + return "List size is: ${list.size}; first is Int: ${list[0].first is Int}; second is String: ${list[1].first is String}" +} +const val listOfPairsSize = listOfPairs() diff --git a/compiler/testData/ir/interpreter/helpers/Arrays.kt b/compiler/testData/ir/interpreter/helpers/Arrays.kt new file mode 100644 index 00000000000..18ee99de598 --- /dev/null +++ b/compiler/testData/ir/interpreter/helpers/Arrays.kt @@ -0,0 +1,234 @@ +@file:kotlin.jvm.JvmMultifileClass +@file:kotlin.jvm.JvmName("ArraysKt") + +package kotlin.collections + +public operator fun Array.contains(element: T): Boolean { + return indexOf(element) >= 0 +} +public operator fun ByteArray.contains(element: Byte): Boolean { + return indexOf(element) >= 0 +} +public operator fun ShortArray.contains(element: Short): Boolean { + return indexOf(element) >= 0 +} +public operator fun IntArray.contains(element: Int): Boolean { + return indexOf(element) >= 0 +} +public operator fun LongArray.contains(element: Long): Boolean { + return indexOf(element) >= 0 +} +public operator fun BooleanArray.contains(element: Boolean): Boolean { + return indexOf(element) >= 0 +} +public operator fun CharArray.contains(element: Char): Boolean { + return indexOf(element) >= 0 +} + +public fun Array.indexOf(element: T): Int { + if (element == null) { + for (index in indices) { + if (this[index] == null) { + return index + } + } + } else { + for (index in indices) { + if (element == this[index]) { + return index + } + } + } + return -1 +} +public fun ByteArray.indexOf(element: Byte): Int { + for (index in indices) { + if (element == this[index]) { + return index + } + } + return -1 +} +public fun ShortArray.indexOf(element: Short): Int { + for (index in indices) { + if (element == this[index]) { + return index + } + } + return -1 +} +public fun IntArray.indexOf(element: Int): Int { + for (index in indices) { + if (element == this[index]) { + return index + } + } + return -1 +} +public fun LongArray.indexOf(element: Long): Int { + for (index in indices) { + if (element == this[index]) { + return index + } + } + return -1 +} +public fun BooleanArray.indexOf(element: Boolean): Int { + for (index in indices) { + if (element == this[index]) { + return index + } + } + return -1 +} +public fun CharArray.indexOf(element: Char): Int { + for (index in indices) { + if (element == this[index]) { + return index + } + } + return -1 +} + +public actual fun Array.asList(): List = kotlin.UnsupportedOperationException("This is intrinsic") +public actual fun ByteArray.asList(): List = kotlin.UnsupportedOperationException("This is intrinsic") +public actual fun ShortArray.asList(): List = kotlin.UnsupportedOperationException("This is intrinsic") +public actual fun IntArray.asList(): List = kotlin.UnsupportedOperationException("This is intrinsic") +public actual fun LongArray.asList(): List = kotlin.UnsupportedOperationException("This is intrinsic") +public actual fun FloatArray.asList(): List = kotlin.UnsupportedOperationException("This is intrinsic") +public actual fun DoubleArray.asList(): List = kotlin.UnsupportedOperationException("This is intrinsic") +public actual fun BooleanArray.asList(): List = kotlin.UnsupportedOperationException("This is intrinsic") +public actual fun CharArray.asList(): List = kotlin.UnsupportedOperationException("This is intrinsic") + +public val Array.indices: IntRange + get() = IntRange(0, lastIndex) +public val ByteArray.indices: IntRange + get() = IntRange(0, lastIndex) +public val ShortArray.indices: IntRange + get() = IntRange(0, lastIndex) +public val IntArray.indices: IntRange + get() = IntRange(0, lastIndex) +public val LongArray.indices: IntRange + get() = IntRange(0, lastIndex) +public val FloatArray.indices: IntRange + get() = IntRange(0, lastIndex) +public val DoubleArray.indices: IntRange + get() = IntRange(0, lastIndex) +public val BooleanArray.indices: IntRange + get() = IntRange(0, lastIndex) +public val CharArray.indices: IntRange + get() = IntRange(0, lastIndex) + +public inline fun Array.isEmpty(): Boolean { + return size == 0 +} + +public val Array.lastIndex: Int + get() = size - 1 +public val ByteArray.lastIndex: Int + get() = size - 1 +public val ShortArray.lastIndex: Int + get() = size - 1 +public val IntArray.lastIndex: Int + get() = size - 1 +public val LongArray.lastIndex: Int + get() = size - 1 +public val FloatArray.lastIndex: Int + get() = size - 1 +public val DoubleArray.lastIndex: Int + get() = size - 1 +public val BooleanArray.lastIndex: Int + get() = size - 1 +public val CharArray.lastIndex: Int + get() = size - 1 + +public fun ByteArray.first(): Int { + if (isEmpty()) throw NoSuchElementException("Array is empty.") + return this[0] +} +public fun ShortArray.first(): Int { + if (isEmpty()) throw NoSuchElementException("Array is empty.") + return this[0] +} +public fun IntArray.first(): Int { + if (isEmpty()) throw NoSuchElementException("Array is empty.") + return this[0] +} +public fun LongArray.first(): Int { + if (isEmpty()) throw NoSuchElementException("Array is empty.") + return this[0] +} + +public inline fun ByteArray.isEmpty(): Boolean = size == 0 +public inline fun ShortArray.isEmpty(): Boolean = size == 0 +public inline fun IntArray.isEmpty(): Boolean = size == 0 +public inline fun LongArray.isEmpty(): Boolean = size == 0 + +public fun Array.toList(): List { + return when (size) { + 0 -> emptyList() + 1 -> listOf(this[0]) + else -> this.toMutableList() + } +} +public fun IntArray.toList(): List { + return when (size) { + 0 -> emptyList() + 1 -> listOf(this[0]) + else -> this.toMutableList() + } +} + +public fun Array.toMutableList(): MutableList = kotlin.UnsupportedOperationException("This is intrinsic") +public fun IntArray.toMutableList(): MutableList { + val list = ArrayList(size) + for (item in this) list.add(item) + return list +} + +public fun > Array.toCollection(destination: C): C { + for (item in this) { + destination.add(item) + } + return destination +} + +public fun Array.toSet(): Set { + return when (size) { + 0 -> emptySet() + 1 -> setOf(this[0]) + else -> toCollection(LinkedHashSet(mapCapacity(size))) + } +} + +public fun Array.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String { + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +} + +public fun Array.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) { + buffer.appendElement(element, transform) + } else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} + +private fun Appendable.appendElement(element: T, transform: ((T) -> CharSequence)?) { + when { + transform != null -> append(transform(element)) + element is CharSequence? -> append(element) + element is Char -> append(element) + else -> append(element.toString()) + } +} + +public fun Array.asSequence(): Sequence { + if (isEmpty()) return emptySequence() + return Sequence { this.iterator() } +} \ No newline at end of file diff --git a/compiler/testData/ir/interpreter/helpers/Char.kt b/compiler/testData/ir/interpreter/helpers/Char.kt new file mode 100644 index 00000000000..41d19a699cd --- /dev/null +++ b/compiler/testData/ir/interpreter/helpers/Char.kt @@ -0,0 +1,6 @@ +@file:kotlin.jvm.JvmMultifileClass +@file:kotlin.jvm.JvmName("CharsKt") + +package kotlin.text + +public actual fun Char.isWhitespace(): Boolean = kotlin.UnsupportedOperationException("This is intrinsic") diff --git a/compiler/testData/ir/interpreter/helpers/Collections.kt b/compiler/testData/ir/interpreter/helpers/Collections.kt new file mode 100644 index 00000000000..013607cde2e --- /dev/null +++ b/compiler/testData/ir/interpreter/helpers/Collections.kt @@ -0,0 +1,176 @@ +@file:kotlin.jvm.JvmMultifileClass +@file:kotlin.jvm.JvmName("CollectionsKt") + +package kotlin.collections + +internal object EmptyIterator : ListIterator { + override fun hasNext(): Boolean = false + override fun hasPrevious(): Boolean = false + override fun nextIndex(): Int = 0 + override fun previousIndex(): Int = -1 + override fun next(): Nothing = throw NoSuchElementException() + override fun previous(): Nothing = throw NoSuchElementException() +} + +internal object EmptyList : List, Serializable, RandomAccess { + private const val serialVersionUID: Long = -7390468764508069838L + + override fun equals(other: Any?): Boolean = other is List<*> && other.isEmpty() + override fun hashCode(): Int = 1 + override fun toString(): String = "[]" + + override val size: Int get() = 0 + override fun isEmpty(): Boolean = true + override fun contains(element: Nothing): Boolean = false + override fun containsAll(elements: Collection): Boolean = elements.isEmpty() + + override fun get(index: Int): Nothing = throw IndexOutOfBoundsException("Empty list doesn't contain element at index $index.") + override fun indexOf(element: Nothing): Int = -1 + override fun lastIndexOf(element: Nothing): Int = -1 + + override fun iterator(): Iterator = EmptyIterator + override fun listIterator(): ListIterator = EmptyIterator + override fun listIterator(index: Int): ListIterator { + if (index != 0) throw IndexOutOfBoundsException("Index: $index") + return EmptyIterator + } + + override fun subList(fromIndex: Int, toIndex: Int): List { + if (fromIndex == 0 && toIndex == 0) return this + throw IndexOutOfBoundsException("fromIndex: $fromIndex, toIndex: $toIndex") + } + + private fun readResolve(): Any = EmptyList +} + +public fun emptyList(): List = EmptyList + +public fun listOf(vararg elements: T): List = if (elements.size > 0) elements.asList() else emptyList() + +public inline fun listOf(): List = emptyList() + +public inline fun mutableListOf(): MutableList = ArrayList() + +public inline fun arrayListOf(): ArrayList = ArrayList() + +public fun mutableListOf(vararg elements: T): MutableList = kotlin.UnsupportedOperationException("This is intrinsic") + +public fun arrayListOf(vararg elements: T): ArrayList = kotlin.UnsupportedOperationException("This is intrinsic") + +public fun listOfNotNull(element: T?): List = if (element != null) listOf(element) else emptyList() + +public inline fun List(size: Int, init: (index: Int) -> T): List = MutableList(size, init) + +public inline fun MutableList(size: Int, init: (index: Int) -> T): MutableList { + val list = ArrayList(size) + repeat(size) { index -> list.add(init(index)) } + return list +} + +public val Collection<*>.indices: IntRange + get() = 0..size - 1 + +public val List.lastIndex: Int + get() = this.size - 1 + +public inline fun Collection.isNotEmpty(): Boolean = !isEmpty() + +public inline fun List.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T { + return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +} + +public fun List.first(): T { + if (isEmpty()) + throw NoSuchElementException("List is empty.") + return this[0] +} + +public fun Iterable.single(): T { + when (this) { + is List -> return this.single() + else -> { + val iterator = iterator() + if (!iterator.hasNext()) + throw NoSuchElementException("Collection is empty.") + val single = iterator.next() + if (iterator.hasNext()) + throw IllegalArgumentException("Collection has more than one element.") + return single + } + } +} + +public fun List.single(): T { + return when (size) { + 0 -> throw NoSuchElementException("List is empty.") + 1 -> this[0] + else -> throw IllegalArgumentException("List has more than one element.") + } +} + +public fun Iterable.toList(): List { + if (this is Collection) { + return when (size) { + 0 -> emptyList() + 1 -> listOf(if (this is List) get(0) else iterator().next()) + else -> this.toMutableList() + } + } + return this.toMutableList().optimizeReadOnlyList() +} + +public fun Iterable.toMutableList(): MutableList { + if (this is Collection) + return this.toMutableList() + return toCollection(ArrayList()) +} + +public fun Collection.toMutableList(): MutableList { + return ArrayList(this) +} + +public fun > Iterable.toCollection(destination: C): C { + for (item in this) { + destination.add(item) + } + return destination +} + +internal fun List.optimizeReadOnlyList() = when (size) { + 0 -> emptyList() + 1 -> listOf(this[0]) + else -> this +} + +public inline fun Iterable.all(predicate: (T) -> Boolean): Boolean { + if (this is Collection && isEmpty()) return true + for (element in this) if (!predicate(element)) return false + return true +} + +public fun Iterable.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) { + buffer.appendElement(element, transform) + } else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} + +private fun Appendable.appendElement(element: T, transform: ((T) -> CharSequence)?) { + when { + transform != null -> append(transform(element)) + element is CharSequence? -> append(element) + element is Char -> append(element) + else -> append(element.toString()) + } +} + +public fun Iterable.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String { + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +} \ No newline at end of file diff --git a/compiler/testData/ir/interpreter/helpers/Maps.kt b/compiler/testData/ir/interpreter/helpers/Maps.kt new file mode 100644 index 00000000000..6e74ca8a658 --- /dev/null +++ b/compiler/testData/ir/interpreter/helpers/Maps.kt @@ -0,0 +1,125 @@ +@file:kotlin.jvm.JvmMultifileClass +@file:kotlin.jvm.JvmName("MapsKt") + +package kotlin.collections + +import kotlin.sequences.* + +private object EmptyMap : Map, Serializable { + private const val serialVersionUID: Long = 8246714829545688274 + + override fun equals(other: Any?): Boolean = other is Map<*, *> && other.isEmpty() + override fun hashCode(): Int = 0 + override fun toString(): String = "{}" + + override val size: Int get() = 0 + override fun isEmpty(): Boolean = true + + override fun containsKey(key: Any?): Boolean = false + override fun containsValue(value: Nothing): Boolean = false + override fun get(key: Any?): Nothing? = null + override val entries: Set> get() = EmptySet + override val keys: Set get() = EmptySet + override val values: Collection get() = EmptyList + + private fun readResolve(): Any = EmptyMap +} + +public fun emptyMap(): Map = @Suppress("UNCHECKED_CAST") (EmptyMap as Map) + +public fun mapOf(vararg pairs: Pair): Map = + if (pairs.size > 0) pairs.toMap(LinkedHashMap(mapCapacity(pairs.size))) else emptyMap() + +public inline fun mapOf(): Map = emptyMap() + +public inline fun mutableMapOf(): MutableMap = LinkedHashMap() + +public fun mutableMapOf(vararg pairs: Pair): MutableMap = + LinkedHashMap(mapCapacity(pairs.size)).apply { putAll(pairs) } + +public inline fun hashMapOf(): HashMap = kotlin.UnsupportedOperationException("This is intrinsic") + +public fun hashMapOf(vararg pairs: Pair): HashMap = kotlin.UnsupportedOperationException("This is intrinsic") + +public inline fun linkedMapOf(): LinkedHashMap = LinkedHashMap() + +internal fun mapCapacity(expectedSize: Int): Int = when { + // We are not coercing the value to a valid one and not throwing an exception. It is up to the caller to + // properly handle negative values. + expectedSize < 0 -> expectedSize + expectedSize < 3 -> expectedSize + 1 + expectedSize < 1 shl (Int.SIZE_BITS - 2) -> ((expectedSize / 0.75F) + 1.0F).toInt() + // any large value + else -> Int.MAX_VALUE +} + +public inline operator fun Map.contains(key: K): Boolean = containsKey(key) + +public inline operator fun Map.get(key: K): V? = (this as Map).get(key) + +public inline operator fun MutableMap.set(key: K, value: V): Unit { + put(key, value) +} + +public inline fun Map.containsKey(key: K): Boolean = (this as Map).containsKey(key) + +public inline fun Map.containsValue(value: V): Boolean = this.containsValue(value) + +public inline fun MutableMap.remove(key: K): V? = (this as MutableMap).remove(key) + +public inline operator fun Map.Entry.component1(): K = key + +public inline operator fun Map.Entry.component2(): V = value + +public inline fun Map.Entry.toPair(): Pair = Pair(key, value) + +public inline operator fun Map.iterator(): Iterator> = entries.iterator() + +public fun MutableMap.putAll(pairs: Array>): Unit { + for ((key, value) in pairs) { + put(key, value) + } +} + +public fun MutableMap.putAll(pairs: Iterable>): Unit { + for ((key, value) in pairs) { + put(key, value) + } +} + +public fun MutableMap.putAll(pairs: Sequence>): Unit { + for ((key, value) in pairs) { + put(key, value) + } +} + +public fun Iterable>.toMap(): Map { + if (this is Collection) { + return when (size) { + 0 -> emptyMap() + 1 -> mapOf(if (this is List) this[0] else iterator().next()) + else -> toMap(LinkedHashMap(mapCapacity(size))) + } + } + return toMap(LinkedHashMap()).optimizeReadOnlyMap() +} + +public fun > Iterable>.toMap(destination: M): M = destination.apply { putAll(this@toMap) } + +public fun Array>.toMap(): Map = when (size) { + 0 -> emptyMap() + 1 -> mapOf(this[0]) + else -> toMap(LinkedHashMap(mapCapacity(size))) +} + +public fun > Array>.toMap(destination: M): M = destination.apply { putAll(this@toMap) } + +public fun Sequence>.toMap(): Map = toMap(LinkedHashMap()).optimizeReadOnlyMap() + +public fun > Sequence>.toMap(destination: M): M = destination.apply { putAll(this@toMap) } + +internal fun Map.optimizeReadOnlyMap() = when (size) { + 0 -> emptyMap() + 1 -> this // toSingletonMapOrSelf() + else -> this +} diff --git a/compiler/testData/ir/interpreter/helpers/Ranges.kt b/compiler/testData/ir/interpreter/helpers/Ranges.kt new file mode 100644 index 00000000000..ff7c000995c --- /dev/null +++ b/compiler/testData/ir/interpreter/helpers/Ranges.kt @@ -0,0 +1,68 @@ +@file:kotlin.jvm.JvmMultifileClass +@file:kotlin.jvm.JvmName("RangesKt") + +package kotlin.ranges + +public infix fun Int.until(to: Byte): IntRange { + return this .. (to.toInt() - 1).toInt() +} +public infix fun Long.until(to: Byte): LongRange { + return this .. (to.toLong() - 1).toLong() +} +public infix fun Byte.until(to: Byte): IntRange { + return this.toInt() .. (to.toInt() - 1).toInt() +} +public infix fun Short.until(to: Byte): IntRange { + return this.toInt() .. (to.toInt() - 1).toInt() +} + +public infix fun Char.until(to: Char): CharRange { + if (to <= '\u0000') return CharRange.EMPTY + return this .. (to - 1).toChar() +} + +public infix fun Int.until(to: Int): IntRange { + if (to <= Int.MIN_VALUE) return IntRange.EMPTY + return this .. (to - 1).toInt() +} +public infix fun Long.until(to: Int): LongRange { + return this .. (to.toLong() - 1).toLong() +} +public infix fun Byte.until(to: Int): IntRange { + if (to <= Int.MIN_VALUE) return IntRange.EMPTY + return this.toInt() .. (to - 1).toInt() +} +public infix fun Short.until(to: Int): IntRange { + if (to <= Int.MIN_VALUE) return IntRange.EMPTY + return this.toInt() .. (to - 1).toInt() +} + +public infix fun Int.until(to: Long): LongRange { + if (to <= Long.MIN_VALUE) return LongRange.EMPTY + return this.toLong() .. (to - 1).toLong() +} +public infix fun Long.until(to: Long): LongRange { + if (to <= Long.MIN_VALUE) return LongRange.EMPTY + return this .. (to - 1).toLong() +} +public infix fun Byte.until(to: Long): LongRange { + if (to <= Long.MIN_VALUE) return LongRange.EMPTY + return this.toLong() .. (to - 1).toLong() +} +public infix fun Short.until(to: Long): LongRange { + if (to <= Long.MIN_VALUE) return LongRange.EMPTY + return this.toLong() .. (to - 1).toLong() +} + +public infix fun Int.until(to: Short): IntRange { + return this .. (to.toInt() - 1).toInt() +} +public infix fun Long.until(to: Short): LongRange { + return this .. (to.toLong() - 1).toLong() +} +public infix fun Byte.until(to: Short): IntRange { + return this.toInt() .. (to.toInt() - 1).toInt() +} +public infix fun Short.until(to: Short): IntRange { + return this.toInt() .. (to.toInt() - 1).toInt() +} \ No newline at end of file diff --git a/compiler/testData/ir/interpreter/helpers/Sequences.kt b/compiler/testData/ir/interpreter/helpers/Sequences.kt new file mode 100644 index 00000000000..dd06694ad72 --- /dev/null +++ b/compiler/testData/ir/interpreter/helpers/Sequences.kt @@ -0,0 +1,122 @@ +@file:kotlin.jvm.JvmMultifileClass +@file:kotlin.jvm.JvmName("SequencesKt") + +package kotlin.sequences + +public inline fun Sequence(crossinline iterator: () -> Iterator): Sequence = object : Sequence { + override fun iterator(): Iterator = iterator() +} + +public fun Iterator.asSequence(): Sequence = Sequence { this }//.constrainOnce() + +public fun sequenceOf(vararg elements: T): Sequence = if (elements.isEmpty()) emptySequence() else elements.asSequence() + +public fun emptySequence(): Sequence = EmptySequence + +private object EmptySequence : Sequence, DropTakeSequence { + override fun iterator(): Iterator = EmptyIterator + override fun drop(n: Int) = EmptySequence + override fun take(n: Int) = EmptySequence +} + +public inline fun Sequence?.orEmpty(): Sequence = this ?: emptySequence() + +private class GeneratorSequence(private val getInitialValue: () -> T?, private val getNextValue: (T) -> T?) : Sequence { + override fun iterator(): Iterator = object : Iterator { + var nextItem: T? = null + var nextState: Int = -2 // -2 for initial unknown, -1 for next unknown, 0 for done, 1 for continue + + private fun calcNext() { + nextItem = if (nextState == -2) getInitialValue() else getNextValue(nextItem!!) + nextState = if (nextItem == null) 0 else 1 + } + + override fun next(): T { + if (nextState < 0) + calcNext() + + if (nextState == 0) + throw NoSuchElementException() + val result = nextItem as T + // Do not clean nextItem (to avoid keeping reference on yielded instance) -- need to keep state for getNextValue + nextState = -1 + return result + } + + override fun hasNext(): Boolean { + if (nextState < 0) + calcNext() + return nextState == 1 + } + } +} + +public fun generateSequence(nextFunction: () -> T?): Sequence { + return GeneratorSequence(nextFunction, { nextFunction() })//.constrainOnce() +} + +public fun generateSequence(seed: T?, nextFunction: (T) -> T?): Sequence = + if (seed == null) + EmptySequence + else + GeneratorSequence({ seed }, nextFunction) + +public fun generateSequence(seedFunction: () -> T?, nextFunction: (T) -> T?): Sequence = + GeneratorSequence(seedFunction, nextFunction) + +public operator fun Sequence.contains(element: T): Boolean { + return indexOf(element) >= 0 +} + +public fun Sequence.indexOf(element: T): Int { + var index = 0 + for (item in this) { + checkIndexOverflow(index) + if (element == item) + return index + index++ + } + return -1 +} + +public fun Sequence.toList(): List { + return this.toMutableList().optimizeReadOnlyList() +} + +public fun Sequence.toMutableList(): MutableList { + return toCollection(ArrayList()) +} + +public fun > Sequence.toCollection(destination: C): C { + for (item in this) { + destination.add(item) + } + return destination +} + +public fun Sequence.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String { + return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() +} + +public fun Sequence.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): A { + buffer.append(prefix) + var count = 0 + for (element in this) { + if (++count > 1) buffer.append(separator) + if (limit < 0 || count <= limit) { + buffer.appendElement(element, transform) + } else break + } + if (limit >= 0 && count > limit) buffer.append(truncated) + buffer.append(postfix) + return buffer +} + +private fun Appendable.appendElement(element: T, transform: ((T) -> CharSequence)?) { + when { + transform != null -> append(transform(element)) + element is CharSequence? -> append(element) + element is Char -> append(element) + else -> append(element.toString()) + } +} \ No newline at end of file diff --git a/compiler/testData/ir/interpreter/helpers/Sets.kt b/compiler/testData/ir/interpreter/helpers/Sets.kt new file mode 100644 index 00000000000..cf98fc04d97 --- /dev/null +++ b/compiler/testData/ir/interpreter/helpers/Sets.kt @@ -0,0 +1,41 @@ +@file:kotlin.jvm.JvmMultifileClass +@file:kotlin.jvm.JvmName("SetsKt") + +package kotlin.collections + +internal object EmptySet : Set, Serializable { + private const val serialVersionUID: Long = 3406603774387020532 + + override fun equals(other: Any?): Boolean = other is Set<*> && other.isEmpty() + override fun hashCode(): Int = 0 + override fun toString(): String = "[]" + + override val size: Int get() = 0 + override fun isEmpty(): Boolean = true + override fun contains(element: Nothing): Boolean = false + override fun containsAll(elements: Collection): Boolean = elements.isEmpty() + + override fun iterator(): Iterator = EmptyIterator + + private fun readResolve(): Any = EmptySet +} + +public fun emptySet(): Set = EmptySet + +public fun setOf(vararg elements: T): Set = if (elements.size > 0) elements.toSet() else emptySet() + +public inline fun setOf(): Set = emptySet() + +public inline fun mutableSetOf(): MutableSet = LinkedHashSet() + +public fun mutableSetOf(vararg elements: T): MutableSet = elements.toCollection(LinkedHashSet(mapCapacity(elements.size))) + +public inline fun hashSetOf(): HashSet = kotlin.UnsupportedOperationException("This is intrinsic") + +public fun hashSetOf(vararg elements: T): HashSet = kotlin.UnsupportedOperationException("This is intrinsic") + +internal fun Set.optimizeReadOnlySet() = when (size) { + 0 -> emptySet() + 1 -> setOf(iterator().next()) + else -> this +} diff --git a/compiler/testData/ir/interpreter/helpers/Standard.kt b/compiler/testData/ir/interpreter/helpers/Standard.kt new file mode 100644 index 00000000000..2912dac6677 --- /dev/null +++ b/compiler/testData/ir/interpreter/helpers/Standard.kt @@ -0,0 +1,43 @@ +package kotlin + +import kotlin.* + +public inline fun run(block: () -> R): R { + return block() +} + +public inline fun T.run(block: T.() -> R): R { + return block() +} + +public inline fun with(receiver: T, block: T.() -> R): R { + return receiver.block() +} + +public inline fun T.apply(block: T.() -> Unit): T { + block() + return this +} + +public inline fun T.also(block: (T) -> Unit): T { + block(this) + return this +} + +public inline fun T.let(block: (T) -> R): R { + return block(this) +} + +public inline fun T.takeIf(predicate: (T) -> Boolean): T? { + return if (predicate(this)) this else null +} + +public inline fun T.takeUnless(predicate: (T) -> Boolean): T? { + return if (!predicate(this)) this else null +} + +public inline fun repeat(times: Int, action: (Int) -> Unit) { + for (index in 0 until times) { + action(index) + } +} diff --git a/compiler/testData/ir/interpreter/helpers/Strings.kt b/compiler/testData/ir/interpreter/helpers/Strings.kt new file mode 100644 index 00000000000..33e1087036f --- /dev/null +++ b/compiler/testData/ir/interpreter/helpers/Strings.kt @@ -0,0 +1,84 @@ +@file:kotlin.jvm.JvmMultifileClass +@file:kotlin.jvm.JvmName("StringsKt") + +package kotlin.text + +public inline fun CharSequence.trim(predicate: (Char) -> Boolean): CharSequence { + var startIndex = 0 + var endIndex = length - 1 + var startFound = false + + while (startIndex <= endIndex) { + val index = if (!startFound) startIndex else endIndex + val match = predicate(this[index]) + + if (!startFound) { + if (!match) + startFound = true + else + startIndex += 1 + } else { + if (!match) + break + else + endIndex -= 1 + } + } + + return subSequence(startIndex, endIndex + 1) +} + +public fun CharSequence.trim(): CharSequence = trim(Char::isWhitespace) + +public inline fun String.trim(): String = (this as CharSequence).trim().toString() + +public inline fun CharSequence.isEmpty(): Boolean = length == 0 + +public inline fun CharSequence.isNotEmpty(): Boolean = length > 0 + +public operator fun CharSequence.iterator(): CharIterator = object : CharIterator() { + private var index = 0 + + public override fun nextChar(): Char = get(index++) + + public override fun hasNext(): Boolean = index < length +} + +public fun CharSequence.first(): Char { + if (isEmpty()) + throw NoSuchElementException("Char sequence is empty.") + return this[0] +} + +public val CharSequence.indices: IntRange + get() = 0..length - 1 + +public val CharSequence.lastIndex: Int + get() = this.length - 1 + +public inline fun CharSequence.substring(startIndex: Int, endIndex: Int = length): String = subSequence(startIndex, endIndex).toString() + +public fun CharSequence.substring(range: IntRange): String = subSequence(range.start, range.endInclusive + 1).toString() + +public inline fun CharSequence.elementAtOrElse(index: Int, defaultValue: (Int) -> Char): Char { + return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +} + +public fun CharSequence.toList(): List { + return when (length) { + 0 -> emptyList() + 1 -> listOf(this[0]) + else -> this.toMutableList() + } +} + +public fun CharSequence.toMutableList(): MutableList { + return toCollection(ArrayList(length)) +} + +public fun > CharSequence.toCollection(destination: C): C { + for (item in this) { + destination.add(item) + } + return destination +} \ No newline at end of file diff --git a/compiler/testData/ir/interpreter/helpers/UArrays.kt b/compiler/testData/ir/interpreter/helpers/UArrays.kt new file mode 100644 index 00000000000..1dfcccabf99 --- /dev/null +++ b/compiler/testData/ir/interpreter/helpers/UArrays.kt @@ -0,0 +1,39 @@ +@file:kotlin.jvm.JvmMultifileClass +@file:kotlin.jvm.JvmName("UArraysKt") + +package kotlin.collections + +public inline fun UIntArray.elementAtOrElse(index: Int, defaultValue: (Int) -> UInt): UInt { + return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) +} + +public inline val UIntArray.indices: IntRange + get() = storage.indices +public inline val ULongArray.indices: IntRange + get() = storage.indices +public inline val UByteArray.indices: IntRange + get() = storage.indices +public inline val UShortArray.indices: IntRange + get() = storage.indices + +public inline val UIntArray.lastIndex: Int + get() = storage.lastIndex +public inline val ULongArray.lastIndex: Int + get() = storage.lastIndex +public inline val UByteArray.lastIndex: Int + get() = storage.lastIndex +public inline val UShortArray.lastIndex: Int + get() = storage.lastIndex + +public inline fun UIntArray.first(): UInt { + return storage.first().toUInt() +} +public inline fun ULongArray.first(): ULong { + return storage.first().toULong() +} +public inline fun UByteArray.first(): UByte { + return storage.first().toUByte() +} +public inline fun UShortArray.first(): UShort { + return storage.first().toUShort() +} \ No newline at end of file diff --git a/compiler/testData/ir/interpreter/helpers/utils/bitwiseOperations.kt b/compiler/testData/ir/interpreter/helpers/utils/bitwiseOperations.kt new file mode 100644 index 00000000000..d70bfe319df --- /dev/null +++ b/compiler/testData/ir/interpreter/helpers/utils/bitwiseOperations.kt @@ -0,0 +1,13 @@ +package kotlin + +public inline infix fun Byte.and(other: Byte): Byte = (this.toInt() and other.toInt()).toByte() +public inline infix fun Byte.or(other: Byte): Byte = (this.toInt() or other.toInt()).toByte() +public inline infix fun Byte.xor(other: Byte): Byte = (this.toInt() xor other.toInt()).toByte() +public inline fun Byte.inv(): Byte = (this.toInt().inv()).toByte() + +public inline infix fun Short.and(other: Short): Short = (this.toInt() and other.toInt()).toShort() +public inline infix fun Short.or(other: Short): Short = (this.toInt() or other.toInt()).toShort() +public inline infix fun Short.xor(other: Short): Short = (this.toInt() xor other.toInt()).toShort() +public inline fun Short.inv(): Short = (this.toInt().inv()).toShort() + + diff --git a/compiler/testData/ir/interpreter/helpers/utils/kotlinUtils.kt b/compiler/testData/ir/interpreter/helpers/utils/kotlinUtils.kt new file mode 100644 index 00000000000..2de9c66bfc0 --- /dev/null +++ b/compiler/testData/ir/interpreter/helpers/utils/kotlinUtils.kt @@ -0,0 +1,29 @@ +package kotlin + +public inline val Char.code: Int get() = this.toInt() + +expect fun Double.isNaN(): Boolean +expect fun Float.isNaN(): Boolean + +public data class Pair(public val first: A, public val second: B) : Serializable { + public override fun toString(): String = "($first, $second)" +} + +public infix fun A.to(that: B): Pair = Pair(this, that) + +public fun Pair.toList(): List = listOf(first, second) + +public data class Triple( + public val first: A, public val second: B, public val third: C +) : Serializable { + public override fun toString(): String = "($first, $second, $third)" +} + +public fun Triple.toList(): List = listOf(first, second, third) + +public fun checkIndexOverflow(index: Int): Int { + if (index < 0) { + throw kotlin.ArithmeticException("Index overflow has happened.") + } + return index +} \ No newline at end of file diff --git a/compiler/testData/ir/interpreter/helpers/utils/sourceLocation.kt b/compiler/testData/ir/interpreter/helpers/utils/sourceLocation.kt new file mode 100644 index 00000000000..0da6cbe6516 --- /dev/null +++ b/compiler/testData/ir/interpreter/helpers/utils/sourceLocation.kt @@ -0,0 +1,4 @@ +package kotlin.experimental + +//Will return file and line number there this function was called +inline fun sourceLocation(): String = throw kotlin.UnsupportedOperationException("Implemented as intrinsic") \ No newline at end of file diff --git a/compiler/testData/ir/interpreter/inKeyword.kt b/compiler/testData/ir/interpreter/inKeyword.kt new file mode 100644 index 00000000000..3e26aa66016 --- /dev/null +++ b/compiler/testData/ir/interpreter/inKeyword.kt @@ -0,0 +1,20 @@ +import kotlin.collections.* + +@CompileTimeCalculation +fun numberIsInArray(array: IntArray, number: Int): Boolean { + return number in array +} + +@CompileTimeCalculation +fun valueIsInArray(array: Array, value: Any?): Boolean { + return value in array +} + +const val a1 = numberIsInArray(intArrayOf(1, 2, 3), 1) +const val a2 = numberIsInArray(intArrayOf(1, 2, 3), -1) + +const val b1 = valueIsInArray(arrayOf(1, 2, 3), 1) +const val b2 = valueIsInArray(arrayOf(1, 2, 3), -1) +const val b3 = valueIsInArray(arrayOf(1, 2.0f, "3"), "3") +const val b4 = valueIsInArray(arrayOf(1, 2.0f, "3"), null) +const val b5 = valueIsInArray(arrayOf(1, 2.0f, "3"), 1.0f) diff --git a/compiler/testData/ir/interpreter/inlineReturn.kt b/compiler/testData/ir/interpreter/inlineReturn.kt new file mode 100644 index 00000000000..6f08e3a790c --- /dev/null +++ b/compiler/testData/ir/interpreter/inlineReturn.kt @@ -0,0 +1,39 @@ +@CompileTimeCalculation +inline fun x(i: Int, w: () -> Int): Int { + return i + w() +} + +@CompileTimeCalculation +fun withNonLocalReturn(): String { + x(10) { return "Non local" } + return "Local" +} + +@CompileTimeCalculation +fun withLocalReturn(): String { + x(10) { return@x 1 } + return "Local" +} + +// TODO can replace IrCall on IrConst inside body +fun foo() { + val a = x(10) l@ { //this call can be replaced on 20 + x(9) { + return@l 10 + } + } +} + +// TODO can replace IrCall on IrConst inside body +fun bar(p: Int) { + x(10) { + val i = p + x(11) { //this call can be replaced on 21 + val j = 0 + x(j) { 10 } + } + } +} + +const val a = withNonLocalReturn() +const val b = withLocalReturn() diff --git a/compiler/testData/ir/interpreter/innerClass.kt b/compiler/testData/ir/interpreter/innerClass.kt new file mode 100644 index 00000000000..778330a7434 --- /dev/null +++ b/compiler/testData/ir/interpreter/innerClass.kt @@ -0,0 +1,27 @@ +@CompileTimeCalculation +class Outer { + private val bar: String = "bar" + val num = 1 + + fun foo() = "outer foo" + + inner class Middle { + val num = 2 + + fun foo() = "middle foo" + + inner class Inner { + val num = 3 + + fun foo() = "inner foo with outer bar = \"$bar\"" + + fun getAllNums() = "From inner: " + this.num + "; from middle: " + this@Middle.num + "; from outer: " + this@Outer.num + } + } +} + +const val a1 = Outer().foo() +const val a2 = Outer().Middle().foo() +const val a3 = Outer().Middle().Inner().foo() + +const val b = Outer().Middle().Inner().getAllNums() diff --git a/compiler/testData/ir/interpreter/instanceOf.kt b/compiler/testData/ir/interpreter/instanceOf.kt new file mode 100644 index 00000000000..bf99a885992 --- /dev/null +++ b/compiler/testData/ir/interpreter/instanceOf.kt @@ -0,0 +1,22 @@ +interface Base + +@CompileTimeCalculation +open class A : Base + +@CompileTimeCalculation +class B : A() + +const val a1 = 1 is Int +const val a2 = 2 !is Int + +const val b1 = A() is Base +const val b2 = A() !is Base +const val b3 = A() is A +const val b4 = A() !is A + +const val c1 = B() is Base +const val c2 = B() !is Base +const val c3 = B() is A +const val c4 = B() !is A +const val c5 = B() is B +const val c6 = B() !is B diff --git a/compiler/testData/ir/interpreter/instanceOfWithTypeParameters.kt b/compiler/testData/ir/interpreter/instanceOfWithTypeParameters.kt new file mode 100644 index 00000000000..825a5ac5521 --- /dev/null +++ b/compiler/testData/ir/interpreter/instanceOfWithTypeParameters.kt @@ -0,0 +1,138 @@ +import kotlin.collections.* +import kotlin.text.isEmpty + +const val result1 = foo() +const val result2 = bar() + +const val result3 = checkForArrayList(1) +const val result4 = checkForArrayList(listOf()) +const val result5 = checkForArrayList(arrayListOf()) + +const val result6 = checkForArray(1) +const val result7 = checkForArray(intArrayOf()) +const val result8 = checkForArray(arrayOf()) + +@CompileTimeCalculation +fun foo(): String { + val a = arrayListOf() + if (a !is Collection) return "fail a 1" + if (a !is Collection) return "fail a 2" + if (a !is Collection<*>) return "fail a 3" + + val b: ArrayList? = null + if (b is Collection) return "fail b 1" + if (b is Collection) return "fail b 2" + if (b is Collection<*>) return "fail b 3" + if (b is Collection) return "fail b 4" + + if (b !is Collection?) return "fail b 5" + if (b !is Collection?) return "fail b 6" + if (b !is Collection<*>?) return "fail b 7" + if (b !is Collection?) return "fail b 8" + + if (b is Collection) return "fail b 9" + if (b is Collection) return "fail b 10" + if (b is Collection) return "fail b 11" + + if (b !is Collection?) return "fail b 12" + if (b !is Collection?) return "fail b 13" + if (b !is Collection?) return "fail b 14" + + val c: ArrayList<*> = arrayListOf(1, 2) + if (c !is Collection<*>) return "fail c 1" + if (c !is Collection<*>?) return "fail c 2" + if (c !is Collection?) return "fail c 3" + + val d: ArrayList = arrayListOf(1, 2) + if (d !is Collection<*>) return "fail d 1" + if (d !is Collection) return "fail d 2" + if (d !is Collection<*>?) return "fail d 3" + if (d !is Collection?) return "fail d 4" + + val e: ArrayList = arrayListOf(1, 2) + if (e !is Collection<*>) return "fail e 1" + if (e !is Collection<*>?) return "fail e 2" + if (e !is Collection?) return "fail e 3" + + if (null is Any) return "fail f 1" + if (null !is Any?) return "fail f 2" + if (null is String) return "fail f 3" + if (null !is String?) return "fail f 4" + if (null is Nothing) return "fail f 5" + if (null !is Nothing?) return "fail f 6" + + val g: Int? = 1 + if (g !is Int) return "fail g 1" + if (g !is Int?) return "fail g 2" + + val h: Int = 1 + if (h !is Int) return "fail h 1" + if (h !is Int?) return "fail h 2" + + return "OK" +} + +@CompileTimeCalculation +fun bar(): String { + val a = arrayListOf() + if (a !is Collection) return "fail a 1" + if (a !is Collection) return "fail a 2" + if (a !is Collection<*>) return "fail a 3" + + val b: Collection? = null + if (b is ArrayList) return "fail b 1" + if (b is ArrayList<*>) return "fail b 2" + if (b !is ArrayList?) return "fail b 3" + if (b !is ArrayList<*>?) return "fail b 4" + + val c: Collection<*> = arrayListOf(1, 2) + if (c !is ArrayList<*>) return "fail c 1" + if (c !is ArrayList<*>?) return "fail c 2" + + val d: Collection = arrayListOf(1, 2) + if (d !is ArrayList<*>) return "fail d 1" + if (d !is ArrayList) return "fail d 2" + if (d !is ArrayList<*>?) return "fail d 3" + + val e: Collection = arrayListOf(1, 2) + if (e !is Collection<*>) return "fail e 1" + if (e !is Collection<*>?) return "fail e 2" + if (e !is Collection?) return "fail e 3" + + val f: Any? = 1 + if (f !is Int) return "fail f 1" + if (f !is Int?) return "fail f 2" + + val g: Any = 1 + if (g !is Int) return "fail g 1" + if (g !is Int?) return "fail g 2" + + return "OK" +} + +@CompileTimeCalculation +fun checkForArrayList(value: T): String { + val sb = StringBuilder() + if (value !is Any) sb.append("fail 1; ") + + if (value !is Collection<*>) sb.append("fail 2; ") + if (value !is Collection) sb.append("fail 3; ") + if (value !is Collection?) sb.append("fail 4; ") + + if (value !is ArrayList<*>) sb.append("fail 5; ") + if (value !is ArrayList<*>?) sb.append("fail 6; ") + + return if (sb.isEmpty()) "OK" else sb.toString() +} + +@CompileTimeCalculation +fun checkForArray(value: T): String { + val sb = StringBuilder() + if (value !is Array<*>) sb.append("fail 1; ") + if (value !is Array<*>?) sb.append("fail 2; ") + + if (value !is ArrayList<*>) sb.append("fail 3; ") + if (value !is ArrayList<*>?) sb.append("fail 4; ") + + return if (sb.isEmpty()) "OK" else sb.toString() +} \ No newline at end of file diff --git a/compiler/testData/ir/interpreter/interface.kt b/compiler/testData/ir/interpreter/interface.kt new file mode 100644 index 00000000000..fd3e562275e --- /dev/null +++ b/compiler/testData/ir/interpreter/interface.kt @@ -0,0 +1,42 @@ +interface A { + @CompileTimeCalculation + fun getStr(): String +} + +interface B : A { + @CompileTimeCalculation + fun getInt(): Int +} + +class C @CompileTimeCalculation constructor(@CompileTimeCalculation val num: Int) : B { + @CompileTimeCalculation + override fun getStr(): String { + return num.toString() + } + + @CompileTimeCalculation + override fun getInt(): Int { + return num + } +} + +@CompileTimeCalculation +fun getClassAsA(num: Int): A { + return C(num) +} + +@CompileTimeCalculation +fun getClassAsB(num: Int): B { + return C(num) +} + +@CompileTimeCalculation +fun getClassAsC(num: Int): C { + return C(num) +} + +const val num1 = getClassAsA(1).getStr() +const val num2 = getClassAsB(2).getStr() +const val num3 = getClassAsB(3).getInt() +const val num4 = getClassAsC(4).getStr() +const val num5 = getClassAsC(5).getInt() diff --git a/compiler/testData/ir/interpreter/interfaceDefault.kt b/compiler/testData/ir/interpreter/interfaceDefault.kt new file mode 100644 index 00000000000..3fe676dae6a --- /dev/null +++ b/compiler/testData/ir/interpreter/interfaceDefault.kt @@ -0,0 +1,30 @@ +@CompileTimeCalculation +interface A { + fun getInt(): Int + + fun getStr(): String = "Number is ${getInt()}" +} + +@CompileTimeCalculation +class B(val b: Int) : A { + override fun getInt(): Int = b + + fun getStrFromB() = "B " + super.getStr() +} + +const val str1 = B(5).getStr() +const val str2 = B(5).getStrFromB() + +@CompileTimeCalculation +interface C { + val num: Int + fun getInt() = num +} + +@CompileTimeCalculation +class D(override val num: Int) : C { + fun getStr() = "D num = " + super.getInt() +} + +const val num1 = D(10).getInt() +const val num2 = D(10).getStr() diff --git a/compiler/testData/ir/interpreter/jvm/classReference.kt b/compiler/testData/ir/interpreter/jvm/classReference.kt new file mode 100644 index 00000000000..7c32ae8ccc3 --- /dev/null +++ b/compiler/testData/ir/interpreter/jvm/classReference.kt @@ -0,0 +1,49 @@ +package test + +import kotlin.reflect.KFunction +import kotlin.collections.* + +@CompileTimeCalculation +class A(val a: Int, val b: String) { + val String.propertyWithExtension: Int + get() = this.length * a + + fun Int.funWithExtension(other: Int) = this + other +} + +const val aSimpleName = A::class.simpleName!! +const val aQualifiedName = A::class.qualifiedName!! +//const val aMembers = A::class.members.joinToString() TODO -> `val test.A.a: kotlin.Int, val test.A.b: kotlin.String, val test.A.(kotlin.String.)propertyWithExtension: kotlin.Int, fun test.A.(kotlin.Int.)funWithExtension(kotlin.Int): kotlin.Int, fun test.A.equals(kotlin.Any?): kotlin.Boolean, fun test.A.hashCode(): kotlin.Int, fun test.A.toString(): kotlin.String` +const val aConstructors = A::class.constructors.(kotlin.Int, kotlin.String): test.A`!>joinToString() +const val aVisibility = A::class.visibility.toString() +const val aSupertypes = A::class.supertypes.joinToString() + +@CompileTimeCalculation +interface Base + +@CompileTimeCalculation +class B(val prop: T) : Base { + fun get(): T = prop + + fun getThis(): B = this + + fun withTypeParameter(num: E) = num.toString() +} + +//const val bMembers = B::class.members.joinToString() TODO -> `val test.B.prop: T, fun test.B.get(): T, fun test.B.getThis(): test.B, fun test.B.withTypeParameter(E): kotlin.String, fun test.B.equals(kotlin.Any?): kotlin.Boolean, fun test.B.hashCode(): kotlin.Int, fun test.B.toString(): kotlin.String` +const val bTypeParameters = B::class.typeParameters.joinToString() +const val bSupertypes = B::class.supertypes., kotlin.Any`!>joinToString() +//const val bReturnType1 = B::class.members.toList()[1].returnType.toString() TODO -> `T` +//const val bReturnType2 = B::class.members.toList()[3].returnType.toString() TODO -> `kotlin.String` + +const val arguments1 = (B(1)::getThis as KFunction<*>).returnType.arguments.joinToString() +const val arguments2 = (arrayOf(1)::iterator as KFunction<*>).returnType.arguments.joinToString() + +@CompileTimeCalculation +class C { + val String.getLength + get() = this.length +} + +//const val cMember = C::class.members.toList()[0].toString() TODO -> `val test.C.(kotlin.String.)getLength: kotlin.Int` +//const val cMemberReturnType = C::class.members.toList()[0].returnType.classifier.toString() TODO -> `class kotlin.Int` \ No newline at end of file diff --git a/compiler/testData/ir/interpreter/jvm/javaStatic.kt b/compiler/testData/ir/interpreter/jvm/javaStatic.kt new file mode 100644 index 00000000000..b8a577efa61 --- /dev/null +++ b/compiler/testData/ir/interpreter/jvm/javaStatic.kt @@ -0,0 +1,26 @@ +const val byteMax = { java.lang.Byte.MAX_VALUE }() +const val byteMin = { java.lang.Byte.MIN_VALUE }() +const val byteSize = { java.lang.Byte.SIZE }() +const val byteBytes = { java.lang.Byte.BYTES }() + +const val intMax = { java.lang.Integer.MAX_VALUE }() +const val intMin = { java.lang.Integer.MIN_VALUE }() +const val intSize = { java.lang.Integer.SIZE }() +const val intBytes = { java.lang.Integer.BYTES }() + +const val floatMax = { java.lang.Float.MAX_VALUE }() +const val floatMin = { java.lang.Float.MIN_VALUE }() +const val floatSize = { java.lang.Float.SIZE }() +const val floatBytes = { java.lang.Float.BYTES }() +const val floatMaxExponent = { java.lang.Float.MAX_EXPONENT }() +const val floatMinExponent = { java.lang.Float.MIN_EXPONENT }() +const val floatNegInfinity = { java.lang.Float.NEGATIVE_INFINITY }() +const val floatPosInfinity = { java.lang.Float.POSITIVE_INFINITY }() + +const val booleanFalse = { java.lang.Boolean.FALSE }().toString() +const val booleanTrue = { java.lang.Boolean.TRUE }().toString() + +const val charMax = { java.lang.Character.MAX_VALUE }().toInt() +const val charMin = { java.lang.Character.MIN_VALUE }().toInt() +const val charSize = { java.lang.Character.SIZE }() +const val charBytes = { java.lang.Character.BYTES }() diff --git a/compiler/testData/ir/interpreter/jvm/kProperty2.kt b/compiler/testData/ir/interpreter/jvm/kProperty2.kt new file mode 100644 index 00000000000..98b24e1fa6f --- /dev/null +++ b/compiler/testData/ir/interpreter/jvm/kProperty2.kt @@ -0,0 +1,11 @@ +package test + +import kotlin.collections.* + +@CompileTimeCalculation +class A(val a: Int) { + val String.size: Int + get() = this.length * a +} + +//const val kproperty2Get = A::class.members.toList()[1].call(A(2), "123").toString() TODO -> `6` diff --git a/compiler/testData/ir/interpreter/jvm/parameterReference.kt b/compiler/testData/ir/interpreter/jvm/parameterReference.kt new file mode 100644 index 00000000000..c46c69238a4 --- /dev/null +++ b/compiler/testData/ir/interpreter/jvm/parameterReference.kt @@ -0,0 +1,29 @@ +package test + +import kotlin.reflect.KFunction +import kotlin.collections.* + +@CompileTimeCalculation +fun withParameters(a: Int, b: Double) = 0 +@CompileTimeCalculation +fun String.withExtension(a: Int) = 0 + +@CompileTimeCalculation +class A { + fun String.get(a: Int) = this +} + +const val parameters1 = (::withParameters as KFunction<*>).parameters.joinToString() +const val parameters2 = (String::withExtension as KFunction<*>).parameters.joinToString() +//const val parameters3 = A::class.members.toList()[0].parameters.joinToString() TODO -> `instance parameter of fun test.A.(kotlin.String.)get(kotlin.Int): kotlin.String, extension receiver parameter of fun test.A.(kotlin.String.)get(kotlin.Int): kotlin.String, parameter #2 a of fun test.A.(kotlin.String.)get(kotlin.Int): kotlin.String` + +// properties +@CompileTimeCalculation +class B(val b: Int) { + val String.size: Int + get() = this.length +} + +const val property0Parameters = B(1)::b.parameters.toString() +const val property1Parameters = B::b.parameters.toString() +//const val property2Parameters = B::class.members.toList()[1].parameters.toString() TODO -> `[instance parameter of val test.B.(kotlin.String.)size: kotlin.Int, extension receiver parameter of val test.B.(kotlin.String.)size: kotlin.Int]` diff --git a/compiler/testData/ir/interpreter/lambda.kt b/compiler/testData/ir/interpreter/lambda.kt new file mode 100644 index 00000000000..e7299dc5c95 --- /dev/null +++ b/compiler/testData/ir/interpreter/lambda.kt @@ -0,0 +1,23 @@ +@CompileTimeCalculation +fun withLambda(arg: Int, function: (Int) -> Int): Int { + return function(arg) +} + +const val a1 = withLambda(10) { it * 2 } +const val a2 = withLambda(20, { num -> num * 2 }) +const val a3 = withLambda(30, @CompileTimeCalculation fun(number: Int) = number * 2) + +@CompileTimeCalculation +fun withLambda2(arg1: T, arg2: E, function: (T, E) -> R): R { + return function.invoke(arg1, arg2) +} + +const val b1 = withLambda2(5, 2.75) { arg1, arg2 -> arg1 * arg2 } +const val b2 = withLambda2(5, "unused") { arg1, _ -> arg1 * 5 } + +@CompileTimeCalculation +fun withLambdaAndReceiver(arg1: T, arg2: E, function: T.(E) -> R): R { + return function.invoke(arg1, arg2) // arg1.function(arg2) +} + +const val c1 = withLambdaAndReceiver(5, 2.75) { arg -> this.plus(arg) } diff --git a/compiler/testData/ir/interpreter/localFunction.kt b/compiler/testData/ir/interpreter/localFunction.kt new file mode 100644 index 00000000000..e412069ee8b --- /dev/null +++ b/compiler/testData/ir/interpreter/localFunction.kt @@ -0,0 +1,55 @@ +@CompileTimeCalculation +fun returnTheSameValueFun(num: Int) = fun(): Int { return num } + +@CompileTimeCalculation +fun multiplyByTwo(num: Int): () -> Int { + val a = 2 + val b = 5 + return fun(): Int { return num * a } +} + +@CompileTimeCalculation +inline fun multiplyBy(noinline multiply: (Int, Int) -> Int): (Int, Int) -> Int { + return multiply +} + +@CompileTimeCalculation +fun checkStackCorrectness(): Int { + returnTheSameValueFun(10).invoke() + val num = 5 + return num +} + +@CompileTimeCalculation +fun checkLaterInvoke(): String { + val num = 10 + val function = multiplyByTwo(num) + val b = 0 + return "previous = " + num + "; multiplied by two = " + function.invoke() + "; b = " + b +} + +@CompileTimeCalculation +fun localInline(): String { + val a = 10 + val b = 20 + val function = multiplyBy() { a, b -> (a + b) * 2 }.invoke(1, 3) + return "result = " + function + "; (a, b) = ($a, $b)" +} + +@CompileTimeCalculation +fun getNumAfterLocalInvoke(): Int { + var a = 1 + @CompileTimeCalculation + fun local() { + a++ + } + local() + return a +} + +const val a = returnTheSameValueFun(2).invoke() +const val b = multiplyByTwo(1).invoke() +const val c = checkStackCorrectness() +const val d = checkLaterInvoke() +const val e = localInline() +const val f = getNumAfterLocalInvoke() diff --git a/compiler/testData/ir/interpreter/localObject.kt b/compiler/testData/ir/interpreter/localObject.kt new file mode 100644 index 00000000000..b54120a1271 --- /dev/null +++ b/compiler/testData/ir/interpreter/localObject.kt @@ -0,0 +1,19 @@ +@CompileTimeCalculation +interface LocalObject { + fun getNum(): Int +} + +@CompileTimeCalculation +fun getLocalObject(num: Int) = object : LocalObject { + override fun getNum() = num +} + +@CompileTimeCalculation +class A(val a: Int) { + val localObject = object : LocalObject { + override fun getNum() = a + } +} + +const val a = getLocalObject(10).getNum() +const val b = A(2).localObject.getNum() diff --git a/compiler/testData/ir/interpreter/logIntrinsic.kt b/compiler/testData/ir/interpreter/logIntrinsic.kt new file mode 100644 index 00000000000..62242c471be --- /dev/null +++ b/compiler/testData/ir/interpreter/logIntrinsic.kt @@ -0,0 +1,35 @@ +// FILE: logIntrinsic.kt + +import kotlin.experimental.* + +const val thisFileInfo = sourceLocation() +const val otherFileInfo = getSomeInfo() + +@CompileTimeCalculation +fun sumWithLog(a: Int, b: Int): String { + val firstWord = log("Function start") + val before = log("Start summation of $a and $b") + val after = log("Result of summation is ${a + b}") + val finalWord = log("Function end", "") + + return "\n" + firstWord + "\n" + before + "\n" + after + "\n" + finalWord +} + +const val sum = `!>sumWithLog(2, 5) + +// FILE: other.kt +import kotlin.experimental.* + +@CompileTimeCalculation +fun getSomeInfo(): String { + return sourceLocation() +} + +@CompileTimeCalculation +inline fun log(info: String, fileNameAndLine: String = sourceLocation()): String { + return info + " at " + fileNameAndLine +} \ No newline at end of file diff --git a/compiler/testData/ir/interpreter/loop.kt b/compiler/testData/ir/interpreter/loop.kt new file mode 100644 index 00000000000..6f810f16c8c --- /dev/null +++ b/compiler/testData/ir/interpreter/loop.kt @@ -0,0 +1,52 @@ +@CompileTimeCalculation +fun loop(toInc: Int, start: Int, end: Int): Int { + var result = toInc + for (i in start..end) { + result += 1 + } + return result +} + +@CompileTimeCalculation +fun withInnerContinue(): Int { + var cycles = 0 + var i = 1 + var j = 1 + L@while (i <= 5) { + j = 1 + while (j <= 5) { + if (i % 2 == 0) { + i += 1 + continue@L + } + cycles += 1 + j += 1 + } + i += 1 + } + + return cycles +} + +@CompileTimeCalculation +fun withBreak(limit: Int): Int { + var x = 0 + while(true) { + if(x < limit) x++ else break + } + return x +} + +@CompileTimeCalculation +fun earlyExit(end: Int, stop: Int): Int { + for (i in 1..end) { + if (i == stop) return i + } + return end +} + +const val a = loop(0, 1, 10) +const val b1 = withInnerContinue() +const val b2 = withBreak(10) +const val c1 = earlyExit(10, 5) +const val c2 = earlyExit(10, 15) diff --git a/compiler/testData/ir/interpreter/multipleOverridden.kt b/compiler/testData/ir/interpreter/multipleOverridden.kt new file mode 100644 index 00000000000..31f540ad03b --- /dev/null +++ b/compiler/testData/ir/interpreter/multipleOverridden.kt @@ -0,0 +1,23 @@ +@CompileTimeCalculation +open class A { + open fun get(): Int { return 1 } +} + +@CompileTimeCalculation +interface B { + fun get(): Int = 2 +} + +@CompileTimeCalculation +interface C { + fun get(): Int = 3 +} + +@CompileTimeCalculation +class D : A(), B, C { + override fun get(): Int { + return super.get() + super.get() + super.get() + } +} + +const val a = D().get() diff --git a/compiler/testData/ir/interpreter/object.kt b/compiler/testData/ir/interpreter/object.kt new file mode 100644 index 00000000000..c8de07d80d7 --- /dev/null +++ b/compiler/testData/ir/interpreter/object.kt @@ -0,0 +1,23 @@ +class A { + const val a = { 10 }() + + companion object { + const val static = { -10 }() + + fun getStaticNumber(): Int { + return Int.MAX_VALUE + } + } +} + +object ObjectWithConst { + const val a = 100 + const val b = concat("Value in a: ", a) + + fun concat(first: String, second: Any) = "$first$second" +} + +const val num = A().a +const val numStatic = A.static +const val numStaticFromFun = A.getStaticNumber() +const val valFromObject = ObjectWithConst.b diff --git a/compiler/testData/ir/interpreter/objectOverride.kt b/compiler/testData/ir/interpreter/objectOverride.kt new file mode 100644 index 00000000000..196e56e05db --- /dev/null +++ b/compiler/testData/ir/interpreter/objectOverride.kt @@ -0,0 +1,27 @@ +@CompileTimeCalculation +interface Object { + fun get(): String + + @CompileTimeCalculation + fun defaultGet() = "Object" +} + +object A : Object { + @CompileTimeCalculation + override fun get() = "A" +} + +open class B : Object { + @CompileTimeCalculation + override fun get() = "B" +} + +object C : B() { + @CompileTimeCalculation + override fun get() = "Default: " + super.defaultGet() + "; from super B: " + super.get() + "; from current: " + "companion C" +} + +const val a1 = A.defaultGet() +const val a2 = A.get() +const val c1 = C.defaultGet() +const val c2 = C.get() diff --git a/compiler/testData/ir/interpreter/overrideDifferentName.kt b/compiler/testData/ir/interpreter/overrideDifferentName.kt new file mode 100644 index 00000000000..e522f69971c --- /dev/null +++ b/compiler/testData/ir/interpreter/overrideDifferentName.kt @@ -0,0 +1,14 @@ +@CompileTimeCalculation +open class A { + open fun inc(i: Int) = i + 1 +} + +@CompileTimeCalculation +class B(val b: Int) : A() { + override fun inc(j: Int): Int { + return j + b + } +} + +const val a = A().inc(10) +const val b = B(10).inc(11) diff --git a/compiler/testData/ir/interpreter/overrideExtension.kt b/compiler/testData/ir/interpreter/overrideExtension.kt new file mode 100644 index 00000000000..dff0d40b466 --- /dev/null +++ b/compiler/testData/ir/interpreter/overrideExtension.kt @@ -0,0 +1,14 @@ +@CompileTimeCalculation +open class A { + open fun String.getSize() = this.length + + fun returnSizeOf(str: String) = str.getSize() +} + +@CompileTimeCalculation +class B : A() { + override fun String.getSize() = -1 +} + +const val a = A().returnSizeOf("1234") +const val b = B().returnSizeOf("1234") diff --git a/compiler/testData/ir/interpreter/primitives/charMethods.kt b/compiler/testData/ir/interpreter/primitives/charMethods.kt new file mode 100644 index 00000000000..c50da5894ca --- /dev/null +++ b/compiler/testData/ir/interpreter/primitives/charMethods.kt @@ -0,0 +1,43 @@ +fun compareTo(first: Char, second: Char) = first.compareTo(second) + +fun plus(first: Char, second: Int) = first.plus(second) + +fun minus(first: Char, second: Char) = first.minus(second) +fun minus(first: Char, second: Int) = first.minus(second) + +fun inc(first: Char) = first.inc() +fun dec(first: Char) = first.dec() + +fun rangeTo(first: Char, second: Char) = first.rangeTo(second) + +fun toByte(first: Char) = first.toByte() +fun toChar(first: Char) = first.toChar() +fun toShort(first: Char) = first.toShort() +fun toInt(first: Char) = first.toInt() +fun toLong(first: Char) = first.toLong() +fun toFloat(first: Char) = first.toFloat() +fun toDouble(first: Char) = first.toDouble() + +fun toString(first: Char) = first.toString() +fun hashCode(first: Char) = first.hashCode() +fun equals(first: Char, second: Char) = first.equals(second) + +const val a1 = compareTo('a', 'b') +const val a2 = plus('1', 2) +const val a3 = minus('9', '1') +const val a4 = minus('9', 1) +const val a5 = inc('1') +const val a6 = dec('1') +const val a7 = rangeTo('9', '1').last + +const val b1 = toByte('1') +const val b2 = toChar('2') +const val b3 = toShort('3') +const val b4 = toInt('4') +const val b5 = toLong('5') +const val b6 = toFloat('6') +const val b7 = toDouble('7') + +const val c1 = toString('q') +const val c2 = hashCode('q') +const val c3 = equals('1', '2') diff --git a/compiler/testData/ir/interpreter/primitives/intMethods.kt b/compiler/testData/ir/interpreter/primitives/intMethods.kt new file mode 100644 index 00000000000..0d02aaea7e2 --- /dev/null +++ b/compiler/testData/ir/interpreter/primitives/intMethods.kt @@ -0,0 +1,156 @@ +@CompileTimeCalculation fun compareTo(value: Int, other: Byte) = value.compareTo(other) +@CompileTimeCalculation fun compareTo(value: Int, other: Short) = value.compareTo(other) +@CompileTimeCalculation fun compareTo(value: Int, other: Int) = value.compareTo(other) +@CompileTimeCalculation fun compareTo(value: Int, other: Long) = value.compareTo(other) +@CompileTimeCalculation fun compareTo(value: Int, other: Float) = value.compareTo(other) +@CompileTimeCalculation fun compareTo(value: Int, other: Double) = value.compareTo(other) + +@CompileTimeCalculation fun plus(value: Int, other: Byte) = value.plus(other) +@CompileTimeCalculation fun plus(value: Int, other: Short) = value.plus(other) +@CompileTimeCalculation fun plus(value: Int, other: Int) = value.plus(other) +@CompileTimeCalculation fun plus(value: Int, other: Long) = value.plus(other) +@CompileTimeCalculation fun plus(value: Int, other: Float) = value.plus(other) +@CompileTimeCalculation fun plus(value: Int, other: Double) = value.plus(other) + +@CompileTimeCalculation fun minus(value: Int, other: Byte) = value.minus(other) +@CompileTimeCalculation fun minus(value: Int, other: Short) = value.minus(other) +@CompileTimeCalculation fun minus(value: Int, other: Int) = value.minus(other) +@CompileTimeCalculation fun minus(value: Int, other: Long) = value.minus(other) +@CompileTimeCalculation fun minus(value: Int, other: Float) = value.minus(other) +@CompileTimeCalculation fun minus(value: Int, other: Double) = value.minus(other) + +@CompileTimeCalculation fun times(value: Int, other: Byte) = value.times(other) +@CompileTimeCalculation fun times(value: Int, other: Short) = value.times(other) +@CompileTimeCalculation fun times(value: Int, other: Int) = value.times(other) +@CompileTimeCalculation fun times(value: Int, other: Long) = value.times(other) +@CompileTimeCalculation fun times(value: Int, other: Float) = value.times(other) +@CompileTimeCalculation fun times(value: Int, other: Double) = value.times(other) + +@CompileTimeCalculation fun div(value: Int, other: Byte) = value.div(other) +@CompileTimeCalculation fun div(value: Int, other: Short) = value.div(other) +@CompileTimeCalculation fun div(value: Int, other: Int) = value.div(other) +@CompileTimeCalculation fun div(value: Int, other: Long) = value.div(other) +@CompileTimeCalculation fun div(value: Int, other: Float) = value.div(other) +@CompileTimeCalculation fun div(value: Int, other: Double) = value.div(other) + +@CompileTimeCalculation fun rem(value: Int, other: Byte) = value.rem(other) +@CompileTimeCalculation fun rem(value: Int, other: Short) = value.rem(other) +@CompileTimeCalculation fun rem(value: Int, other: Int) = value.rem(other) +@CompileTimeCalculation fun rem(value: Int, other: Long) = value.rem(other) +@CompileTimeCalculation fun rem(value: Int, other: Float) = value.rem(other) +@CompileTimeCalculation fun rem(value: Int, other: Double) = value.rem(other) + +@CompileTimeCalculation fun inc(value: Int) = value.inc() +@CompileTimeCalculation fun dec(value: Int) = value.dec() + +@CompileTimeCalculation fun unaryPlus(value: Int) = value.unaryPlus() +@CompileTimeCalculation fun unaryMinus(value: Int) = value.unaryMinus() + +@CompileTimeCalculation fun rangeTo(value: Int, other: Byte) = value.rangeTo(other) +@CompileTimeCalculation fun rangeTo(value: Int, other: Short) = value.rangeTo(other) +@CompileTimeCalculation fun rangeTo(value: Int, other: Int) = value.rangeTo(other) +@CompileTimeCalculation fun rangeTo(value: Int, other: Long) = value.rangeTo(other) + +@CompileTimeCalculation fun shl(value: Int, bitCount: Int) = value.shl(bitCount) +@CompileTimeCalculation fun shr(value: Int, bitCount: Int) = value.shr(bitCount) +@CompileTimeCalculation fun ushr(value: Int, bitCount: Int) = value.ushr(bitCount) + +@CompileTimeCalculation fun and(value: Int, other: Int) = value.and(other) +@CompileTimeCalculation fun or(value: Int, other: Int) = value.or(other) +@CompileTimeCalculation fun xor(value: Int, other: Int) = value.xor(other) +@CompileTimeCalculation fun inv(value: Int) = value.inv() + +@CompileTimeCalculation fun toByte(value: Int) = value.toByte() +@CompileTimeCalculation fun toChar(value: Int) = value.toChar() +@CompileTimeCalculation fun toShort(value: Int) = value.toShort() +@CompileTimeCalculation fun toInt(value: Int) = value.toInt() +@CompileTimeCalculation fun toLong(value: Int) = value.toLong() +@CompileTimeCalculation fun toFloat(value: Int) = value.toFloat() +@CompileTimeCalculation fun toDouble(value: Int) = value.toDouble() + +@CompileTimeCalculation fun toString(value: Int) = value.toString() +@CompileTimeCalculation fun hashCode(value: Int) = value.hashCode() +@CompileTimeCalculation fun equals(value: Int, other: Int) = value.equals(other) + +@CompileTimeCalculation fun echo(value: Int) = value + +const val min = echo(Int.MIN_VALUE) +const val max = echo(Int.MAX_VALUE) +const val bytes = echo(Int.SIZE_BYTES) +const val bits = echo(Int.SIZE_BITS) + +const val compare1 = compareTo(5, 1.toByte()) +const val compare2 = compareTo(5, 2.toShort()) +const val compare3 = compareTo(5, 3) +const val compare4 = compareTo(5, 4L) +const val compare5 = compareTo(5, 5.toFloat()) +const val compare6 = compareTo(5, 6.toDouble()) + +const val plus1 = plus(5, 1.toByte()) +const val plus2 = plus(5, 2.toShort()) +const val plus3 = plus(5, 3) +const val plus4 = plus(5, 4L) +const val plus5 = plus(5, 5.toFloat()) +const val plus6 = plus(5, 6.toDouble()) + +const val minus1 = minus(5, 1.toByte()) +const val minus2 = minus(5, 2.toShort()) +const val minus3 = minus(5, 3) +const val minus4 = minus(5, 4L) +const val minus5 = minus(5, 5.toFloat()) +const val minus6 = minus(5, 6.toDouble()) + +const val times1 = times(5, 1.toByte()) +const val times2 = times(5, 2.toShort()) +const val times3 = times(5, 3) +const val times4 = times(5, 4L) +const val times5 = times(5, 5.toFloat()) +const val times6 = times(5, 6.toDouble()) + +const val div1 = div(100, 1.toByte()) +const val div2 = div(100, 2.toShort()) +const val div3 = div(100, 4) +const val div4 = div(100, 10L) +const val div5 = div(100, 25.toFloat()) +const val div6 = div(100, 50.toDouble()) + +const val rem1 = rem(5, 1.toByte()) +const val rem2 = rem(5, 2.toShort()) +const val rem3 = rem(5, 3) +const val rem4 = rem(5, 4L) +const val rem5 = rem(5, 5.toFloat()) +const val rem6 = rem(5, 6.toDouble()) + +const val increment = inc(3) +const val decrement = dec(3) + +const val unaryPlus = unaryPlus(3) +const val unaryMinus = unaryMinus(3) + +const val rangeTo1 = rangeTo(5, 1.toByte()).last +const val rangeTo2 = rangeTo(5, 2.toShort()).last +const val rangeTo3 = rangeTo(5, 3).last +const val rangeTo4 = rangeTo(5, 4L).last + +const val shiftLeft = shl(8, 1) +const val shiftRight = shr(8, 2) +const val unsignedShiftRight = ushr(-8, 3) + +const val and = and(8, 1) +const val or = or(8, 2) +const val xor = xor(-8, 3) +const val inv = inv(8) + +const val a1 = toByte(1) +const val a2 = toChar(2) +const val a3 = toShort(3) +const val a4 = toInt(4) +const val a5 = toLong(5) +const val a6 = toFloat(6) +const val a7 = toDouble(7) + +const val b1 = toString(10) +const val b2 = hashCode(10) +const val b3 = equals(10, 11) +const val b4 = equals(1, 1.toInt()) +const val b5 = equals(1, 1) diff --git a/compiler/testData/ir/interpreter/primitives/longMethods.kt b/compiler/testData/ir/interpreter/primitives/longMethods.kt new file mode 100644 index 00000000000..1a34df8ceb9 --- /dev/null +++ b/compiler/testData/ir/interpreter/primitives/longMethods.kt @@ -0,0 +1,156 @@ +@CompileTimeCalculation fun compareTo(value: Long, other: Byte) = value.compareTo(other) +@CompileTimeCalculation fun compareTo(value: Long, other: Short) = value.compareTo(other) +@CompileTimeCalculation fun compareTo(value: Long, other: Int) = value.compareTo(other) +@CompileTimeCalculation fun compareTo(value: Long, other: Long) = value.compareTo(other) +@CompileTimeCalculation fun compareTo(value: Long, other: Float) = value.compareTo(other) +@CompileTimeCalculation fun compareTo(value: Long, other: Double) = value.compareTo(other) + +@CompileTimeCalculation fun plus(value: Long, other: Byte) = value.plus(other) +@CompileTimeCalculation fun plus(value: Long, other: Short) = value.plus(other) +@CompileTimeCalculation fun plus(value: Long, other: Int) = value.plus(other) +@CompileTimeCalculation fun plus(value: Long, other: Long) = value.plus(other) +@CompileTimeCalculation fun plus(value: Long, other: Float) = value.plus(other) +@CompileTimeCalculation fun plus(value: Long, other: Double) = value.plus(other) + +@CompileTimeCalculation fun minus(value: Long, other: Byte) = value.minus(other) +@CompileTimeCalculation fun minus(value: Long, other: Short) = value.minus(other) +@CompileTimeCalculation fun minus(value: Long, other: Int) = value.minus(other) +@CompileTimeCalculation fun minus(value: Long, other: Long) = value.minus(other) +@CompileTimeCalculation fun minus(value: Long, other: Float) = value.minus(other) +@CompileTimeCalculation fun minus(value: Long, other: Double) = value.minus(other) + +@CompileTimeCalculation fun times(value: Long, other: Byte) = value.times(other) +@CompileTimeCalculation fun times(value: Long, other: Short) = value.times(other) +@CompileTimeCalculation fun times(value: Long, other: Int) = value.times(other) +@CompileTimeCalculation fun times(value: Long, other: Long) = value.times(other) +@CompileTimeCalculation fun times(value: Long, other: Float) = value.times(other) +@CompileTimeCalculation fun times(value: Long, other: Double) = value.times(other) + +@CompileTimeCalculation fun div(value: Long, other: Byte) = value.div(other) +@CompileTimeCalculation fun div(value: Long, other: Short) = value.div(other) +@CompileTimeCalculation fun div(value: Long, other: Int) = value.div(other) +@CompileTimeCalculation fun div(value: Long, other: Long) = value.div(other) +@CompileTimeCalculation fun div(value: Long, other: Float) = value.div(other) +@CompileTimeCalculation fun div(value: Long, other: Double) = value.div(other) + +@CompileTimeCalculation fun rem(value: Long, other: Byte) = value.rem(other) +@CompileTimeCalculation fun rem(value: Long, other: Short) = value.rem(other) +@CompileTimeCalculation fun rem(value: Long, other: Int) = value.rem(other) +@CompileTimeCalculation fun rem(value: Long, other: Long) = value.rem(other) +@CompileTimeCalculation fun rem(value: Long, other: Float) = value.rem(other) +@CompileTimeCalculation fun rem(value: Long, other: Double) = value.rem(other) + +@CompileTimeCalculation fun inc(value: Long) = value.inc() +@CompileTimeCalculation fun dec(value: Long) = value.dec() + +@CompileTimeCalculation fun unaryPlus(value: Long) = value.unaryPlus() +@CompileTimeCalculation fun unaryMinus(value: Long) = value.unaryMinus() + +@CompileTimeCalculation fun rangeTo(value: Long, other: Byte) = value.rangeTo(other) +@CompileTimeCalculation fun rangeTo(value: Long, other: Short) = value.rangeTo(other) +@CompileTimeCalculation fun rangeTo(value: Long, other: Int) = value.rangeTo(other) +@CompileTimeCalculation fun rangeTo(value: Long, other: Long) = value.rangeTo(other) + +@CompileTimeCalculation fun shl(value: Long, bitCount: Int) = value.shl(bitCount) +@CompileTimeCalculation fun shr(value: Long, bitCount: Int) = value.shr(bitCount) +@CompileTimeCalculation fun ushr(value: Long, bitCount: Int) = value.ushr(bitCount) + +@CompileTimeCalculation fun and(value: Long, other: Long) = value.and(other) +@CompileTimeCalculation fun or(value: Long, other: Long) = value.or(other) +@CompileTimeCalculation fun xor(value: Long, other: Long) = value.xor(other) +@CompileTimeCalculation fun inv(value: Long) = value.inv() + +@CompileTimeCalculation fun toByte(value: Long) = value.toByte() +@CompileTimeCalculation fun toChar(value: Long) = value.toChar() +@CompileTimeCalculation fun toShort(value: Long) = value.toShort() +@CompileTimeCalculation fun toInt(value: Long) = value.toInt() +@CompileTimeCalculation fun toLong(value: Long) = value.toLong() +@CompileTimeCalculation fun toFloat(value: Long) = value.toFloat() +@CompileTimeCalculation fun toDouble(value: Long) = value.toDouble() + +@CompileTimeCalculation fun toString(value: Long) = value.toString() +@CompileTimeCalculation fun hashCode(value: Long) = value.hashCode() +@CompileTimeCalculation fun equals(value: Long, other: Long) = value.equals(other) + +@CompileTimeCalculation fun echo(value: Any) = value + +const val min = echo(Long.MIN_VALUE) as Long +const val max = echo(Long.MAX_VALUE) as Long +const val bytes = echo(Long.SIZE_BYTES) as Int +const val bits = echo(Long.SIZE_BITS) as Int + +const val compare1 = compareTo(5L, 1.toByte()) +const val compare2 = compareTo(5L, 2.toShort()) +const val compare3 = compareTo(5L, 3) +const val compare4 = compareTo(5L, 4L) +const val compare5 = compareTo(5L, 5.toFloat()) +const val compare6 = compareTo(5L, 6.toDouble()) + +const val plus1 = plus(5L, 1.toByte()) +const val plus2 = plus(5L, 2.toShort()) +const val plus3 = plus(5L, 3) +const val plus4 = plus(5L, 4L) +const val plus5 = plus(5L, 5.toFloat()) +const val plus6 = plus(5L, 6.toDouble()) + +const val minus1 = minus(5L, 1.toByte()) +const val minus2 = minus(5L, 2.toShort()) +const val minus3 = minus(5L, 3) +const val minus4 = minus(5L, 4L) +const val minus5 = minus(5L, 5.toFloat()) +const val minus6 = minus(5L, 6.toDouble()) + +const val times1 = times(5L, 1.toByte()) +const val times2 = times(5L, 2.toShort()) +const val times3 = times(5L, 3) +const val times4 = times(5L, 4L) +const val times5 = times(5L, 5.toFloat()) +const val times6 = times(5L, 6.toDouble()) + +const val div1 = div(100L, 1.toByte()) +const val div2 = div(100L, 2.toShort()) +const val div3 = div(100L, 4) +const val div4 = div(100L, 10L) +const val div5 = div(100L, 25.toFloat()) +const val div6 = div(100L, 50.toDouble()) + +const val rem1 = rem(5L, 1.toByte()) +const val rem2 = rem(5L, 2.toShort()) +const val rem3 = rem(5L, 3) +const val rem4 = rem(5L, 4L) +const val rem5 = rem(5L, 5.toFloat()) +const val rem6 = rem(5L, 6.toDouble()) + +const val increment = inc(3L) +const val decrement = dec(3L) + +const val unaryPlus = unaryPlus(3L) +const val unaryMinus = unaryMinus(3L) + +const val rangeTo1 = rangeTo(5L, 1.toByte()).last +const val rangeTo2 = rangeTo(5L, 2.toShort()).last +const val rangeTo3 = rangeTo(5L, 3).last +const val rangeTo4 = rangeTo(5L, 4L).last + +const val shiftLeft = shl(8L, 1) +const val shiftRight = shr(8L, 2) +const val unsignedShiftRight = ushr(-8L, 3) + +const val and = and(8L, 1L) +const val or = or(8L, 2L) +const val xor = xor(-8L, 3L) +const val inv = inv(8L) + +const val a1 = toByte(1L) +const val a2 = toChar(2L) +const val a3 = toShort(3L) +const val a4 = toInt(4L) +const val a5 = toLong(5L) +const val a6 = toFloat(6L) +const val a7 = toDouble(7L) + +const val b1 = toString(10L) +const val b2 = hashCode(10L) +const val b3 = equals(10L, 11L) +const val b4 = equals(1L, 1.toLong()) +const val b5 = equals(1L, 1) diff --git a/compiler/testData/ir/interpreter/primitives/uInt.kt b/compiler/testData/ir/interpreter/primitives/uInt.kt new file mode 100644 index 00000000000..bdd461047b1 --- /dev/null +++ b/compiler/testData/ir/interpreter/primitives/uInt.kt @@ -0,0 +1,131 @@ +import kotlin.* + +@CompileTimeCalculation fun compareTo(value: UInt, other: UByte) = value.compareTo(other) +@CompileTimeCalculation fun compareTo(value: UInt, other: UShort) = value.compareTo(other) +@CompileTimeCalculation fun compareTo(value: UInt, other: UInt) = value.compareTo(other) +@CompileTimeCalculation fun compareTo(value: UInt, other: ULong) = value.compareTo(other) + +@CompileTimeCalculation fun plus(value: UInt, other: UByte) = value.plus(other) +@CompileTimeCalculation fun plus(value: UInt, other: UShort) = value.plus(other) +@CompileTimeCalculation fun plus(value: UInt, other: UInt) = value.plus(other) +@CompileTimeCalculation fun plus(value: UInt, other: ULong) = value.plus(other) + +@CompileTimeCalculation fun minus(value: UInt, other: UByte) = value.minus(other) +@CompileTimeCalculation fun minus(value: UInt, other: UShort) = value.minus(other) +@CompileTimeCalculation fun minus(value: UInt, other: UInt) = value.minus(other) +@CompileTimeCalculation fun minus(value: UInt, other: ULong) = value.minus(other) + +@CompileTimeCalculation fun times(value: UInt, other: UByte) = value.times(other) +@CompileTimeCalculation fun times(value: UInt, other: UShort) = value.times(other) +@CompileTimeCalculation fun times(value: UInt, other: UInt) = value.times(other) +@CompileTimeCalculation fun times(value: UInt, other: ULong) = value.times(other) + +@CompileTimeCalculation fun div(value: UInt, other: UByte) = value.div(other) +@CompileTimeCalculation fun div(value: UInt, other: UShort) = value.div(other) +@CompileTimeCalculation fun div(value: UInt, other: UInt) = value.div(other) +@CompileTimeCalculation fun div(value: UInt, other: ULong) = value.div(other) + +@CompileTimeCalculation fun rem(value: UInt, other: UByte) = value.rem(other) +@CompileTimeCalculation fun rem(value: UInt, other: UShort) = value.rem(other) +@CompileTimeCalculation fun rem(value: UInt, other: UInt) = value.rem(other) +@CompileTimeCalculation fun rem(value: UInt, other: ULong) = value.rem(other) + +@CompileTimeCalculation fun inc(value: UInt) = value.inc() +@CompileTimeCalculation fun dec(value: UInt) = value.dec() + +@CompileTimeCalculation fun rangeTo(value: UInt, other: UInt) = value.rangeTo(other) + +@CompileTimeCalculation fun shl(value: UInt, bitCount: Int) = value.shl(bitCount) +@CompileTimeCalculation fun shr(value: UInt, bitCount: Int) = value.shr(bitCount) +@CompileTimeCalculation fun and(value: UInt, other: UInt) = value.and(other) +@CompileTimeCalculation fun or(value: UInt, other: UInt) = value.or(other) +@CompileTimeCalculation fun xor(value: UInt, other: UInt) = value.xor(other) +@CompileTimeCalculation fun inv(value: UInt) = value.inv() + +@CompileTimeCalculation fun toByte(value: UInt) = value.toByte() +@CompileTimeCalculation fun toShort(value: UInt) = value.toShort() +@CompileTimeCalculation fun toInt(value: UInt) = value.toInt() +@CompileTimeCalculation fun toLong(value: UInt) = value.toLong() +@CompileTimeCalculation fun toUByte(value: UInt) = value.toUByte() +@CompileTimeCalculation fun toUShort(value: UInt) = value.toUShort() +@CompileTimeCalculation fun toUInt(value: UInt) = value.toUInt() +@CompileTimeCalculation fun toULong(value: UInt) = value.toULong() +@CompileTimeCalculation fun toFloat(value: UInt) = value.toFloat() +@CompileTimeCalculation fun toDouble(value: UInt) = value.toDouble() + +@CompileTimeCalculation fun toString(value: UInt) = value.toString() +@CompileTimeCalculation fun hashCode(value: UInt) = value.hashCode() +@CompileTimeCalculation fun equals(value: UInt, other: Any) = value.equals(other) + +@CompileTimeCalculation fun echo(value: Any) = value + +const val min = echo(UInt.MIN_VALUE) as UInt +const val max = echo(UInt.MAX_VALUE) as UInt +const val bytes = echo(UInt.SIZE_BYTES) as Int +const val bits = echo(UInt.SIZE_BITS) as Int + +const val uByte: UByte = 0u +const val uByteNonZero: UByte = 1u +const val uShort: UShort = 1u +const val uInt: UInt = 2u +const val uLong: ULong = 3uL + +const val compare1 = compareTo(2u, uByte) +const val compare2 = compareTo(2u, uShort) +const val compare3 = compareTo(2u, uInt) +const val compare4 = compareTo(2u, uLong) + +const val plus1 = plus(2u, uByte) +const val plus2 = plus(2u, uShort) +const val plus3 = plus(2u, uInt) +const val plus4 = plus(2u, uLong) + +const val minus1 = minus(2u, uByte) +const val minus2 = minus(2u, uShort) +const val minus3 = minus(2u, uInt) +const val minus4 = minus(2u, uLong) + +const val times1 = times(2u, uByte) +const val times2 = times(2u, uShort) +const val times3 = times(2u, uInt) +const val times4 = times(2u, uLong) + +const val div1 = div(2u, uByteNonZero) +const val div2 = div(2u, uShort) +const val div3 = div(2u, uInt) +const val div4 = div(2u, uLong) + +const val rem1 = rem(2u, uByteNonZero) +const val rem2 = rem(2u, uShort) +const val rem3 = rem(2u, uInt) +const val rem4 = rem(2u, uLong) + +const val inc = inc(3u) +const val dec = dec(3u) + +const val rangeTo = rangeTo(0u, 10u).last + +const val shiftLeft = shl(8u, 1) +const val shiftRight = shr(8u, 2) + +const val and = and(8u, 1u) +const val or = or(8u, 2u) +const val xor = xor(8u, 3u) +const val inv = inv(8u) + +const val a1 = toByte(1u) +const val a2 = toShort(2u) +const val a3 = toInt(3u) +const val a4 = toLong(4u) +const val a5 = toUByte(5u) +const val a6 = toUShort(6u) +const val a7 = toUInt(7u) +const val a8 = toULong(8u) +const val a9 = toFloat(9u) +const val a10 = toDouble(10u) + +const val b1 = toString(10u) +// const val b2 = hashCode(10u) TODO support later; in current version method hashCode is missing +const val b3 = equals(10u, 11u) +const val b4 = equals(1u, 1) +const val b5 = equals(3u, 3uL) diff --git a/compiler/testData/ir/interpreter/progressionFromClosedRange.kt b/compiler/testData/ir/interpreter/progressionFromClosedRange.kt new file mode 100644 index 00000000000..69e9d846741 --- /dev/null +++ b/compiler/testData/ir/interpreter/progressionFromClosedRange.kt @@ -0,0 +1,3 @@ +const val a = IntProgression.fromClosedRange(0, 10, 1).first +const val b = LongProgression.fromClosedRange(0L, 10L, 1L).last +const val c = CharProgression.fromClosedRange('0', '9', 1).step diff --git a/compiler/testData/ir/interpreter/proxy/customCharSequence.kt b/compiler/testData/ir/interpreter/proxy/customCharSequence.kt new file mode 100644 index 00000000000..edc71a67c10 --- /dev/null +++ b/compiler/testData/ir/interpreter/proxy/customCharSequence.kt @@ -0,0 +1,12 @@ +@CompileTimeCalculation +class MyCharSequence(val str: String): CharSequence { + override val length: Int = str.length + + override fun get(index: Int) = str[index] + + override fun subSequence(startIndex: Int, endIndex: Int) = str.subSequence(startIndex, endIndex) +} + +const val sbSize = StringBuilder(MyCharSequence("MyString")).length +const val appendSize = StringBuilder().append(MyCharSequence("MyString")).length +const val subSequenceSize = StringBuilder(StringBuilder(MyCharSequence("MyString")).subSequence(0, 4)).length diff --git a/compiler/testData/ir/interpreter/proxy/customEquals.kt b/compiler/testData/ir/interpreter/proxy/customEquals.kt new file mode 100644 index 00000000000..62a0a0c1d37 --- /dev/null +++ b/compiler/testData/ir/interpreter/proxy/customEquals.kt @@ -0,0 +1,13 @@ +import kotlin.collections.* + +@CompileTimeCalculation +class B(val b: Int) { + override fun equals(other: Any?): Boolean { + other as? B ?: return false + return this.b == other.b + } + + override fun toString(): String = "B($b)" +} +const val areEquals = listOf(B(1), B(2)) == listOf(B(1), B(2)) +const val asString = listOf(B(1), B(2)).toString() diff --git a/compiler/testData/ir/interpreter/proxy/proxyPair.kt b/compiler/testData/ir/interpreter/proxy/proxyPair.kt new file mode 100644 index 00000000000..59a3a8741a8 --- /dev/null +++ b/compiler/testData/ir/interpreter/proxy/proxyPair.kt @@ -0,0 +1,8 @@ +import kotlin.* +import kotlin.collections.* + +@CompileTimeCalculation +class A(val a: Int) +const val size = mapOf(1 to "A(1)").size +const val first = mapOf(1 to "A(1)").entries.single().key +const val second = mapOf(1 to "A(1)").values.single() diff --git a/compiler/testData/ir/interpreter/proxy/superWrapper.kt b/compiler/testData/ir/interpreter/proxy/superWrapper.kt new file mode 100644 index 00000000000..68da6b20e48 --- /dev/null +++ b/compiler/testData/ir/interpreter/proxy/superWrapper.kt @@ -0,0 +1,21 @@ +import kotlin.collections.* + +@CompileTimeCalculation +class MyArrayList: ArrayList() { + var addCounter = 0 + override fun add(element: E): Boolean { + addCounter++ + return super.add(element) + } +} + +@CompileTimeCalculation +fun test(): String { + val list = MyArrayList() + list.add(1) + list.add(2) + list.add(3) + return "Counter " + list.addCounter + "; size " + list.size +} + +const val testResult = test() diff --git a/compiler/testData/ir/interpreter/rangeTo.kt b/compiler/testData/ir/interpreter/rangeTo.kt new file mode 100644 index 00000000000..a6ee31e6244 --- /dev/null +++ b/compiler/testData/ir/interpreter/rangeTo.kt @@ -0,0 +1,11 @@ +const val range = (1..10).first + +@CompileTimeCalculation +fun getIterator(first: Int, last: Int): Int { + val iterator = (first..last).iterator() + iterator.nextInt() + iterator.nextInt() + iterator.nextInt() + return iterator.nextInt() +} +const val testIterator = getIterator(1, 10) diff --git a/compiler/testData/ir/interpreter/reference/propertyReference.kt b/compiler/testData/ir/interpreter/reference/propertyReference.kt new file mode 100644 index 00000000000..393b58f1ed4 --- /dev/null +++ b/compiler/testData/ir/interpreter/reference/propertyReference.kt @@ -0,0 +1,25 @@ +import kotlin.* + +@CompileTimeCalculation +class A(val a: Int) + +const val propertyName = A::a.name +const val propertyGet = A::a.get(A(1)) +const val propertyInvoke = A::a.invoke(A(2)) + +const val propertyWithReceiverName = A(10)::a.name +const val propertyWithReceiverGet = A(11)::a.get() +const val propertyWithReceiverInvoke = A(12)::a.invoke() + +@CompileTimeCalculation +class B(var b: Int) + +const val mutablePropertyName = B::b.name +const val mutablePropertyGet = B::b.get(B(1)) +const val mutablePropertySet = B(2).apply { B::b.set(this, 3) }.b +const val mutablePropertyInvoke = B::b.invoke(B(4)) + +const val mutablePropertyWithReceiverName = B(10)::b.name +const val mutablePropertyWithReceiverGet = B(11)::b.get() +const val mutablePropertyWithReceiverSet = B(12).apply { this::b.set(13) }.b +const val mutablePropertyWithReceiverInvoke = B(14)::b.invoke() diff --git a/compiler/testData/ir/interpreter/regex.kt b/compiler/testData/ir/interpreter/regex.kt new file mode 100644 index 00000000000..56393cf4700 --- /dev/null +++ b/compiler/testData/ir/interpreter/regex.kt @@ -0,0 +1,35 @@ +import kotlin.text.* +import kotlin.collections.* + +const val regConstructor1 = Regex("pattern").pattern +const val regConstructor2 = Regex("pattern", RegexOption.IGNORE_CASE).options.iterator().next().name +const val regConstructor3 = Regex("pattern", setOf(RegexOption.IGNORE_CASE, RegexOption.MULTILINE)).options.size + +const val matchEntire1 = Regex("pat").matchEntire("pat")?.value.toString() +const val matchEntire2 = Regex("[abc]").matchEntire("a")?.range?.last.toString() +const val matches1 = Regex("str(1)?").matches("str1") +const val matches2 = Regex("str(1)?").matches("str2") +const val containsMatchIn1 = Regex("[0-9]").containsMatchIn("0") +const val containsMatchIn2 = Regex("[0-9]").containsMatchIn("!!0!!") +const val containsMatchIn3 = Regex("[0-9]").containsMatchIn("!!p!!") + +//replace +const val replace1 = Regex("0").replace("There are 0 apples", "n") +const val replace2 = Regex("(red|green|blue)").replace("Roses are red, Violets are blue") { it.value + "!" } +const val replace3 = Regex("(red|green|blue)").replaceFirst("Roses are red, Violets are blue", "REPLACED") +const val split = Regex("\\W+").split("Roses are red, Violets are blue").size + +//find +const val find1 = Regex("p").find("p")?.value.toString() +const val find2 = Regex("(red|green|blue)").find("Roses are red, Violets are blue")?.groups?.size.toString() +const val find3 = Regex("(red|green|blue)").find("Roses are red, Violets are blue")?.destructured?.component1().toString() +const val find4 = Regex("(red|green|blue)").find("Roses are red, Violets are blue")?.next()?.value.toString() +const val find5 = Regex("(red|green|blue)").find("Roses are red, Violets are blue", 15)?.value.toString() +const val find6 = Regex("(red|green|blue)").findAll("Roses are red, Violets are blue").iterator().next()?.value.toString() +const val find7 = Regex("(red|green|blue)").findAll("Roses are red, Violets are blue").iterator().next()?.next()?.value.toString() +const val find8 = Regex("(red|green|blue)").findAll("Roses are red, Violets are blue").iterator().next()?.next()?.next()?.value.toString() + +//companion +const val fromLiteral = Regex.fromLiteral("[a-z0-9]+").pattern +const val escape = Regex.escape("[a-z0-9]+") +const val escapeReplacement = Regex.escapeReplacement("[a-z0-9]+") diff --git a/compiler/testData/ir/interpreter/safeClassCast.kt b/compiler/testData/ir/interpreter/safeClassCast.kt new file mode 100644 index 00000000000..3fd046c0272 --- /dev/null +++ b/compiler/testData/ir/interpreter/safeClassCast.kt @@ -0,0 +1,33 @@ +import kotlin.collections.* + +@CompileTimeCalculation +fun foo(): String { + return if (listOf() as? T == null) "Can't cast" else "Safe cast" +} + +@CompileTimeCalculation +inline fun bar(): String { + return if (listOf() as? T == null) "Can't cast" else "Safe cast" +} + +const val a1 = foo() +const val a2 = foo() +const val a3 = foo() +const val a4 = foo>() +const val a5 = foo>() + +const val b1 = bar() +const val b2 = bar() +const val b3 = bar() +const val b4 = bar>() +const val b5 = bar>() +const val b6 = bar>() + +const val c1 = arrayOf(1, 2, 3) as? Array == null +const val c2 = arrayOf(1, 2, 3) as? Array == null +const val c3 = arrayOf(listOf(1, 2), listOf(2, 3)) as? Array?> == null +const val c4 = arrayOf>(listOf(1, 2), listOf(2, 3)) as? Array?> == null +const val c5 = arrayOf>(listOf(1, 2), listOf(2, 3)) as? Array> == null +const val c6 = arrayOf>(listOf(1, 2), listOf(2, 3)) as? Array> == null +const val c7 = Array>(3) { listOf(it, it + 1) } as? Array?> == null +const val c8 = Array>(3) { listOf(it, it + 1) } as? Array> == null diff --git a/compiler/testData/ir/interpreter/scopeFunctions.kt b/compiler/testData/ir/interpreter/scopeFunctions.kt new file mode 100644 index 00000000000..322d6059566 --- /dev/null +++ b/compiler/testData/ir/interpreter/scopeFunctions.kt @@ -0,0 +1,35 @@ +import kotlin.* +import kotlin.collections.* + +@CompileTimeCalculation +class A(var num: Int, var str: String) { + fun setNewStr(newString: String) { + this.str = newString + } +} + +@CompileTimeCalculation +fun echo(value: T): T = value + +const val a = run { echo("Run block") } + +const val b = A(0, "Run with receiver").run { this.str + this.num } + +const val c = with (A(1, "String")) { + setNewStr("New String") + this.str +} + +const val d = A(2, "Apply test").apply { this.setNewStr("New apply str") }.str + +const val e = mutableListOf("one", "two", "three").also { it.add("four") }.size +const val f1 = mutableListOf("one", "two", "three").let { + it.add("four") + it.size +} +const val f2 = 10.let { it + 10 } + +const val g1 = 1.takeIf { it % 2 == 0 }.toString() +const val g2 = 2.takeIf { it % 2 == 0 }.toString() +const val h1 = (-1).takeUnless { it > 0 }.toString() +const val h2 = 1.takeUnless { it > 0 }.toString() diff --git a/compiler/testData/ir/interpreter/secondaryConstructor.kt b/compiler/testData/ir/interpreter/secondaryConstructor.kt new file mode 100644 index 00000000000..507bb732274 --- /dev/null +++ b/compiler/testData/ir/interpreter/secondaryConstructor.kt @@ -0,0 +1,33 @@ +@CompileTimeCalculation +class Person(val name: String, val surname: String) { + var age: Int + val wholeName: String + + init { + wholeName = name + " " + surname + } + + init { + age = -1 + } + + constructor(name: String) : this(name, "") {} + + constructor() : this("") {} + + constructor(name: String, age: Int): this(name) { + this.age = age + } +} + +const val a1 = Person("Ivan", "Ivanov").age +const val a2 = Person("Ivan", "Ivanov").wholeName + +const val b1 = Person("Ivan").age +const val b2 = Person("Ivan").`!>wholeName + +const val c1 = Person().age +const val c2 = Person(). `!>wholeName + +const val d1 = Person("Ivan", 20).age +const val d2 = Person("Ivan", 20).`!>wholeName diff --git a/compiler/testData/ir/interpreter/spreadOperator.kt b/compiler/testData/ir/interpreter/spreadOperator.kt new file mode 100644 index 00000000000..9f190dc8c6d --- /dev/null +++ b/compiler/testData/ir/interpreter/spreadOperator.kt @@ -0,0 +1,36 @@ +@CompileTimeCalculation +fun varargSum(quantityToSum: Int, vararg num: Int): Int { + var sum = 0 + for (i in 0..(quantityToSum - 1)) { + if (i >= num.size) return sum + sum += num[i] + } + return sum +} + +@CompileTimeCalculation +fun sumWithVarargAtFirst(vararg num: Int, quantityToSum: Int = num.size) = varargSum(quantityToSum, *num) + +@CompileTimeCalculation +fun concatenation(vararg str: String): String { + var result = "" + for (s in str) result += s + return result +} + +@CompileTimeCalculation +fun customArrayConcatenation(vararg array: Any?): String { + var result = "" + for (elem in array) result += elem.toString() + " " + return result +} + +const val a1 = varargSum(3, 1, 2, 3) +const val a2 = varargSum(num = *intArrayOf(1, 2, 3), quantityToSum = 2) +const val a3 = varargSum(6, *intArrayOf(1, 2), 3, *intArrayOf(4, 5, 6)) + +const val b1 = sumWithVarargAtFirst(1, 2, 3) +const val b2 = sumWithVarargAtFirst(quantityToSum = 3, num = *intArrayOf(1, 2, 3)) + +const val c1 = concatenation(*arrayOf("1", " "), "2", *arrayOf(" ", "3")) +const val c2 = customArrayConcatenation(*arrayOf(1, 2.0), "3", *arrayOf(-1, -2.0)) diff --git a/compiler/testData/ir/interpreter/stringBuilder.kt b/compiler/testData/ir/interpreter/stringBuilder.kt new file mode 100644 index 00000000000..9952de4031f --- /dev/null +++ b/compiler/testData/ir/interpreter/stringBuilder.kt @@ -0,0 +1,24 @@ +@CompileTimeCalculation +fun appendVararg(vararg strings: String): String { + val sb = StringBuilder() + for (string in strings) { + sb.append(string) + } + return sb.toString() +} + + +const val simpleAppend = StringBuilder().append("str").toString() +const val withCapacity = StringBuilder(7).append("example").toString() +const val withContent = StringBuilder("first").append(" ").append("second").toString() +const val appendInFun = appendVararg("1", " ", "2", " ", "3") + +const val length1 = StringBuilder(3).append("1").length +const val length2 = StringBuilder().append("123456789").length +const val get0 = StringBuilder().append("1234556789").get(0) +const val get1 = StringBuilder().append("1234556789").get(1) +const val subSequence1 = StringBuilder().append("123456789").subSequence(0, 2) as String +const val subSequence2 = StringBuilder().append("123456789").subSequence(2, 8) as String + +const val appendPart = StringBuilder().append("123456789", 1, 3).toString() +const val appendNull = StringBuilder().append(null as Any?).toString() diff --git a/compiler/testData/ir/interpreter/stringConcatenation.kt b/compiler/testData/ir/interpreter/stringConcatenation.kt new file mode 100644 index 00000000000..0f45f054904 --- /dev/null +++ b/compiler/testData/ir/interpreter/stringConcatenation.kt @@ -0,0 +1,66 @@ +import kotlin.* + +@CompileTimeCalculation +open class A { + override fun toString(): String { + return "toString call from A class" + } +} + +@CompileTimeCalculation +class B : A() + +@CompileTimeCalculation +class C + +class D @CompileTimeCalculation constructor() { + @CompileTimeCalculation + override fun toString(): String { + return super.toString() + } +} + +@CompileTimeCalculation +fun getDoubledValue(a: Int): Int { + return 2 * a +} + +@CompileTimeCalculation +fun checkToStringCorrectness(value: Any, startSymbol: Char): Boolean { + val string = value.toString() + return string.get(0) == startSymbol && string.get(1) == '@' && string.length == 10 +} + +@CompileTimeCalculation fun echo(value: String) = value +@CompileTimeCalculation fun concat(first: String, second: Any) = "$first$second" + +const val constStr = echo("Success") +const val concat1 = concat("String concatenation example: ", constStr) +const val concat2 = concat("String concatenation example with primitive: ", 1) +const val concat3 = concat("String concatenation example with primitive and explicit toString call: ", 1.toString()) +const val concat4 = "String concatenation example with function that return primitive: ${getDoubledValue(10)}" +const val concat5 = "String concatenation example with A class: ${A()}" +const val concat6 = "String concatenation example with B class, where toString is FAKE_OVERRIDDEN: ${B()}" +const val concat7 = "String concatenation example with B class and explicit toString call: ${B().toString()}" +const val concat8 = "String concatenation example with C class, where toString isn't present; is it correct: ${checkToStringCorrectness(C(), 'C')}" +const val concat9 = "String concatenation example with D class, where toString is taken from Any; is it correct: ${checkToStringCorrectness(D(), 'D')}" + +const val concat10 = "String plus example with A class: " + A() +const val concat11 = "String plus example with B class, where toString is FAKE_OVERRIDDEN: " + B() + +const val concatLambda1 = kotlin.String`!>"" + fun(): String = "" +const val concatLambda2 = kotlin.String`!>"" + (fun(): String = "").toString() +const val concatLambda3 = kotlin.String`!>"" + fun(): String = "Some string" +const val concatLambda4 = kotlin.String`!>"" + fun(i: Int): String = "" +const val concatLambda5 = kotlin.String?`!>"" + fun(i: Int?): String? = "" +const val concatLambda6 = kotlin.String`!>"" + { i: Int -> "" } +const val concatLambda7 = kotlin.Unit`!>"" + { } +const val concatLambda8 = kotlin.Unit`!>"" + { i: Int, b: Double, c: String -> } +const val concatLambda9 = "". kotlin.String`!>let { + val lambdaWith: Double.(Int) -> String = { "A" } + lambdaWith.toString() +} + +// wrap as lambda to prevent calculations on frontend +const val extensionPlus1 = { "Null as string = " + null }() +const val extensionPlus2 = "Null as string = ${null.toString()}" diff --git a/compiler/testData/ir/interpreter/superClass.kt b/compiler/testData/ir/interpreter/superClass.kt new file mode 100644 index 00000000000..d2c8fdbace1 --- /dev/null +++ b/compiler/testData/ir/interpreter/superClass.kt @@ -0,0 +1,70 @@ +open class A @CompileTimeCalculation constructor(var a: Int) { + @CompileTimeCalculation + fun get(): Int { + return a + } + + @CompileTimeCalculation + open fun openGet(): Int { + return a + } + + @CompileTimeCalculation + fun setA(a: Int): A { + this.a = a + return this + } +} + +open class B @CompileTimeCalculation constructor(val b: Int) : A(b + 1) { + @CompileTimeCalculation + fun getAFromB(): Int { + return a + } + + @CompileTimeCalculation + fun getFromValueParameter(a: A): Int { + return a.get() + } +} + +open class C @CompileTimeCalculation constructor(val c: Int) : B(c + 1) { + @CompileTimeCalculation + fun getAFromC(): Int { + return a + } + + @CompileTimeCalculation + override fun openGet(): Int { + return super.openGet() + } +} + +open class D @CompileTimeCalculation constructor(val d: Int) : C(d + 1) { + +} + +open class E @CompileTimeCalculation constructor(val e: Int) : D(e + 1) { + +} + +const val a1 = A(1).get() +const val a2 = A(1).setA(2).get() +const val a3 = A(1).openGet() +const val a4 = A(1).a // property inherits compile-time annotation from primary constructor + +const val b1 = B(1).getAFromB() +const val b2 = B(1).getFromValueParameter(A(10)) +const val b3 = B(1).get() //fake overridden +const val b4 = B(1).setA(-1).get() + +const val c1 = C(1).getAFromC() +const val c2 = C(1).get() //fake overridden +const val c3 = C(1).openGet() +const val c4 = C(1).getAFromB() +const val c5 = C(1).getFromValueParameter(A(10)) //method from B +const val c6 = C(1).setA(-2).get() + +// test deep fake overridden +const val d1 = D(1).get() +const val e1 = E(1).get() diff --git a/compiler/testData/ir/interpreter/vararg.kt b/compiler/testData/ir/interpreter/vararg.kt new file mode 100644 index 00000000000..05de377b805 --- /dev/null +++ b/compiler/testData/ir/interpreter/vararg.kt @@ -0,0 +1,33 @@ +@CompileTimeCalculation +fun withVararg(vararg nums: Int): String { + var sum = 0 + for (num in nums) { + sum += num + } + return "size = " + nums.size + "; sum = " + sum +} + +@CompileTimeCalculation +fun withVarargUnknownType(vararg args: T): String { + var str = "" + for (arg in args) { + str += arg.toString() + " " + } + return "size = " + args.size + "; join = " + str +} + +@CompileTimeCalculation +fun withVarargClassType(vararg args: A): String { + var str = "" + for (arg in args) { + str += arg.i.toString() + " " + } + return "size = " + args.size + "; join = " + str +} + +@CompileTimeCalculation +class A(val i: Int) + +const val a = withVararg(1, 2, 3) +const val b = withVarargUnknownType(1, 2.0, "a") +const val c = withVarargClassType(A(1), A(2), A(3)) diff --git a/compiler/testData/ir/interpreter/variableShadowing.kt b/compiler/testData/ir/interpreter/variableShadowing.kt new file mode 100644 index 00000000000..ba7b10e35da --- /dev/null +++ b/compiler/testData/ir/interpreter/variableShadowing.kt @@ -0,0 +1,7 @@ +@CompileTimeCalculation +fun returnValueFromA(a: Int, b: Int): Int { + val a = b + return a +} + +const val num = returnValueFromA(1, 2) diff --git a/compiler/testData/ir/interpreter/variables.kt b/compiler/testData/ir/interpreter/variables.kt new file mode 100644 index 00000000000..a9627ef238f --- /dev/null +++ b/compiler/testData/ir/interpreter/variables.kt @@ -0,0 +1,33 @@ +@CompileTimeCalculation fun evalWithVariables(): Double { + val a = 1 + val b = 1.5 + return a + b +} + +@CompileTimeCalculation fun evalWithVariablesLateinit(): Double { + var a: Double + var b: Double + a = 1.5 + b = -3.75 + return a + b +} + +@CompileTimeCalculation fun evalWithValueParameter(toAdd: Int): Int { + var a: Int = toAdd + a += 10 + a = a % 5 + a -= 2 + return a +} + +class A @CompileTimeCalculation constructor(@CompileTimeCalculation val a: Int) + +@CompileTimeCalculation fun createObject(a: Int): Int { + val aObj = A(a) + return aObj.a +} + +const val a = evalWithVariables() +const val b = evalWithVariablesLateinit() +const val c = evalWithValueParameter(10) +const val d = createObject(c) diff --git a/compiler/testData/ir/interpreter/withReceivers.kt b/compiler/testData/ir/interpreter/withReceivers.kt new file mode 100644 index 00000000000..c1e22a0caf3 --- /dev/null +++ b/compiler/testData/ir/interpreter/withReceivers.kt @@ -0,0 +1,22 @@ +import kotlin.* + +@CompileTimeCalculation +class Temp(val a: T) { + fun plus(temp: Temp): Double { + return with(temp) { + return@with this.a.toDouble() + this@Temp.a.toDouble() + } + } +} + +@CompileTimeCalculation +fun plus(a: Temp, b: Temp): Double { + return with(a) w1@{ + return@w1 with(b) w2@{ + return@w2 this@w1.a.toDouble() + this@w2.a.toDouble() + } + } +} + +const val a1 = Temp(1).plus(Temp(2.0)) +const val a2 = plus(Temp(3), Temp(4)) diff --git a/compiler/tests-for-compiler-generator/tests/org/jetbrains/kotlin/test/generators/GenerateJUnit5CompilerTests.kt b/compiler/tests-for-compiler-generator/tests/org/jetbrains/kotlin/test/generators/GenerateJUnit5CompilerTests.kt index 95580ad924a..4571a0d5b6f 100644 --- a/compiler/tests-for-compiler-generator/tests/org/jetbrains/kotlin/test/generators/GenerateJUnit5CompilerTests.kt +++ b/compiler/tests-for-compiler-generator/tests/org/jetbrains/kotlin/test/generators/GenerateJUnit5CompilerTests.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.test.runners.* import org.jetbrains.kotlin.test.runners.codegen.* import org.jetbrains.kotlin.test.runners.ir.AbstractFir2IrTextTest import org.jetbrains.kotlin.test.runners.ir.AbstractIrTextTest +import org.jetbrains.kotlin.test.runners.ir.interpreter.AbstractIrInterpreterAfterFir2IrTest import org.jetbrains.kotlin.visualizer.fir.AbstractFirVisualizerTest import org.jetbrains.kotlin.visualizer.psi.AbstractPsiVisualizerTest import org.junit.jupiter.api.parallel.Execution @@ -150,6 +151,10 @@ fun generateJUnit5CompilerTests(args: Array) { testClass { model("codegen/boxInline") } + + testClass { + model("ir/interpreter", excludeDirs = listOf("helpers")) + } } testGroup("compiler/fir/analysis-tests/tests-gen", "compiler/fir/analysis-tests/testData") {