From 61811572ede9eba2c48e0eb5bb106a251ac198a6 Mon Sep 17 00:00:00 2001 From: Francis Wang Date: Thu, 4 Nov 2021 10:42:03 -0400 Subject: [PATCH 1/5] Fix type specializer reference forwarding bug --- .../ast/element/common/EDeclaration.kt | 2 +- .../post/NameRedeclarationCheckerStage.kt | 8 +++++ .../compiler/specialize/TypeSpecializer.kt | 8 +++-- .../DeclarationSpecializerStageTest.kt | 36 ++++++++++++++++++- 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/common/EDeclaration.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/common/EDeclaration.kt index 88f4b96fb..a41f540af 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/common/EDeclaration.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/common/EDeclaration.kt @@ -24,7 +24,7 @@ abstract class EDeclaration : ETypedElement(), Declaration { fun isSpecializable(): Boolean { return when (val parent = this.parent) { is EFile -> true - is EKtBasicClass -> this in parent.declarations + is EKtBasicClass -> this in parent.declarations || this == parent.primaryConstructor else -> false } } diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/check/post/NameRedeclarationCheckerStage.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/check/post/NameRedeclarationCheckerStage.kt index 252c63fe7..1866ff18b 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/check/post/NameRedeclarationCheckerStage.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/check/post/NameRedeclarationCheckerStage.kt @@ -16,6 +16,7 @@ package io.verik.compiler.check.post +import io.verik.compiler.ast.element.common.EAbstractContainerClass import io.verik.compiler.ast.element.common.EAbstractPackage import io.verik.compiler.ast.element.common.EDeclaration import io.verik.compiler.common.ProjectStage @@ -64,5 +65,12 @@ object NameRedeclarationCheckerStage : ProjectStage() { } declarationSet.checkDuplicates() } + + override fun visitAbstractContainerClass(abstractContainerClass: EAbstractContainerClass) { + super.visitAbstractContainerClass(abstractContainerClass) + val declarationSet = DeclarationSet() + abstractContainerClass.declarations.forEach { declarationSet.add(it) } + declarationSet.checkDuplicates() + } } } diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/TypeSpecializer.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/TypeSpecializer.kt index 71086e139..b03af8dff 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/TypeSpecializer.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/TypeSpecializer.kt @@ -42,7 +42,10 @@ object TypeSpecializer { } is EKtBasicClass -> { if (forwardReferences) { - val typeParameterContext = TypeParameterContext.getFromTypeArguments(arguments, reference, element) + val argumentsNotForwarded = type.arguments + .map { specialize(it, specializerContext, element, false) } + val typeParameterContext = TypeParameterContext + .getFromTypeArguments(argumentsNotForwarded, reference, element) val forwardedReference = specializerContext[reference, typeParameterContext, element] forwardedReference.toType() } else { @@ -50,7 +53,8 @@ object TypeSpecializer { } } is ETypeParameter -> { - specializerContext.typeParameterContext.specialize(reference, element) + val typeParameterType = specializerContext.typeParameterContext.specialize(reference, element) + specialize(typeParameterType, specializerContext, element, forwardReferences) } else -> { type.reference.toType(arguments) diff --git a/verik-compiler/src/test/kotlin/io/verik/compiler/specialize/DeclarationSpecializerStageTest.kt b/verik-compiler/src/test/kotlin/io/verik/compiler/specialize/DeclarationSpecializerStageTest.kt index e374497c1..be060faee 100644 --- a/verik-compiler/src/test/kotlin/io/verik/compiler/specialize/DeclarationSpecializerStageTest.kt +++ b/verik-compiler/src/test/kotlin/io/verik/compiler/specialize/DeclarationSpecializerStageTest.kt @@ -23,7 +23,7 @@ import org.junit.jupiter.api.Test internal class DeclarationSpecializerStageTest : BaseTest() { @Test - fun `specialize class type parameter`() { + fun `specialize class type parameter cardinal`() { val projectContext = driveTest( DeclarationSpecializerStage::class, """ @@ -37,6 +37,22 @@ internal class DeclarationSpecializerStageTest : BaseTest() { ) } + @Test + fun `specialize class type parameter class`() { + val projectContext = driveTest( + DeclarationSpecializerStage::class, + """ + class C + class D + val d = D() + """.trimIndent() + ) + assertElementEquals( + "KtBasicClass(D_C, [], [], [], false, false, false, PrimaryConstructor(D_C, [], []), null)", + projectContext.findDeclaration("D_C") + ) + } + @Test fun `specialize class with property`() { val projectContext = driveTest( @@ -80,4 +96,22 @@ internal class DeclarationSpecializerStageTest : BaseTest() { projectContext.findDeclaration("f_8") ) } + + @Test + fun `specialize property type parameter`() { + val projectContext = driveTest( + DeclarationSpecializerStage::class, + """ + class C + class D { + val e : E = nc() + } + val d = D() + """.trimIndent() + ) + assertElementEquals( + "KtProperty(e, C, KtCallExpression(*), [])", + projectContext.findDeclaration("e") + ) + } } From 526045276a9031538d7c984d0f797fceb57c00d5 Mon Sep 17 00:00:00 2001 From: Francis Wang Date: Thu, 4 Nov 2021 10:57:23 -0400 Subject: [PATCH 2/5] Add message to fatal --- .../io/verik/compiler/core/common/Core.kt | 1 + .../compiler/core/declaration/vk/CoreVk.kt | 17 ++++++++ .../src/main/kotlin/io/verik/core/Logging.kt | 40 ------------------- .../src/main/kotlin/io/verik/core/System.kt | 33 +++++++++++++-- 4 files changed, 48 insertions(+), 43 deletions(-) delete mode 100644 verik-core/src/main/kotlin/io/verik/core/Logging.kt diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/core/common/Core.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/core/common/Core.kt index 2d6de3485..2128146a4 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/core/common/Core.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/core/common/Core.kt @@ -172,6 +172,7 @@ object Core { val F_time = CoreVk.F_time val F_finish = CoreVk.F_finish val F_fatal = CoreVk.F_fatal + val F_fatal_String = CoreVk.F_fatal_String val F_error_String = CoreVk.F_error_String val F_sv_String = CoreVk.F_sv_String diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/core/declaration/vk/CoreVk.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/core/declaration/vk/CoreVk.kt index f984562c7..7dfa4ecdf 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/core/declaration/vk/CoreVk.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/core/declaration/vk/CoreVk.kt @@ -310,6 +310,23 @@ object CoreVk : CoreScope(CorePackage.VK) { val F_fatal = BasicCoreFunctionDeclaration(parent, "fatal", "fun fatal()", Target.F_fatal) + val F_fatal_String = object : TransformableCoreFunctionDeclaration(parent, "fatal", "fun fatal(String)") { + + override fun transform(callExpression: EKtCallExpression): EExpression { + return EKtCallExpression( + callExpression.location, + callExpression.type, + Target.F_fatal, + null, + arrayListOf( + EConstantExpression(callExpression.location, Core.Kt.C_Int.toType(), "1"), + callExpression.valueArguments[0] + ), + ArrayList() + ) + } + } + val F_error_String = BasicCoreFunctionDeclaration(parent, "error", "fun error(String)", Target.F_error) val F_sv_String = BasicCoreFunctionDeclaration(parent, "sv", "fun sv(String)", null) diff --git a/verik-core/src/main/kotlin/io/verik/core/Logging.kt b/verik-core/src/main/kotlin/io/verik/core/Logging.kt deleted file mode 100644 index ab886b3b2..000000000 --- a/verik-core/src/main/kotlin/io/verik/core/Logging.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2021 Francis Wang - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@file:Suppress("unused", "UNUSED_PARAMETER") - -package io.verik.core - -/** - * Logs [message] with severity error. - */ -fun error(message: String) { - throw VerikException() -} - -/** - * Logs [message] with severity warning. - */ -fun warning(message: String) { - throw VerikException() -} - -/** - * Logs [message] with severity info. - */ -fun info(message: String) { - throw VerikException() -} diff --git a/verik-core/src/main/kotlin/io/verik/core/System.kt b/verik-core/src/main/kotlin/io/verik/core/System.kt index 6f4f1566c..aab75cc42 100644 --- a/verik-core/src/main/kotlin/io/verik/core/System.kt +++ b/verik-core/src/main/kotlin/io/verik/core/System.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -@file:Suppress("unused") +@file:Suppress("unused", "UNUSED_PARAMETER") package io.verik.core @@ -24,10 +24,37 @@ package io.verik.core fun finish(): Nothing { throw VerikException() } - /** - Exits the simulation with an error status. + * Exits the simulation with error status. */ fun fatal(): Nothing { throw VerikException() } + +/** + * Logs [message] with severity fatal and exits the simulation with error status. + */ +fun fatal(message: String): Nothing { + throw VerikException() +} + +/** + * Logs [message] with severity error. + */ +fun error(message: String) { + throw VerikException() +} + +/** + * Logs [message] with severity warning. + */ +fun warning(message: String) { + throw VerikException() +} + +/** + * Logs [message] with severity info. + */ +fun info(message: String) { + throw VerikException() +} From d5aa7a389523e314a3fce9873008301170123783 Mon Sep 17 00:00:00 2001 From: Francis Wang Date: Thu, 4 Nov 2021 11:47:03 -0400 Subject: [PATCH 3/5] Cast is expression --- .../compiler/ast/element/kt/EIsExpression.kt | 45 +++++++++++++++++++ .../io/verik/compiler/cast/CasterVisitor.kt | 5 +++ .../verik/compiler/cast/ExpressionCaster.kt | 9 ++++ .../post/UntransformedElementCheckerStage.kt | 6 +++ .../verik/compiler/common/ElementPrinter.kt | 10 +++++ .../io/verik/compiler/common/Visitor.kt | 5 +++ .../specialize/ExpressionSpecializer.kt | 11 +++++ .../compiler/cast/ExpressionCasterTest.kt | 14 ++++++ 8 files changed, 105 insertions(+) create mode 100644 verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/kt/EIsExpression.kt diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/kt/EIsExpression.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/kt/EIsExpression.kt new file mode 100644 index 000000000..8f6908f12 --- /dev/null +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/kt/EIsExpression.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Francis Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.verik.compiler.ast.element.kt + +import io.verik.compiler.ast.element.common.EAbstractContainerExpression +import io.verik.compiler.ast.element.common.EExpression +import io.verik.compiler.ast.property.SerializationType +import io.verik.compiler.ast.property.Type +import io.verik.compiler.common.Visitor +import io.verik.compiler.core.common.Core +import io.verik.compiler.message.SourceLocation + +class EIsExpression( + override val location: SourceLocation, + override var expression: EExpression, + val isNegated: Boolean, + var castType: Type +) : EAbstractContainerExpression() { + + override var type = Core.Kt.C_Boolean.toType() + + override val serializationType = SerializationType.INTERNAL + + init { + expression.parent = this + } + + override fun accept(visitor: Visitor) { + visitor.visitIsExpression(this) + } +} diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/cast/CasterVisitor.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/cast/CasterVisitor.kt index eaeae3064..243f73927 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/cast/CasterVisitor.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/cast/CasterVisitor.kt @@ -58,6 +58,7 @@ import org.jetbrains.kotlin.psi.KtEnumEntry import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.KtIfExpression +import org.jetbrains.kotlin.psi.KtIsExpression import org.jetbrains.kotlin.psi.KtLambdaExpression import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtParameter @@ -236,6 +237,10 @@ class CasterVisitor(private val castContext: CastContext) : KtVisitor specializeReturnStatement(expression, specializerContext) is EFunctionLiteralExpression -> specializeFunctionLiteralExpression(expression, specializerContext) is EStringTemplateExpression -> specializeStringTemplateExpression(expression, specializerContext) + is EIsExpression -> specializeIsExpression(expression, specializerContext) is EIfExpression -> specializeIfExpression(expression, specializerContext) is EWhenExpression -> specializeWhenExpression(expression, specializerContext) is EWhileExpression -> specializeWhileExpression(expression, specializerContext) @@ -222,6 +224,15 @@ object ExpressionSpecializer { return EStringTemplateExpression(stringTemplateExpression.location, entries) } + private fun specializeIsExpression( + isExpression: EIsExpression, + specializerContext: SpecializerContext + ): EIsExpression { + val expression = specializerContext.specialize(isExpression.expression) + val castType = specializerContext.specializeType(isExpression.castType, isExpression) + return EIsExpression(isExpression.location, expression, isExpression.isNegated, castType) + } + private fun specializeIfExpression( ifExpression: EIfExpression, specializerContext: SpecializerContext diff --git a/verik-compiler/src/test/kotlin/io/verik/compiler/cast/ExpressionCasterTest.kt b/verik-compiler/src/test/kotlin/io/verik/compiler/cast/ExpressionCasterTest.kt index 5e6a105c7..b16b5f095 100644 --- a/verik-compiler/src/test/kotlin/io/verik/compiler/cast/ExpressionCasterTest.kt +++ b/verik-compiler/src/test/kotlin/io/verik/compiler/cast/ExpressionCasterTest.kt @@ -320,6 +320,20 @@ internal class ExpressionCasterTest : BaseTest() { ) } + @Test + fun `is expression`() { + val projectContext = driveTest( + CasterStage::class, + """ + var x = 0 is Int + """.trimIndent() + ) + assertElementEquals( + "IsExpression(Boolean, ConstantExpression(*), false, Int)", + projectContext.findExpression("x") + ) + } + @Test fun `if expression`() { val projectContext = driveTest( From 1ad48d3b6bb96df7206f98c8b5f6f057e55eee3c Mon Sep 17 00:00:00 2001 From: Francis Wang Date: Thu, 4 Nov 2021 14:53:53 -0400 Subject: [PATCH 4/5] Property in is expression --- .../ast/element/common/EPropertyStatement.kt | 4 ++-- .../ast/element/common/ETemporaryProperty.kt | 11 ++++++---- .../compiler/ast/element/kt/EIsExpression.kt | 21 ++++++++++++++++++- .../verik/compiler/cast/ExpressionCaster.kt | 11 +++++++++- .../verik/compiler/common/ElementPrinter.kt | 1 + .../interpret/BasicClassInterpreterStage.kt | 4 ++-- .../io/verik/compiler/message/Messages.kt | 2 +- .../DeclarationSpecializeIndexerVisitor.kt | 7 +++++++ .../specialize/DeclarationSpecializer.kt | 17 +++++++++++++++ .../specialize/ExpressionSpecializer.kt | 9 +++++++- .../mid/IfAndWhenExpressionUnlifterStage.kt | 14 ++++--------- .../mid/SubexpressionExtractorStage.kt | 7 ++----- .../compiler/cast/ExpressionCasterTest.kt | 2 +- 13 files changed, 82 insertions(+), 28 deletions(-) diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/common/EPropertyStatement.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/common/EPropertyStatement.kt index 7aae86019..7ed121960 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/common/EPropertyStatement.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/common/EPropertyStatement.kt @@ -46,8 +46,8 @@ class EPropertyStatement( override fun replaceChild(oldDeclaration: EDeclaration, newDeclaration: EDeclaration): Boolean { newDeclaration.parent = this - return if (property == oldDeclaration && newDeclaration is EAbstractInitializedProperty) { - property = newDeclaration + return if (property == oldDeclaration) { + newDeclaration.cast()?.let { property = it } true } else false } diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/common/ETemporaryProperty.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/common/ETemporaryProperty.kt index ae8a66a8f..728d02b0a 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/common/ETemporaryProperty.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/common/ETemporaryProperty.kt @@ -17,19 +17,22 @@ package io.verik.compiler.ast.element.common import io.verik.compiler.ast.property.Type +import io.verik.compiler.common.NullDeclaration import io.verik.compiler.common.Visitor import io.verik.compiler.message.SourceLocation class ETemporaryProperty( - override val location: SourceLocation, - override var type: Type, - override var initializer: EExpression? + override val location: SourceLocation ) : EAbstractInitializedProperty() { override var name = "" + override var type: Type = NullDeclaration.toType() + override var initializer: EExpression? = null - init { + fun init(type: Type, initializer: EExpression?) { initializer?.parent = this + this.type = type + this.initializer = initializer } override fun accept(visitor: Visitor) { diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/kt/EIsExpression.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/kt/EIsExpression.kt index 8f6908f12..c299d2032 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/kt/EIsExpression.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/kt/EIsExpression.kt @@ -17,9 +17,13 @@ package io.verik.compiler.ast.element.kt import io.verik.compiler.ast.element.common.EAbstractContainerExpression +import io.verik.compiler.ast.element.common.EAbstractInitializedProperty +import io.verik.compiler.ast.element.common.EDeclaration import io.verik.compiler.ast.element.common.EExpression +import io.verik.compiler.ast.interfaces.DeclarationContainer import io.verik.compiler.ast.property.SerializationType import io.verik.compiler.ast.property.Type +import io.verik.compiler.common.TreeVisitor import io.verik.compiler.common.Visitor import io.verik.compiler.core.common.Core import io.verik.compiler.message.SourceLocation @@ -27,9 +31,10 @@ import io.verik.compiler.message.SourceLocation class EIsExpression( override val location: SourceLocation, override var expression: EExpression, + var property: EAbstractInitializedProperty, val isNegated: Boolean, var castType: Type -) : EAbstractContainerExpression() { +) : EAbstractContainerExpression(), DeclarationContainer { override var type = Core.Kt.C_Boolean.toType() @@ -37,9 +42,23 @@ class EIsExpression( init { expression.parent = this + property.parent = this } override fun accept(visitor: Visitor) { visitor.visitIsExpression(this) } + + override fun acceptChildren(visitor: TreeVisitor) { + super.acceptChildren(visitor) + property.accept(visitor) + } + + override fun replaceChild(oldDeclaration: EDeclaration, newDeclaration: EDeclaration): Boolean { + newDeclaration.parent = this + return if (property == oldDeclaration) { + newDeclaration.cast()?.let { property = it } + true + } else false + } } diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/cast/ExpressionCaster.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/cast/ExpressionCaster.kt index b29ae5660..a88bb1f5d 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/cast/ExpressionCaster.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/cast/ExpressionCaster.kt @@ -22,6 +22,7 @@ import io.verik.compiler.ast.element.common.EIfExpression import io.verik.compiler.ast.element.common.EReferenceExpression import io.verik.compiler.ast.element.common.EReturnStatement import io.verik.compiler.ast.element.common.ESuperExpression +import io.verik.compiler.ast.element.common.ETemporaryProperty import io.verik.compiler.ast.element.common.EThisExpression import io.verik.compiler.ast.element.common.EWhileExpression import io.verik.compiler.ast.element.kt.EForExpression @@ -261,7 +262,15 @@ object ExpressionCaster { val location = expression.location() val childExpression = castContext.casterVisitor.getExpression(expression.leftHandSide) val castType = castContext.castType(expression.typeReference!!) - return EIsExpression(location, childExpression, expression.isNegated, castType) + val temporaryProperty = ETemporaryProperty(location) + temporaryProperty.init(castType, null) + return EIsExpression( + location, + childExpression, + temporaryProperty, + expression.isNegated, + castType + ) } fun castIfExpression(expression: KtIfExpression, castContext: CastContext): EIfExpression { diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/common/ElementPrinter.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/common/ElementPrinter.kt index 3197ff021..456a5dfab 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/common/ElementPrinter.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/common/ElementPrinter.kt @@ -621,6 +621,7 @@ class ElementPrinter : Visitor() { build("IsExpression") { build(isExpression.type.toString()) build(isExpression.expression) + build(isExpression.property) build(isExpression.isNegated) build(isExpression.castType.toString()) } diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/interpret/BasicClassInterpreterStage.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/interpret/BasicClassInterpreterStage.kt index 40e266088..d4202754d 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/interpret/BasicClassInterpreterStage.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/interpret/BasicClassInterpreterStage.kt @@ -168,8 +168,8 @@ object BasicClassInterpreterStage : ProjectStage() { ): ESvFunction? { if (basicClass.isAbstract) return null - val temporaryProperty = ETemporaryProperty( - constructor.location, + val temporaryProperty = ETemporaryProperty(constructor.location) + temporaryProperty.init( constructor.type.copy(), ESvCallExpression( constructor.location, diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/message/Messages.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/message/Messages.kt index 9d82ab9b4..b65f98f15 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/message/Messages.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/message/Messages.kt @@ -124,7 +124,7 @@ object Messages { ) val NO_TOP_DECLARATIONS = MessageTemplate0( - Severity.ERROR, + Severity.WARNING, "No top level declarations found" ) diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/DeclarationSpecializeIndexerVisitor.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/DeclarationSpecializeIndexerVisitor.kt index a888abc8b..c53029c09 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/DeclarationSpecializeIndexerVisitor.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/DeclarationSpecializeIndexerVisitor.kt @@ -20,6 +20,7 @@ import io.verik.compiler.ast.element.common.EDeclaration import io.verik.compiler.ast.element.common.EElement import io.verik.compiler.ast.element.common.EReceiverExpression import io.verik.compiler.ast.element.common.EReferenceExpression +import io.verik.compiler.ast.element.common.ETemporaryProperty import io.verik.compiler.ast.element.common.ETypedElement import io.verik.compiler.ast.element.kt.EKtAbstractFunction import io.verik.compiler.ast.element.kt.EKtBasicClass @@ -161,6 +162,12 @@ class DeclarationSpecializeIndexerVisitor( specializerContext[property] = specializedProperty } + override fun visitTemporaryProperty(temporaryProperty: ETemporaryProperty) { + super.visitTemporaryProperty(temporaryProperty) + val specializedTemporaryProperty = ETemporaryProperty(temporaryProperty.location) + specializerContext[temporaryProperty] = specializedTemporaryProperty + } + override fun visitKtEnumEntry(enumEntry: EKtEnumEntry) { super.visitKtEnumEntry(enumEntry) val specializedEnumEntry = EKtEnumEntry(enumEntry.location, enumEntry.name) diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/DeclarationSpecializer.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/DeclarationSpecializer.kt index 73593a722..eca47caff 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/DeclarationSpecializer.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/DeclarationSpecializer.kt @@ -17,6 +17,7 @@ package io.verik.compiler.specialize import io.verik.compiler.ast.element.common.EDeclaration +import io.verik.compiler.ast.element.common.ETemporaryProperty import io.verik.compiler.ast.element.kt.EKtBasicClass import io.verik.compiler.ast.element.kt.EKtEnumEntry import io.verik.compiler.ast.element.kt.EKtFunction @@ -37,6 +38,7 @@ object DeclarationSpecializer { is EKtFunction -> specializeKtFunction(declaration, specializerContext) is EPrimaryConstructor -> specializePrimaryConstructor(declaration, specializerContext) is EKtProperty -> specializeKtProperty(declaration, specializerContext) + is ETemporaryProperty -> specializeTemporaryProperty(declaration, specializerContext) is EKtEnumEntry -> specializeKtEnumEntry(declaration, specializerContext) is EKtValueParameter -> specializeKtValueParameter(declaration, specializerContext) else -> { @@ -144,6 +146,21 @@ object DeclarationSpecializer { return specializedProperty } + private fun specializeTemporaryProperty( + temporaryProperty: ETemporaryProperty, + specializerContext: SpecializerContext + ): ETemporaryProperty { + val specializedTemporaryProperty = specializerContext[temporaryProperty, temporaryProperty] + .cast(temporaryProperty) + ?: return temporaryProperty + + val type = specializerContext.specializeType(temporaryProperty) + val initializer = temporaryProperty.initializer?.let { specializerContext.specialize(it) } + + specializedTemporaryProperty.init(type, initializer) + return specializedTemporaryProperty + } + private fun specializeKtEnumEntry(enumEntry: EKtEnumEntry, specializerContext: SpecializerContext): EKtEnumEntry { val specializedEnumEntry = specializerContext[enumEntry, enumEntry] .cast(enumEntry) diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/ExpressionSpecializer.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/ExpressionSpecializer.kt index 6c29be9cb..395d62809 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/ExpressionSpecializer.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/specialize/ExpressionSpecializer.kt @@ -229,8 +229,15 @@ object ExpressionSpecializer { specializerContext: SpecializerContext ): EIsExpression { val expression = specializerContext.specialize(isExpression.expression) + val property = specializerContext.specialize(isExpression.property) val castType = specializerContext.specializeType(isExpression.castType, isExpression) - return EIsExpression(isExpression.location, expression, isExpression.isNegated, castType) + return EIsExpression( + isExpression.location, + expression, + property, + isExpression.isNegated, + castType + ) } private fun specializeIfExpression( diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/IfAndWhenExpressionUnlifterStage.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/IfAndWhenExpressionUnlifterStage.kt index 4ac0f6c4f..76ee5a5bc 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/IfAndWhenExpressionUnlifterStage.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/IfAndWhenExpressionUnlifterStage.kt @@ -48,11 +48,8 @@ object IfAndWhenExpressionUnlifterStage : ProjectStage() { override fun visitIfExpression(ifExpression: EIfExpression) { super.visitIfExpression(ifExpression) if (ifExpression.getExpressionType().isSubexpression()) { - val temporaryProperty = ETemporaryProperty( - ifExpression.location, - ifExpression.type.copy(), - null - ) + val temporaryProperty = ETemporaryProperty(ifExpression.location) + temporaryProperty.init(ifExpression.type.copy(), null) val propertyStatement = EPropertyStatement( ifExpression.location, temporaryProperty @@ -69,11 +66,8 @@ object IfAndWhenExpressionUnlifterStage : ProjectStage() { override fun visitWhenExpression(whenExpression: EWhenExpression) { super.visitWhenExpression(whenExpression) if (whenExpression.getExpressionType().isSubexpression()) { - val temporaryProperty = ETemporaryProperty( - whenExpression.location, - whenExpression.type.copy(), - null - ) + val temporaryProperty = ETemporaryProperty(whenExpression.location) + temporaryProperty.init(whenExpression.type.copy(), null) val propertyStatement = EPropertyStatement( whenExpression.location, temporaryProperty diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/SubexpressionExtractorStage.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/SubexpressionExtractorStage.kt index 426289818..b9c27e71c 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/SubexpressionExtractorStage.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/SubexpressionExtractorStage.kt @@ -79,11 +79,8 @@ object SubexpressionExtractorStage : ProjectStage() { streamingExpression.type.copy(), streamingExpression.expression ) - val temporaryProperty = ETemporaryProperty( - streamingExpression.location, - streamingExpression.type.copy(), - streamingExpressionReplacement - ) + val temporaryProperty = ETemporaryProperty(streamingExpression.location) + temporaryProperty.init(streamingExpression.type.copy(), streamingExpressionReplacement) val propertyStatement = EPropertyStatement( streamingExpression.location, temporaryProperty diff --git a/verik-compiler/src/test/kotlin/io/verik/compiler/cast/ExpressionCasterTest.kt b/verik-compiler/src/test/kotlin/io/verik/compiler/cast/ExpressionCasterTest.kt index b16b5f095..3b97f8bbb 100644 --- a/verik-compiler/src/test/kotlin/io/verik/compiler/cast/ExpressionCasterTest.kt +++ b/verik-compiler/src/test/kotlin/io/verik/compiler/cast/ExpressionCasterTest.kt @@ -329,7 +329,7 @@ internal class ExpressionCasterTest : BaseTest() { """.trimIndent() ) assertElementEquals( - "IsExpression(Boolean, ConstantExpression(*), false, Int)", + "IsExpression(Boolean, ConstantExpression(*), TemporaryProperty(Int, null), false, Int)", projectContext.findExpression("x") ) } From 9066b857d9095ad461ba77733dac9f2d4ab5ff52 Mon Sep 17 00:00:00 2001 From: Francis Wang Date: Thu, 4 Nov 2021 17:33:54 -0400 Subject: [PATCH 5/5] Cast transformer stage --- .../io/verik/compiler/main/StageSequencer.kt | 2 + .../io/verik/compiler/target/common/Target.kt | 1 + .../target/declaration/TargetSystem.kt | 1 + .../transform/mid/CastTransformerStage.kt | 64 +++++++++++++++++++ .../mid/IfAndWhenExpressionUnlifterStage.kt | 16 ++++- .../transform/mid/SubexpressionExtractor.kt | 37 ++++------- .../mid/SubexpressionExtractorStage.kt | 9 ++- .../transform/mid/CastTransformerStageTest.kt | 57 +++++++++++++++++ 8 files changed, 161 insertions(+), 26 deletions(-) create mode 100644 verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/CastTransformerStage.kt create mode 100644 verik-compiler/src/test/kotlin/io/verik/compiler/transform/mid/CastTransformerStageTest.kt diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/main/StageSequencer.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/main/StageSequencer.kt index b7ec6d6a8..bd818ccd6 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/main/StageSequencer.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/main/StageSequencer.kt @@ -53,6 +53,7 @@ import io.verik.compiler.serialize.target.TargetSerializerStage import io.verik.compiler.specialize.DeclarationSpecializerStage import io.verik.compiler.transform.mid.AssignmentTransformerStage import io.verik.compiler.transform.mid.CaseStatementTransformerStage +import io.verik.compiler.transform.mid.CastTransformerStage import io.verik.compiler.transform.mid.ConstantExpressionEvaluatorStage import io.verik.compiler.transform.mid.EnumNameTransformerStage import io.verik.compiler.transform.mid.ForStatementTransformerStage @@ -138,6 +139,7 @@ object StageSequencer { stageSequence.add(EnumNameTransformerStage) stageSequence.add(InjectedExpressionReducerStage) stageSequence.add(StringTemplateExpressionReducerStage) + stageSequence.add(CastTransformerStage) stageSequence.add(UninitializedPropertyTransformerStage) stageSequence.add(ForStatementTransformerStage) stageSequence.add(FunctionTransformerStage) diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/target/common/Target.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/target/common/Target.kt index da2d10987..1629299c7 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/target/common/Target.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/target/common/Target.kt @@ -35,6 +35,7 @@ object Target { val C_Event = TargetClass.C_Event val C_ArrayList = TargetClass.C_ArrayList + val F_cast = TargetSystem.F_cast val F_display = TargetSystem.F_display val F_write = TargetSystem.F_write val F_sformatf = TargetSystem.F_sformatf diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/target/declaration/TargetSystem.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/target/declaration/TargetSystem.kt index c45e68ecd..e807bde18 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/target/declaration/TargetSystem.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/target/declaration/TargetSystem.kt @@ -22,6 +22,7 @@ import io.verik.compiler.target.common.TargetScope object TargetSystem : TargetScope(TargetPackage) { + val F_cast = PrimitiveTargetFunctionDeclaration(parent, "\$cast") val F_display = PrimitiveTargetFunctionDeclaration(parent, "\$display") val F_write = PrimitiveTargetFunctionDeclaration(parent, "\$write") val F_sformatf = PrimitiveTargetFunctionDeclaration(parent, "\$sformatf") diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/CastTransformerStage.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/CastTransformerStage.kt new file mode 100644 index 000000000..0fc2d8609 --- /dev/null +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/CastTransformerStage.kt @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021 Francis Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.verik.compiler.transform.mid + +import io.verik.compiler.ast.element.common.EPropertyStatement +import io.verik.compiler.ast.element.common.EReferenceExpression +import io.verik.compiler.ast.element.kt.EIsExpression +import io.verik.compiler.ast.element.kt.EKtCallExpression +import io.verik.compiler.common.ProjectStage +import io.verik.compiler.common.TreeVisitor +import io.verik.compiler.core.common.Core +import io.verik.compiler.main.ProjectContext +import io.verik.compiler.target.common.Target + +object CastTransformerStage : ProjectStage() { + + override val checkNormalization = true + + override fun process(projectContext: ProjectContext) { + val subexpressionExtractor = SubexpressionExtractor() + val castTransformerVisitor = CastTransformerVisitor(subexpressionExtractor) + projectContext.project.accept(castTransformerVisitor) + subexpressionExtractor.flush() + } + + private class CastTransformerVisitor( + private val subexpressionExtractor: SubexpressionExtractor + ) : TreeVisitor() { + + override fun visitIsExpression(isExpression: EIsExpression) { + super.visitIsExpression(isExpression) + val referenceExpression = EReferenceExpression( + isExpression.location, + isExpression.property.type.copy(), + isExpression.property, + null + ) + val callExpression = EKtCallExpression( + isExpression.location, + Core.Kt.C_Boolean.toType(), + Target.F_cast, + null, + arrayListOf(referenceExpression, isExpression.expression), + ArrayList() + ) + val propertyStatement = EPropertyStatement(isExpression.location, isExpression.property) + subexpressionExtractor.extract(isExpression, callExpression, listOf(propertyStatement)) + } + } +} diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/IfAndWhenExpressionUnlifterStage.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/IfAndWhenExpressionUnlifterStage.kt index 76ee5a5bc..661cdc3f7 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/IfAndWhenExpressionUnlifterStage.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/IfAndWhenExpressionUnlifterStage.kt @@ -50,6 +50,12 @@ object IfAndWhenExpressionUnlifterStage : ProjectStage() { if (ifExpression.getExpressionType().isSubexpression()) { val temporaryProperty = ETemporaryProperty(ifExpression.location) temporaryProperty.init(ifExpression.type.copy(), null) + val referenceExpression = EReferenceExpression( + ifExpression.location, + temporaryProperty.type.copy(), + temporaryProperty, + null + ) val propertyStatement = EPropertyStatement( ifExpression.location, temporaryProperty @@ -57,7 +63,7 @@ object IfAndWhenExpressionUnlifterStage : ProjectStage() { val ifExpressionReplacement = getIfExpressionReplacement(ifExpression, temporaryProperty) subexpressionExtractor.extract( ifExpression, - temporaryProperty, + referenceExpression, listOf(propertyStatement, ifExpressionReplacement) ) } @@ -68,6 +74,12 @@ object IfAndWhenExpressionUnlifterStage : ProjectStage() { if (whenExpression.getExpressionType().isSubexpression()) { val temporaryProperty = ETemporaryProperty(whenExpression.location) temporaryProperty.init(whenExpression.type.copy(), null) + val referenceExpression = EReferenceExpression( + whenExpression.location, + temporaryProperty.type.copy(), + temporaryProperty, + null + ) val propertyStatement = EPropertyStatement( whenExpression.location, temporaryProperty @@ -75,7 +87,7 @@ object IfAndWhenExpressionUnlifterStage : ProjectStage() { val whenExpressionReplacement = getWhenExpressionReplacement(whenExpression, temporaryProperty) subexpressionExtractor.extract( whenExpression, - temporaryProperty, + referenceExpression, listOf(propertyStatement, whenExpressionReplacement) ) } diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/SubexpressionExtractor.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/SubexpressionExtractor.kt index 56cffc8ca..d62eece14 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/SubexpressionExtractor.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/SubexpressionExtractor.kt @@ -21,8 +21,6 @@ import io.verik.compiler.ast.element.common.EAbstractFunction import io.verik.compiler.ast.element.common.EElement import io.verik.compiler.ast.element.common.EExpression import io.verik.compiler.ast.element.common.EFile -import io.verik.compiler.ast.element.common.EReferenceExpression -import io.verik.compiler.ast.element.common.ETemporaryProperty import io.verik.compiler.ast.element.kt.EKtBlockExpression import io.verik.compiler.message.Messages @@ -31,11 +29,11 @@ class SubexpressionExtractor { private val entries = ArrayList() fun extract( - expression: EExpression, - temporaryProperty: ETemporaryProperty, - initializerExpressions: List + oldExpression: EExpression, + newExpression: EExpression, + extractedExpressions: List ) { - entries.add(SubexpressionExtractorEntry(expression, temporaryProperty, initializerExpressions)) + entries.add(SubexpressionExtractorEntry(oldExpression, newExpression, extractedExpressions)) } fun flush() { @@ -43,8 +41,8 @@ class SubexpressionExtractor { } private fun flushEntry(entry: SubexpressionExtractorEntry) { - var blockExpression = entry.expression.parent - var blockExpressionChild: EElement = entry.expression + var blockExpression = entry.oldExpression.parent + var blockExpressionChild: EElement = entry.oldExpression while (true) { when (blockExpression) { is EKtBlockExpression -> { @@ -52,11 +50,11 @@ class SubexpressionExtractor { if (blockExpressionIndex != -1) flushEntry(blockExpression, blockExpressionIndex, entry) else - Messages.SUBEXPRESSION_UNABLE_TO_EXTRACT.on(entry.expression) + Messages.SUBEXPRESSION_UNABLE_TO_EXTRACT.on(entry.oldExpression) return } is EAbstractFunction, is EAbstractClass, is EFile, null -> { - Messages.SUBEXPRESSION_UNABLE_TO_EXTRACT.on(entry.expression) + Messages.SUBEXPRESSION_UNABLE_TO_EXTRACT.on(entry.oldExpression) return } else -> { @@ -72,21 +70,14 @@ class SubexpressionExtractor { blockExpressionIndex: Int, subexpressionExtractorEntry: SubexpressionExtractorEntry ) { - subexpressionExtractorEntry.initializerExpressions.forEach { it.parent = blockExpression } - blockExpression.statements.addAll(blockExpressionIndex, subexpressionExtractorEntry.initializerExpressions) - - val referenceExpression = EReferenceExpression( - subexpressionExtractorEntry.expression.location, - subexpressionExtractorEntry.temporaryProperty.type.copy(), - subexpressionExtractorEntry.temporaryProperty, - null - ) - subexpressionExtractorEntry.expression.replace(referenceExpression) + subexpressionExtractorEntry.extractedExpressions.forEach { it.parent = blockExpression } + blockExpression.statements.addAll(blockExpressionIndex, subexpressionExtractorEntry.extractedExpressions) + subexpressionExtractorEntry.oldExpression.replace(subexpressionExtractorEntry.newExpression) } private data class SubexpressionExtractorEntry( - val expression: EExpression, - val temporaryProperty: ETemporaryProperty, - val initializerExpressions: List + val oldExpression: EExpression, + val newExpression: EExpression, + val extractedExpressions: List ) } diff --git a/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/SubexpressionExtractorStage.kt b/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/SubexpressionExtractorStage.kt index b9c27e71c..10b5d4777 100644 --- a/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/SubexpressionExtractorStage.kt +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/transform/mid/SubexpressionExtractorStage.kt @@ -49,6 +49,7 @@ package io.verik.compiler.transform.mid import io.verik.compiler.ast.element.common.EPropertyStatement +import io.verik.compiler.ast.element.common.EReferenceExpression import io.verik.compiler.ast.element.common.ETemporaryProperty import io.verik.compiler.ast.element.sv.EStreamingExpression import io.verik.compiler.ast.property.ExpressionType @@ -81,11 +82,17 @@ object SubexpressionExtractorStage : ProjectStage() { ) val temporaryProperty = ETemporaryProperty(streamingExpression.location) temporaryProperty.init(streamingExpression.type.copy(), streamingExpressionReplacement) + val referenceExpression = EReferenceExpression( + streamingExpression.location, + temporaryProperty.type.copy(), + temporaryProperty, + null + ) val propertyStatement = EPropertyStatement( streamingExpression.location, temporaryProperty ) - subexpressionExtractor.extract(streamingExpression, temporaryProperty, listOf(propertyStatement)) + subexpressionExtractor.extract(streamingExpression, referenceExpression, listOf(propertyStatement)) } } } diff --git a/verik-compiler/src/test/kotlin/io/verik/compiler/transform/mid/CastTransformerStageTest.kt b/verik-compiler/src/test/kotlin/io/verik/compiler/transform/mid/CastTransformerStageTest.kt new file mode 100644 index 000000000..a86041f7b --- /dev/null +++ b/verik-compiler/src/test/kotlin/io/verik/compiler/transform/mid/CastTransformerStageTest.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Francis Wang + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.verik.compiler.transform.mid + +import io.verik.compiler.util.BaseTest +import io.verik.compiler.util.findStatements +import org.junit.jupiter.api.Test + +internal class CastTransformerStageTest : BaseTest() { + + @Test + fun `is expression`() { + val projectContext = driveTest( + SubexpressionExtractorStage::class, + """ + var x = false + fun f() { + x = 0 is Int + } + """.trimIndent() + ) + assertElementEquals( + """ + [ + PropertyStatement(Unit, TemporaryProperty(Int, null)), + KtBinaryExpression( + Unit, + ReferenceExpression(Boolean, x, null), + KtCallExpression( + Boolean, + ${'$'}cast, + null, + [ReferenceExpression(Int, , null), ConstantExpression(*)], + [] + ), + EQ + ) + ] + """.trimIndent(), + projectContext.findStatements("f") + ) + } +}