Generate get/set for local delegated properties as accessor calls.
This commit is contained in:
committed by
Dmitry Petrov
parent
f2e778d2d0
commit
8b95992af1
+1
-1
@@ -114,7 +114,7 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
||||
BackingFieldLValue(ktLeft.startOffset, ktLeft.endOffset, descriptor.propertyDescriptor, operator)
|
||||
is LocalVariableDescriptor ->
|
||||
if (descriptor.isDelegated)
|
||||
TODO("Delegated local variable")
|
||||
DelegatedLocalPropertyLValue(ktLeft.startOffset, ktLeft.endOffset, descriptor, operator)
|
||||
else
|
||||
VariableLValue(ktLeft.startOffset, ktLeft.endOffset, descriptor, operator)
|
||||
is PropertyDescriptor ->
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.psi2ir.generators
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
@@ -35,7 +36,7 @@ class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorE
|
||||
generatePropertyGetterCall(descriptor, startOffset, endOffset, call)
|
||||
is VariableDescriptor ->
|
||||
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
IrGetVariableImpl(startOffset, endOffset, descriptor, operator)
|
||||
generateGetVariable(startOffset, endOffset, descriptor, operator)
|
||||
}
|
||||
is FunctionDescriptor ->
|
||||
generateFunctionCall(descriptor, startOffset, endOffset, operator, call)
|
||||
@@ -44,6 +45,12 @@ class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorE
|
||||
}
|
||||
}
|
||||
|
||||
fun generateGetVariable(startOffset: Int, endOffset: Int, descriptor: VariableDescriptor, operator: IrOperator? = null) =
|
||||
if (descriptor is LocalVariableDescriptor && descriptor.isDelegated)
|
||||
IrCallImpl(startOffset, endOffset, descriptor.type, descriptor.getter!!, operator ?: IrOperator.GET_LOCAL_PROPERTY)
|
||||
else
|
||||
IrGetVariableImpl(startOffset, endOffset, descriptor, operator)
|
||||
|
||||
fun generateDelegatingConstructorCall(startOffset: Int, endOffset: Int, call: CallBuilder) : IrExpression {
|
||||
val descriptor = call.descriptor
|
||||
if (descriptor !is ConstructorDescriptor) throw AssertionError("Constructor expected: $descriptor")
|
||||
|
||||
+1
-1
@@ -255,7 +255,7 @@ class StatementGenerator(
|
||||
CallGenerator(this).generateCall(expression.startOffset, expression.endOffset, pregenerateCall(resolvedCall))
|
||||
}
|
||||
is VariableDescriptor ->
|
||||
IrGetVariableImpl(expression.startOffset, expression.endOffset, descriptor)
|
||||
CallGenerator(this).generateGetVariable(expression.startOffset, expression.endOffset, descriptor)
|
||||
else ->
|
||||
IrDummyExpression(
|
||||
expression.startOffset, expression.endOffset, getInferredTypeWithImplicitCastsOrFail(expression),
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.psi2ir.intermediate
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrOperator
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
class DelegatedLocalPropertyLValue(
|
||||
val startOffset: Int,
|
||||
val endOffset: Int,
|
||||
val descriptor: VariableDescriptorWithAccessors,
|
||||
val irOperator: IrOperator? = null
|
||||
) : LValue, AssignmentReceiver {
|
||||
override val type: KotlinType get() = descriptor.type
|
||||
|
||||
override fun load(): IrExpression =
|
||||
IrCallImpl(startOffset, endOffset, descriptor.type, descriptor.getter!!, irOperator)
|
||||
|
||||
override fun store(irExpression: IrExpression): IrExpression =
|
||||
IrCallImpl(startOffset, endOffset, descriptor.type, descriptor.setter!!, irOperator).apply {
|
||||
putArgument(0, irExpression)
|
||||
}
|
||||
|
||||
override fun assign(withLValue: (LValue) -> IrExpression): IrExpression =
|
||||
withLValue(this)
|
||||
}
|
||||
@@ -72,6 +72,7 @@ interface IrOperator {
|
||||
object DESTRUCTURING_DECLARATION : IrOperatorImpl("DESTRUCTURING_DECLARATION")
|
||||
|
||||
object GET_PROPERTY : IrOperatorImpl("GET_PROPERTY")
|
||||
object GET_LOCAL_PROPERTY : IrOperatorImpl("GET_LOCAL_PROPERTY")
|
||||
|
||||
object IF : IrOperatorImpl("IF")
|
||||
object WHEN : IrOperatorImpl("WHEN")
|
||||
|
||||
@@ -69,6 +69,12 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
|
||||
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer, data: Nothing?): String =
|
||||
"ANONYMOUS_INITIALIZER ${declaration.descriptor.name}"
|
||||
|
||||
override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty, data: Nothing?): String =
|
||||
"LOCAL_DELEGATED_PROPERTY ${declaration.descriptor.render()}"
|
||||
|
||||
override fun visitLocalPropertyAccessor(declaration: IrLocalPropertyAccessor, data: Nothing?): String =
|
||||
"LOCAL_PROPERTY_ACCESSOR ${declaration.descriptor.name}" // can't render, see nullability for modality
|
||||
|
||||
override fun visitExpressionBody(body: IrExpressionBody, data: Nothing?): String =
|
||||
"EXPRESSION_BODY"
|
||||
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
fun test1() {
|
||||
val x by lazy { 42 }
|
||||
println(x)
|
||||
}
|
||||
|
||||
fun test2() {
|
||||
var x by hashMapOf<String, Int>()
|
||||
x = 0
|
||||
x++
|
||||
x += 1
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
FILE /localDelegatedProperties.kt
|
||||
FUN public fun test1(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
? IrLocalDelegatedPropertyImpl x
|
||||
LOCAL_DELEGATED_PROPERTY val x: kotlin.Int
|
||||
VAR val `x$delegate`: kotlin.Lazy<kotlin.Int>
|
||||
CALL .lazy type=kotlin.Lazy<kotlin.Int> operator=null
|
||||
initializer: BLOCK type=() -> kotlin.Int operator=LAMBDA
|
||||
@@ -10,7 +10,7 @@ FILE /localDelegatedProperties.kt
|
||||
RETURN type=kotlin.Nothing from=<anonymous>
|
||||
CONST Int type=kotlin.Int value='42'
|
||||
CALLABLE_REFERENCE local final fun <anonymous>(): kotlin.Int type=() -> kotlin.Int
|
||||
? IrLocalPropertyAccessorImpl <get-x>
|
||||
LOCAL_PROPERTY_ACCESSOR <get-x>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=<get-x>
|
||||
CALL .getValue type=kotlin.Int operator=null
|
||||
@@ -18,4 +18,38 @@ FILE /localDelegatedProperties.kt
|
||||
thisRef: CONST Null type=kotlin.Nothing? value='null'
|
||||
property: CALLABLE_REFERENCE val x: kotlin.Int type=kotlin.reflect.KProperty0<kotlin.Int>
|
||||
CALL .println type=kotlin.Unit operator=null
|
||||
message: GET_VAR x type=kotlin.Int operator=null
|
||||
message: CALL .<get-x> type=kotlin.Int operator=GET_LOCAL_PROPERTY
|
||||
FUN public fun test2(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
LOCAL_DELEGATED_PROPERTY var x: kotlin.Int
|
||||
VAR val `x$delegate`: java.util.HashMap<kotlin.String, kotlin.Int>
|
||||
CALL .hashMapOf type=java.util.HashMap<kotlin.String, kotlin.Int> operator=null
|
||||
LOCAL_PROPERTY_ACCESSOR <get-x>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=<get-x>
|
||||
CALL .getValue type=kotlin.Int operator=null
|
||||
$receiver: GET_VAR x$delegate type=java.util.HashMap<kotlin.String, kotlin.Int> operator=null
|
||||
thisRef: CONST Null type=kotlin.Nothing? value='null'
|
||||
property: CALLABLE_REFERENCE var x: kotlin.Int type=kotlin.reflect.KMutableProperty0<kotlin.Int>
|
||||
LOCAL_PROPERTY_ACCESSOR <set-x>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=<set-x>
|
||||
TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.Int
|
||||
CALL .setValue type=kotlin.Unit operator=null
|
||||
$receiver: GET_VAR x$delegate type=java.util.HashMap<kotlin.String, kotlin.Int> operator=null
|
||||
thisRef: CONST Null type=kotlin.Nothing? value='null'
|
||||
property: CALLABLE_REFERENCE var x: kotlin.Int type=kotlin.reflect.KMutableProperty0<kotlin.Int>
|
||||
value: GET_VAR value type=kotlin.Int operator=null
|
||||
CALL .<set-x> type=kotlin.Int operator=EQ
|
||||
value: CONST Int type=kotlin.Int value='0'
|
||||
BLOCK type=kotlin.Int operator=POSTFIX_INCR
|
||||
VAR val tmp0: kotlin.Int
|
||||
CALL .<get-x> type=kotlin.Int operator=POSTFIX_INCR
|
||||
CALL .<set-x> type=kotlin.Int operator=POSTFIX_INCR
|
||||
value: CALL .inc type=kotlin.Int operator=POSTFIX_INCR
|
||||
$this: GET_VAR tmp0 type=kotlin.Int operator=null
|
||||
GET_VAR tmp0 type=kotlin.Int operator=null
|
||||
CALL .<set-x> type=kotlin.Int operator=PLUSEQ
|
||||
value: CALL .plus type=kotlin.Int operator=PLUSEQ
|
||||
$this: CALL .<get-x> type=kotlin.Int operator=PLUSEQ
|
||||
other: CONST Int type=kotlin.Int value='1'
|
||||
|
||||
Reference in New Issue
Block a user