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/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 new file mode 100644 index 000000000..c299d2032 --- /dev/null +++ b/verik-compiler/src/main/kotlin/io/verik/compiler/ast/element/kt/EIsExpression.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.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 + +class EIsExpression( + override val location: SourceLocation, + override var expression: EExpression, + var property: EAbstractInitializedProperty, + val isNegated: Boolean, + var castType: Type +) : EAbstractContainerExpression(), DeclarationContainer { + + override var type = Core.Kt.C_Boolean.toType() + + override val serializationType = SerializationType.INTERNAL + + 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/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 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 4d4215c65..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 @@ -27,6 +27,7 @@ import io.verik.compiler.ast.element.common.ESuperExpression import io.verik.compiler.ast.element.common.EThisExpression import io.verik.compiler.ast.element.common.EWhileExpression import io.verik.compiler.ast.element.kt.EFunctionLiteralExpression +import io.verik.compiler.ast.element.kt.EIsExpression import io.verik.compiler.ast.element.kt.EKtAbstractFunction import io.verik.compiler.ast.element.kt.EKtBinaryExpression import io.verik.compiler.ast.element.kt.EKtBlockExpression @@ -55,6 +56,7 @@ object ExpressionSpecializer { is EReturnStatement -> 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,22 @@ object ExpressionSpecializer { return EStringTemplateExpression(stringTemplateExpression.location, entries) } + private fun specializeIsExpression( + isExpression: EIsExpression, + 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, + property, + isExpression.isNegated, + castType + ) + } + private fun specializeIfExpression( ifExpression: EIfExpression, specializerContext: SpecializerContext 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/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 4ac0f6c4f..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 @@ -48,9 +48,12 @@ object IfAndWhenExpressionUnlifterStage : ProjectStage() { override fun visitIfExpression(ifExpression: EIfExpression) { super.visitIfExpression(ifExpression) if (ifExpression.getExpressionType().isSubexpression()) { - val temporaryProperty = ETemporaryProperty( + val temporaryProperty = ETemporaryProperty(ifExpression.location) + temporaryProperty.init(ifExpression.type.copy(), null) + val referenceExpression = EReferenceExpression( ifExpression.location, - ifExpression.type.copy(), + temporaryProperty.type.copy(), + temporaryProperty, null ) val propertyStatement = EPropertyStatement( @@ -60,7 +63,7 @@ object IfAndWhenExpressionUnlifterStage : ProjectStage() { val ifExpressionReplacement = getIfExpressionReplacement(ifExpression, temporaryProperty) subexpressionExtractor.extract( ifExpression, - temporaryProperty, + referenceExpression, listOf(propertyStatement, ifExpressionReplacement) ) } @@ -69,9 +72,12 @@ object IfAndWhenExpressionUnlifterStage : ProjectStage() { override fun visitWhenExpression(whenExpression: EWhenExpression) { super.visitWhenExpression(whenExpression) if (whenExpression.getExpressionType().isSubexpression()) { - val temporaryProperty = ETemporaryProperty( + val temporaryProperty = ETemporaryProperty(whenExpression.location) + temporaryProperty.init(whenExpression.type.copy(), null) + val referenceExpression = EReferenceExpression( whenExpression.location, - whenExpression.type.copy(), + temporaryProperty.type.copy(), + temporaryProperty, null ) val propertyStatement = EPropertyStatement( @@ -81,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 426289818..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 @@ -79,16 +80,19 @@ object SubexpressionExtractorStage : ProjectStage() { streamingExpression.type.copy(), streamingExpression.expression ) - val temporaryProperty = ETemporaryProperty( + val temporaryProperty = ETemporaryProperty(streamingExpression.location) + temporaryProperty.init(streamingExpression.type.copy(), streamingExpressionReplacement) + val referenceExpression = EReferenceExpression( streamingExpression.location, - streamingExpression.type.copy(), - streamingExpressionReplacement + 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/cast/ExpressionCasterTest.kt b/verik-compiler/src/test/kotlin/io/verik/compiler/cast/ExpressionCasterTest.kt index 5e6a105c7..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 @@ -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(*), TemporaryProperty(Int, null), false, Int)", + projectContext.findExpression("x") + ) + } + @Test fun `if expression`() { val projectContext = driveTest( 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") + ) + } } 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") + ) + } +} 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() +}