Effects: add interpreters of ContractDescription
Interpreters convert declarative representation of contracts (ContractDescription) in internal representation convenient for usage inside compiler (Computations, Effects, etc.) ========== Effect System introduction: 3/18
This commit is contained in:
+58
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* http://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 org.jetbrains.kotlin.contracts.interpretation
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.contracts.description.*
|
||||||
|
import org.jetbrains.kotlin.contracts.description.expressions.*
|
||||||
|
import org.jetbrains.kotlin.contracts.model.ESExpression
|
||||||
|
import org.jetbrains.kotlin.contracts.model.functors.IsFunctor
|
||||||
|
import org.jetbrains.kotlin.contracts.model.structure.*
|
||||||
|
|
||||||
|
internal class ConditionInterpreter(private val dispatcher: ContractInterpretationDispatcher) : ContractDescriptionVisitor<ESExpression?, Unit> {
|
||||||
|
override fun visitLogicalOr(logicalOr: LogicalOr, data: Unit): ESExpression? {
|
||||||
|
val left = logicalOr.left.accept(this, data) ?: return null
|
||||||
|
val right = logicalOr.right.accept(this, data) ?: return null
|
||||||
|
return ESOr(left, right)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitLogicalAnd(logicalAnd: LogicalAnd, data: Unit): ESExpression? {
|
||||||
|
val left = logicalAnd.left.accept(this, data) ?: return null
|
||||||
|
val right = logicalAnd.right.accept(this, data) ?: return null
|
||||||
|
return ESAnd(left, right)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitLogicalNot(logicalNot: LogicalNot, data: Unit): ESExpression? {
|
||||||
|
val arg = logicalNot.arg.accept(this, data) ?: return null
|
||||||
|
return ESNot(arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitIsInstancePredicate(isInstancePredicate: IsInstancePredicate, data: Unit): ESExpression? {
|
||||||
|
val esVariable = dispatcher.interpretVariable(isInstancePredicate.arg) ?: return null
|
||||||
|
return ESIs(esVariable, IsFunctor(isInstancePredicate.type, isInstancePredicate.isNegated))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitIsNullPredicate(isNullPredicate: IsNullPredicate, data: Unit): ESExpression? {
|
||||||
|
val variable = dispatcher.interpretVariable(isNullPredicate.arg) ?: return null
|
||||||
|
return ESEqual(variable, ESConstant.NULL, isNullPredicate.isNegated)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitBooleanConstantDescriptor(booleanConstantDescriptor: BooleanConstantReference, data: Unit): ESExpression? =
|
||||||
|
dispatcher.interpretConstant(booleanConstantDescriptor)
|
||||||
|
|
||||||
|
override fun visitBooleanVariableReference(booleanVariableReference: BooleanVariableReference, data: Unit): ESExpression? =
|
||||||
|
dispatcher.interpretVariable(booleanVariableReference)
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* http://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 org.jetbrains.kotlin.contracts.interpretation
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.contracts.description.expressions.BooleanConstantReference
|
||||||
|
import org.jetbrains.kotlin.contracts.description.expressions.ConstantReference
|
||||||
|
import org.jetbrains.kotlin.contracts.model.structure.ESConstant
|
||||||
|
import org.jetbrains.kotlin.contracts.model.structure.lift
|
||||||
|
|
||||||
|
internal class ConstantValuesInterpreter {
|
||||||
|
fun interpretConstant(constantReference: ConstantReference): ESConstant? = when (constantReference) {
|
||||||
|
BooleanConstantReference.TRUE -> true.lift()
|
||||||
|
BooleanConstantReference.FALSE -> false.lift()
|
||||||
|
ConstantReference.NULL-> ESConstant.NULL
|
||||||
|
ConstantReference.NOT_NULL -> ESConstant.NOT_NULL
|
||||||
|
ConstantReference.WILDCARD -> ESConstant.WILDCARD
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
+71
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* http://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 org.jetbrains.kotlin.contracts.interpretation
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.contracts.description.*
|
||||||
|
import org.jetbrains.kotlin.contracts.description.expressions.ConstantReference
|
||||||
|
import org.jetbrains.kotlin.contracts.description.expressions.VariableReference
|
||||||
|
import org.jetbrains.kotlin.contracts.model.functors.SubstitutingFunctor
|
||||||
|
import org.jetbrains.kotlin.contracts.model.structure.ESConstant
|
||||||
|
import org.jetbrains.kotlin.contracts.model.structure.ESVariable
|
||||||
|
import org.jetbrains.kotlin.contracts.model.ESEffect
|
||||||
|
import org.jetbrains.kotlin.contracts.model.ESExpression
|
||||||
|
import org.jetbrains.kotlin.contracts.model.Functor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class manages conversion of [ContractDescription] to [Functor]
|
||||||
|
*/
|
||||||
|
class ContractInterpretationDispatcher {
|
||||||
|
private val constantsInterpreter = ConstantValuesInterpreter()
|
||||||
|
private val conditionInterpreter = ConditionInterpreter(this)
|
||||||
|
private val conditionalEffectInterpreter = ConditionalEffectInterpreter(this)
|
||||||
|
private val effectsInterpreters: List<EffectDeclarationInterpreter> = listOf(
|
||||||
|
ReturnsEffectInterpreter(this),
|
||||||
|
CallsEffectInterpreter(this)
|
||||||
|
)
|
||||||
|
fun resolveFunctor(functionDescriptor: FunctionDescriptor): Functor? {
|
||||||
|
val contractDescriptor = functionDescriptor.getUserData(ContractProviderKey)?.getContractDescription() ?: return null
|
||||||
|
return convertContractDescriptorToFunctor(contractDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun convertContractDescriptorToFunctor(contractDescription: ContractDescription): Functor? {
|
||||||
|
val resultingClauses = contractDescription.effects.map { effect ->
|
||||||
|
if (effect is ConditionalEffectDeclaration) {
|
||||||
|
conditionalEffectInterpreter.interpret(effect) ?: return null
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
effectsInterpreters.mapNotNull { it.tryInterpret(effect) }.singleOrNull() ?: return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SubstitutingFunctor(resultingClauses, contractDescription.ownerFunction)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun interpretEffect(effectDeclaration: EffectDeclaration): ESEffect? {
|
||||||
|
val convertedFunctors = effectsInterpreters.mapNotNull { it.tryInterpret(effectDeclaration) }
|
||||||
|
return convertedFunctors.singleOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun interpretConstant(constantReference: ConstantReference): ESConstant? =
|
||||||
|
constantsInterpreter.interpretConstant(constantReference)
|
||||||
|
|
||||||
|
internal fun interpretCondition(booleanExpression: BooleanExpression): ESExpression? =
|
||||||
|
booleanExpression.accept(conditionInterpreter, Unit)
|
||||||
|
|
||||||
|
internal fun interpretVariable(variableReference: VariableReference): ESVariable? = ESVariable(variableReference.descriptor)
|
||||||
|
}
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* http://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 org.jetbrains.kotlin.contracts.interpretation
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.contracts.description.EffectDeclaration
|
||||||
|
import org.jetbrains.kotlin.contracts.model.ESEffect
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interpreter of some effects. For most cases, each particular
|
||||||
|
* EffectDeclaration, EffectDeclarationInterpreter and ESEffect
|
||||||
|
* should be in 1-1-1 correspondence to each other and be agnostic
|
||||||
|
* about other implementations.
|
||||||
|
*/
|
||||||
|
internal interface EffectDeclarationInterpreter {
|
||||||
|
fun tryInterpret(effectDeclaration: EffectDeclaration): ESEffect?
|
||||||
|
}
|
||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* http://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 org.jetbrains.kotlin.contracts.interpretation
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.contracts.description.CallsEffectDeclaration
|
||||||
|
import org.jetbrains.kotlin.contracts.description.ConditionalEffectDeclaration
|
||||||
|
import org.jetbrains.kotlin.contracts.description.EffectDeclaration
|
||||||
|
import org.jetbrains.kotlin.contracts.description.ReturnsEffectDeclaration
|
||||||
|
import org.jetbrains.kotlin.contracts.model.ConditionalEffect
|
||||||
|
import org.jetbrains.kotlin.contracts.model.ESEffect
|
||||||
|
import org.jetbrains.kotlin.contracts.model.SimpleEffect
|
||||||
|
import org.jetbrains.kotlin.contracts.model.structure.ESCalls
|
||||||
|
import org.jetbrains.kotlin.contracts.model.structure.ESReturns
|
||||||
|
|
||||||
|
internal class CallsEffectInterpreter(private val dispatcher: ContractInterpretationDispatcher) : EffectDeclarationInterpreter {
|
||||||
|
override fun tryInterpret(effectDeclaration: EffectDeclaration): ESEffect? {
|
||||||
|
if (effectDeclaration !is CallsEffectDeclaration) return null
|
||||||
|
|
||||||
|
val variable = dispatcher.interpretVariable(effectDeclaration.variableReference) ?: return null
|
||||||
|
val kind = effectDeclaration.kind
|
||||||
|
return ESCalls(variable, kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ConditionalEffectInterpreter(private val dispatcher: ContractInterpretationDispatcher) {
|
||||||
|
fun interpret(conditionalEffectDeclaration: ConditionalEffectDeclaration): ConditionalEffect? {
|
||||||
|
val effect = dispatcher.interpretEffect(conditionalEffectDeclaration.effect) as? SimpleEffect ?: return null
|
||||||
|
val condition = dispatcher.interpretCondition(conditionalEffectDeclaration.condition) ?: return null
|
||||||
|
|
||||||
|
return ConditionalEffect(condition, effect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ReturnsEffectInterpreter(private val dispatcher: ContractInterpretationDispatcher) : EffectDeclarationInterpreter {
|
||||||
|
override fun tryInterpret(effectDeclaration: EffectDeclaration): ESEffect? {
|
||||||
|
if (effectDeclaration !is ReturnsEffectDeclaration) return null
|
||||||
|
val returnedValue = dispatcher.interpretConstant(effectDeclaration.value) ?: return null
|
||||||
|
return ESReturns(returnedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user