Raw FIR: create resolved references for desugared temporary variables

This commit is contained in:
Simon Ogorodnik
2019-04-25 15:50:33 +03:00
committed by Mikhail Glukhikh
parent 99994e6c41
commit 458080ca8b
9 changed files with 100 additions and 67 deletions
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.* import org.jetbrains.kotlin.fir.expressions.impl.*
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirExplicitThisReference import org.jetbrains.kotlin.fir.references.FirExplicitThisReference
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
@@ -196,7 +197,7 @@ internal fun FirExpression.generateNotNullOrOther(
) )
branches += FirWhenBranchImpl( branches += FirWhenBranchImpl(
session, other.psi, FirElseIfTrueCondition(session, psi), session, other.psi, FirElseIfTrueCondition(session, psi),
FirSingleExpressionBlock(session, generateAccessExpression(session, psi, subjectName)) FirSingleExpressionBlock(session, generateResolvedAccessExpression(session, psi, subjectVariable))
) )
} }
} }
@@ -343,6 +344,31 @@ internal fun FirExpression.generateContainsOperation(
} }
} }
/**
* given:
* argument++
*
* result:
* {
* val <unary> = argument
* argument = <unary>.inc()
* ^<unary>
* }
*
* given:
* ++argument
*
* result:
* {
* val <unary> = argument
* argument = <unary>.inc()
* ^argument
* }
*
*/
// TODO: Refactor, support receiver capturing in case of a.b
internal fun generateIncrementOrDecrementBlock( internal fun generateIncrementOrDecrementBlock(
session: FirSession, session: FirSession,
baseExpression: KtUnaryExpression, baseExpression: KtUnaryExpression,
@@ -356,17 +382,18 @@ internal fun generateIncrementOrDecrementBlock(
} }
return FirBlockImpl(session, baseExpression).apply { return FirBlockImpl(session, baseExpression).apply {
val tempName = Name.special("<unary>") val tempName = Name.special("<unary>")
statements += generateTemporaryVariable(session, baseExpression, tempName, argument.convert()) val temporaryVariable = generateTemporaryVariable(session, baseExpression, tempName, argument.convert())
statements += temporaryVariable
val resultName = Name.special("<unary-result>") val resultName = Name.special("<unary-result>")
val resultInitializer = FirFunctionCallImpl(session, baseExpression).apply { val resultInitializer = FirFunctionCallImpl(session, baseExpression).apply {
this.calleeReference = FirSimpleNamedReference(session, baseExpression.operationReference, callName) this.calleeReference = FirSimpleNamedReference(session, baseExpression.operationReference, callName)
this.explicitReceiver = generateAccessExpression(session, baseExpression, tempName) this.explicitReceiver = generateResolvedAccessExpression(session, baseExpression, temporaryVariable)
} }
val resultVar = generateTemporaryVariable(session, baseExpression, resultName, resultInitializer) val resultVar = generateTemporaryVariable(session, baseExpression, resultName, resultInitializer)
val assignment = argument.generateAssignment( val assignment = argument.generateAssignment(
session, baseExpression, session, baseExpression,
if (prefix && argument !is KtSimpleNameExpression) if (prefix && argument !is KtSimpleNameExpression)
generateAccessExpression(session, baseExpression, resultName) generateResolvedAccessExpression(session, baseExpression, resultVar)
else else
resultInitializer, resultInitializer,
FirOperation.ASSIGN, convert FirOperation.ASSIGN, convert
@@ -384,14 +411,14 @@ internal fun generateIncrementOrDecrementBlock(
if (argument !is KtSimpleNameExpression) { if (argument !is KtSimpleNameExpression) {
statements += resultVar statements += resultVar
appendAssignment() appendAssignment()
statements += generateAccessExpression(session, baseExpression, resultName) statements += generateResolvedAccessExpression(session, baseExpression, resultVar)
} else { } else {
appendAssignment() appendAssignment()
statements += generateAccessExpression(session, baseExpression, argument.getReferencedNameAsName()) statements += generateAccessExpression(session, baseExpression, argument.getReferencedNameAsName())
} }
} else { } else {
appendAssignment() appendAssignment()
statements += generateAccessExpression(session, baseExpression, tempName) statements += generateResolvedAccessExpression(session, baseExpression, temporaryVariable)
} }
} }
} }
@@ -401,6 +428,11 @@ internal fun generateAccessExpression(session: FirSession, psi: PsiElement?, nam
calleeReference = FirSimpleNamedReference(session, psi, name) calleeReference = FirSimpleNamedReference(session, psi, name)
} }
internal fun generateResolvedAccessExpression(session: FirSession, psi: PsiElement?, variable: FirVariable): FirQualifiedAccessExpression =
FirQualifiedAccessExpressionImpl(session, psi).apply {
calleeReference = FirResolvedCallableReferenceImpl(session, psi, variable.name, variable.symbol)
}
internal fun generateDestructuringBlock( internal fun generateDestructuringBlock(
session: FirSession, session: FirSession,
multiDeclaration: KtDestructuringDeclaration, multiDeclaration: KtDestructuringDeclaration,
@@ -418,7 +450,7 @@ internal fun generateDestructuringBlock(
statements += FirVariableImpl( statements += FirVariableImpl(
session, entry, entry.nameAsSafeName, session, entry, entry.nameAsSafeName,
entry.typeReference.toFirOrImplicitTypeRef(), isVar, entry.typeReference.toFirOrImplicitTypeRef(), isVar,
FirComponentCallImpl(session, entry, index + 1, generateAccessExpression(session, entry, container.name)), FirComponentCallImpl(session, entry, index + 1, generateResolvedAccessExpression(session, entry, container)),
FirVariableSymbol(entry.nameAsSafeName) // TODO? FirVariableSymbol(entry.nameAsSafeName) // TODO?
).apply { ).apply {
entry.extractAnnotationsTo(this) entry.extractAnnotationsTo(this)
@@ -1091,21 +1091,22 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
val rangeExpression = expression.loopRange.toFirExpression("No range in for loop") val rangeExpression = expression.loopRange.toFirExpression("No range in for loop")
val parameter = expression.loopParameter val parameter = expression.loopParameter
return FirBlockImpl(session, expression).apply { return FirBlockImpl(session, expression).apply {
val rangeName = Name.special("<range>") val rangeVal =
statements += generateTemporaryVariable(this@RawFirBuilder.session, expression.loopRange, rangeName, rangeExpression) generateTemporaryVariable(this@RawFirBuilder.session, expression.loopRange, Name.special("<range>"), rangeExpression)
val iteratorName = Name.special("<iterator>") statements += rangeVal
statements += generateTemporaryVariable( val iteratorVal = generateTemporaryVariable(
this@RawFirBuilder.session, expression.loopRange, iteratorName, this@RawFirBuilder.session, expression.loopRange, Name.special("<iterator>"),
FirFunctionCallImpl(this@RawFirBuilder.session, expression).apply { FirFunctionCallImpl(this@RawFirBuilder.session, expression).apply {
calleeReference = FirSimpleNamedReference(this@RawFirBuilder.session, expression, Name.identifier("iterator")) calleeReference = FirSimpleNamedReference(this@RawFirBuilder.session, expression, Name.identifier("iterator"))
explicitReceiver = generateAccessExpression(this@RawFirBuilder.session, expression.loopRange, rangeName) explicitReceiver = generateResolvedAccessExpression(this@RawFirBuilder.session, expression.loopRange, rangeVal)
} }
) )
statements += iteratorVal
statements += FirWhileLoopImpl( statements += FirWhileLoopImpl(
this@RawFirBuilder.session, expression, this@RawFirBuilder.session, expression,
FirFunctionCallImpl(this@RawFirBuilder.session, expression).apply { FirFunctionCallImpl(this@RawFirBuilder.session, expression).apply {
calleeReference = FirSimpleNamedReference(this@RawFirBuilder.session, expression, Name.identifier("hasNext")) calleeReference = FirSimpleNamedReference(this@RawFirBuilder.session, expression, Name.identifier("hasNext"))
explicitReceiver = generateAccessExpression(this@RawFirBuilder.session, expression, iteratorName) explicitReceiver = generateResolvedAccessExpression(this@RawFirBuilder.session, expression, iteratorVal)
} }
).configure { ).configure {
// NB: just body.toFirBlock() isn't acceptable here because we need to add some statements // NB: just body.toFirBlock() isn't acceptable here because we need to add some statements
@@ -1121,7 +1122,7 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
if (multiDeclaration != null) Name.special("<destruct>") else parameter.nameAsSafeName, if (multiDeclaration != null) Name.special("<destruct>") else parameter.nameAsSafeName,
FirFunctionCallImpl(this@RawFirBuilder.session, expression).apply { FirFunctionCallImpl(this@RawFirBuilder.session, expression).apply {
calleeReference = FirSimpleNamedReference(this@RawFirBuilder.session, expression, Name.identifier("next")) calleeReference = FirSimpleNamedReference(this@RawFirBuilder.session, expression, Name.identifier("next"))
explicitReceiver = generateAccessExpression(this@RawFirBuilder.session, expression, iteratorName) explicitReceiver = generateResolvedAccessExpression(this@RawFirBuilder.session, expression, iteratorVal)
} }
) )
if (multiDeclaration != null) { if (multiDeclaration != null) {
@@ -32,6 +32,6 @@ FILE: annotated.kt
} }
public? final? fun bar(two: Two): kotlin/Unit { public? final? fun bar(two: Two): kotlin/Unit {
lval <destruct>: <implicit> = two# lval <destruct>: <implicit> = two#
@Ann() lval x: <implicit> = <destruct>#.component1() @Ann() lval x: <implicit> = R|<local>/<destruct>|.component1()
@Ann() lval y: <implicit> = <destruct>#.component2() @Ann() lval y: <implicit> = R|<local>/<destruct>|.component2()
} }
@@ -28,12 +28,12 @@ FILE: destructuring.kt
} }
public? final? fun foo(some: Some): kotlin/Unit { public? final? fun foo(some: Some): kotlin/Unit {
lval <destruct>: <implicit> = some# lval <destruct>: <implicit> = some#
lvar x: <implicit> = <destruct>#.component1() lvar x: <implicit> = R|<local>/<destruct>|.component1()
lvar y: <implicit> = <destruct>#.component2() lvar y: <implicit> = R|<local>/<destruct>|.component2()
lvar z: String = <destruct>#.component3() lvar z: String = R|<local>/<destruct>|.component3()
lval <unary>: <implicit> = x# lval <unary>: <implicit> = x#
x# = <unary>#.inc#() x# = R|<local>/<unary>|.inc#()
<unary># R|<local>/<unary>|
y# *= Double(2.0) y# *= Double(2.0)
z# = String() z# = String()
} }
+14 -14
View File
@@ -1,25 +1,25 @@
FILE: for.kt FILE: for.kt
public? final? fun foo(): kotlin/Unit { public? final? fun foo(): kotlin/Unit {
lval <range>: <implicit> = Int(1).rangeTo#(Int(10)) lval <range>: <implicit> = Int(1).rangeTo#(Int(10))
lval <iterator>: <implicit> = <range>#.iterator#() lval <iterator>: <implicit> = R|<local>/<range>|.iterator#()
while(<iterator>#.hasNext#()) { while(R|<local>/<iterator>|.hasNext#()) {
lval i: <implicit> = <iterator>#.next#() lval i: <implicit> = R|<local>/<iterator>|.next#()
println#(i#) println#(i#)
} }
} }
public? final? fun bar(list: List<String>): kotlin/Unit { public? final? fun bar(list: List<String>): kotlin/Unit {
lval <range>: <implicit> = list#.subList#(Int(0), Int(10)) lval <range>: <implicit> = list#.subList#(Int(0), Int(10))
lval <iterator>: <implicit> = <range>#.iterator#() lval <iterator>: <implicit> = R|<local>/<range>|.iterator#()
while(<iterator>#.hasNext#()) { while(R|<local>/<iterator>|.hasNext#()) {
lval element: <implicit> = <iterator>#.next#() lval element: <implicit> = R|<local>/<iterator>|.next#()
println#(element#) println#(element#)
} }
lval <range>: <implicit> = list#.subList#(Int(10), Int(20)) lval <range>: <implicit> = list#.subList#(Int(10), Int(20))
lval <iterator>: <implicit> = <range>#.iterator#() lval <iterator>: <implicit> = R|<local>/<range>|.iterator#()
while(<iterator>#.hasNext#()) { while(R|<local>/<iterator>|.hasNext#()) {
lval element: <implicit> = <iterator>#.next#() lval element: <implicit> = R|<local>/<iterator>|.next#()
println#(element#) println#(element#)
} }
@@ -46,11 +46,11 @@ FILE: for.kt
} }
public? final? fun baz(set: Set<Some>): kotlin/Unit { public? final? fun baz(set: Set<Some>): kotlin/Unit {
lval <range>: <implicit> = set# lval <range>: <implicit> = set#
lval <iterator>: <implicit> = <range>#.iterator#() lval <iterator>: <implicit> = R|<local>/<range>|.iterator#()
while(<iterator>#.hasNext#()) { while(R|<local>/<iterator>|.hasNext#()) {
lval <destruct>: <implicit> = <iterator>#.next#() lval <destruct>: <implicit> = R|<local>/<iterator>|.next#()
lval x: <implicit> = <destruct>#.component1() lval x: <implicit> = R|<local>/<destruct>|.component1()
lval y: <implicit> = <destruct>#.component2() lval y: <implicit> = R|<local>/<destruct>|.component2()
println#(<strcat>(String(x = ), x#, String( y = ), y#)) println#(<strcat>(String(x = ), x#, String( y = ), y#))
} }
@@ -30,8 +30,8 @@ FILE: lambda.kt
} }
use#(<L> = use@fun <implicit>.<anonymous>(<destruct>: <implicit>): <implicit> { use#(<L> = use@fun <implicit>.<anonymous>(<destruct>: <implicit>): <implicit> {
lval x: <implicit> = <destruct>#.component1() lval x: <implicit> = R|<local>/<destruct>|.component1()
lval y: <implicit> = <destruct>#.component2() lval y: <implicit> = R|<local>/<destruct>|.component2()
x#.plus#(y#) x#.plus#(y#)
} }
) )
@@ -5,7 +5,7 @@ FILE: nullability.kt
Int(42) Int(42)
} }
else -> { else -> {
<elvis># R|<local>/<elvis>|
} }
} }
@@ -16,7 +16,7 @@ FILE: nullability.kt
throw KotlinNullPointerException#() throw KotlinNullPointerException#()
} }
else -> { else -> {
<bangbang># R|<local>/<bangbang>|
} }
} }
@@ -3,26 +3,26 @@ FILE: unary.kt
lvar x: <implicit> = Int(0) lvar x: <implicit> = Int(0)
lval x1: <implicit> = { lval x1: <implicit> = {
lval <unary>: <implicit> = x# lval <unary>: <implicit> = x#
x# = <unary>#.inc#() x# = R|<local>/<unary>|.inc#()
<unary># R|<local>/<unary>|
} }
lval x2: <implicit> = { lval x2: <implicit> = {
lval <unary>: <implicit> = x# lval <unary>: <implicit> = x#
x# = <unary>#.inc#() x# = R|<local>/<unary>|.inc#()
x# x#
} }
lval x3: <implicit> = { lval x3: <implicit> = {
lval <unary>: <implicit> = x# lval <unary>: <implicit> = x#
x# = <unary>#.dec#() x# = R|<local>/<unary>|.dec#()
x# x#
} }
lval x4: <implicit> = { lval x4: <implicit> = {
lval <unary>: <implicit> = x# lval <unary>: <implicit> = x#
x# = <unary>#.dec#() x# = R|<local>/<unary>|.dec#()
<unary># R|<local>/<unary>|
} }
when () { when () {
@@ -46,30 +46,30 @@ FILE: unary.kt
public? final? fun test2(x: X): kotlin/Unit { public? final? fun test2(x: X): kotlin/Unit {
lval x1: <implicit> = { lval x1: <implicit> = {
lval <unary>: <implicit> = x#.i# lval <unary>: <implicit> = x#.i#
x#.i# = <unary>#.inc#() x#.i# = R|<local>/<unary>|.inc#()
<unary># R|<local>/<unary>|
} }
lval x2: <implicit> = { lval x2: <implicit> = {
lval <unary>: <implicit> = x#.i# lval <unary>: <implicit> = x#.i#
lval <unary-result>: <implicit> = <unary>#.inc#() lval <unary-result>: <implicit> = R|<local>/<unary>|.inc#()
x#.i# = <unary-result># x#.i# = R|<local>/<unary-result>|
<unary-result># R|<local>/<unary-result>|
} }
} }
public? final? fun test3(arr: Array<Int>): kotlin/Unit { public? final? fun test3(arr: Array<Int>): kotlin/Unit {
lval x1: <implicit> = { lval x1: <implicit> = {
lval <unary>: <implicit> = arr#.get#(Int(0)) lval <unary>: <implicit> = arr#.get#(Int(0))
arr#.set#(Int(0), <unary>#.inc#()) arr#.set#(Int(0), R|<local>/<unary>|.inc#())
<unary># R|<local>/<unary>|
} }
lval x2: <implicit> = { lval x2: <implicit> = {
lval <unary>: <implicit> = arr#.get#(Int(1)) lval <unary>: <implicit> = arr#.get#(Int(1))
lval <unary-result>: <implicit> = <unary>#.inc#() lval <unary-result>: <implicit> = R|<local>/<unary>|.inc#()
arr#.set#(Int(1), <unary-result>#) arr#.set#(Int(1), R|<local>/<unary-result>|)
<unary-result># R|<local>/<unary-result>|
} }
} }
@@ -85,15 +85,15 @@ FILE: unary.kt
public? final? fun test4(y: Y): kotlin/Unit { public? final? fun test4(y: Y): kotlin/Unit {
lval x1: <implicit> = { lval x1: <implicit> = {
lval <unary>: <implicit> = y#.arr#.get#(Int(0)) lval <unary>: <implicit> = y#.arr#.get#(Int(0))
y#.arr#.set#(Int(0), <unary>#.inc#()) y#.arr#.set#(Int(0), R|<local>/<unary>|.inc#())
<unary># R|<local>/<unary>|
} }
lval x2: <implicit> = { lval x2: <implicit> = {
lval <unary>: <implicit> = y#.arr#.get#(Int(1)) lval <unary>: <implicit> = y#.arr#.get#(Int(1))
lval <unary-result>: <implicit> = <unary>#.inc#() lval <unary-result>: <implicit> = R|<local>/<unary>|.inc#()
y#.arr#.set#(Int(1), <unary-result>#) y#.arr#.set#(Int(1), R|<local>/<unary-result>|)
<unary-result># R|<local>/<unary-result>|
} }
} }
@@ -3,13 +3,13 @@ FILE: while.kt
lvar k: <implicit> = Int(0) lvar k: <implicit> = Int(0)
some@while(<(k#, limit#)) { some@while(<(k#, limit#)) {
lval <unary>: <implicit> = k# lval <unary>: <implicit> = k#
k# = <unary>#.inc#() k# = R|<local>/<unary>|.inc#()
<unary># R|<local>/<unary>|
println#(k#) println#(k#)
while(==(k#, Int(13))) { while(==(k#, Int(13))) {
lval <unary>: <implicit> = k# lval <unary>: <implicit> = k#
k# = <unary>#.inc#() k# = R|<local>/<unary>|.inc#()
<unary># R|<local>/<unary>|
when () { when () {
<(k#, limit#) -> { <(k#, limit#) -> {
break@@@[<(k#, limit#)] break@@@[<(k#, limit#)]
@@ -35,8 +35,8 @@ FILE: while.kt
lvar k: <implicit> = limit# lvar k: <implicit> = limit#
do { do {
lval <unary>: <implicit> = k# lval <unary>: <implicit> = k#
k# = <unary>#.dec#() k# = R|<local>/<unary>|.dec#()
<unary># R|<local>/<unary>|
println#(k#) println#(k#)
} }
while(>=(k#, Int(0))) while(>=(k#, Int(0)))