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.references.FirErrorNamedReference
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.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef
@@ -196,7 +197,7 @@ internal fun FirExpression.generateNotNullOrOther(
)
branches += FirWhenBranchImpl(
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(
session: FirSession,
baseExpression: KtUnaryExpression,
@@ -356,17 +382,18 @@ internal fun generateIncrementOrDecrementBlock(
}
return FirBlockImpl(session, baseExpression).apply {
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 resultInitializer = FirFunctionCallImpl(session, baseExpression).apply {
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 assignment = argument.generateAssignment(
session, baseExpression,
if (prefix && argument !is KtSimpleNameExpression)
generateAccessExpression(session, baseExpression, resultName)
generateResolvedAccessExpression(session, baseExpression, resultVar)
else
resultInitializer,
FirOperation.ASSIGN, convert
@@ -384,14 +411,14 @@ internal fun generateIncrementOrDecrementBlock(
if (argument !is KtSimpleNameExpression) {
statements += resultVar
appendAssignment()
statements += generateAccessExpression(session, baseExpression, resultName)
statements += generateResolvedAccessExpression(session, baseExpression, resultVar)
} else {
appendAssignment()
statements += generateAccessExpression(session, baseExpression, argument.getReferencedNameAsName())
}
} else {
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)
}
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(
session: FirSession,
multiDeclaration: KtDestructuringDeclaration,
@@ -418,7 +450,7 @@ internal fun generateDestructuringBlock(
statements += FirVariableImpl(
session, entry, entry.nameAsSafeName,
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?
).apply {
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 parameter = expression.loopParameter
return FirBlockImpl(session, expression).apply {
val rangeName = Name.special("<range>")
statements += generateTemporaryVariable(this@RawFirBuilder.session, expression.loopRange, rangeName, rangeExpression)
val iteratorName = Name.special("<iterator>")
statements += generateTemporaryVariable(
this@RawFirBuilder.session, expression.loopRange, iteratorName,
val rangeVal =
generateTemporaryVariable(this@RawFirBuilder.session, expression.loopRange, Name.special("<range>"), rangeExpression)
statements += rangeVal
val iteratorVal = generateTemporaryVariable(
this@RawFirBuilder.session, expression.loopRange, Name.special("<iterator>"),
FirFunctionCallImpl(this@RawFirBuilder.session, expression).apply {
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(
this@RawFirBuilder.session, expression,
FirFunctionCallImpl(this@RawFirBuilder.session, expression).apply {
calleeReference = FirSimpleNamedReference(this@RawFirBuilder.session, expression, Name.identifier("hasNext"))
explicitReceiver = generateAccessExpression(this@RawFirBuilder.session, expression, iteratorName)
explicitReceiver = generateResolvedAccessExpression(this@RawFirBuilder.session, expression, iteratorVal)
}
).configure {
// 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,
FirFunctionCallImpl(this@RawFirBuilder.session, expression).apply {
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) {
@@ -32,6 +32,6 @@ FILE: annotated.kt
}
public? final? fun bar(two: Two): kotlin/Unit {
lval <destruct>: <implicit> = two#
@Ann() lval x: <implicit> = <destruct>#.component1()
@Ann() lval y: <implicit> = <destruct>#.component2()
@Ann() lval x: <implicit> = R|<local>/<destruct>|.component1()
@Ann() lval y: <implicit> = R|<local>/<destruct>|.component2()
}
@@ -28,12 +28,12 @@ FILE: destructuring.kt
}
public? final? fun foo(some: Some): kotlin/Unit {
lval <destruct>: <implicit> = some#
lvar x: <implicit> = <destruct>#.component1()
lvar y: <implicit> = <destruct>#.component2()
lvar z: String = <destruct>#.component3()
lvar x: <implicit> = R|<local>/<destruct>|.component1()
lvar y: <implicit> = R|<local>/<destruct>|.component2()
lvar z: String = R|<local>/<destruct>|.component3()
lval <unary>: <implicit> = x#
x# = <unary>#.inc#()
<unary>#
x# = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
y# *= Double(2.0)
z# = String()
}
+14 -14
View File
@@ -1,25 +1,25 @@
FILE: for.kt
public? final? fun foo(): kotlin/Unit {
lval <range>: <implicit> = Int(1).rangeTo#(Int(10))
lval <iterator>: <implicit> = <range>#.iterator#()
while(<iterator>#.hasNext#()) {
lval i: <implicit> = <iterator>#.next#()
lval <iterator>: <implicit> = R|<local>/<range>|.iterator#()
while(R|<local>/<iterator>|.hasNext#()) {
lval i: <implicit> = R|<local>/<iterator>|.next#()
println#(i#)
}
}
public? final? fun bar(list: List<String>): kotlin/Unit {
lval <range>: <implicit> = list#.subList#(Int(0), Int(10))
lval <iterator>: <implicit> = <range>#.iterator#()
while(<iterator>#.hasNext#()) {
lval element: <implicit> = <iterator>#.next#()
lval <iterator>: <implicit> = R|<local>/<range>|.iterator#()
while(R|<local>/<iterator>|.hasNext#()) {
lval element: <implicit> = R|<local>/<iterator>|.next#()
println#(element#)
}
lval <range>: <implicit> = list#.subList#(Int(10), Int(20))
lval <iterator>: <implicit> = <range>#.iterator#()
while(<iterator>#.hasNext#()) {
lval element: <implicit> = <iterator>#.next#()
lval <iterator>: <implicit> = R|<local>/<range>|.iterator#()
while(R|<local>/<iterator>|.hasNext#()) {
lval element: <implicit> = R|<local>/<iterator>|.next#()
println#(element#)
}
@@ -46,11 +46,11 @@ FILE: for.kt
}
public? final? fun baz(set: Set<Some>): kotlin/Unit {
lval <range>: <implicit> = set#
lval <iterator>: <implicit> = <range>#.iterator#()
while(<iterator>#.hasNext#()) {
lval <destruct>: <implicit> = <iterator>#.next#()
lval x: <implicit> = <destruct>#.component1()
lval y: <implicit> = <destruct>#.component2()
lval <iterator>: <implicit> = R|<local>/<range>|.iterator#()
while(R|<local>/<iterator>|.hasNext#()) {
lval <destruct>: <implicit> = R|<local>/<iterator>|.next#()
lval x: <implicit> = R|<local>/<destruct>|.component1()
lval y: <implicit> = R|<local>/<destruct>|.component2()
println#(<strcat>(String(x = ), x#, String( y = ), y#))
}
@@ -30,8 +30,8 @@ FILE: lambda.kt
}
use#(<L> = use@fun <implicit>.<anonymous>(<destruct>: <implicit>): <implicit> {
lval x: <implicit> = <destruct>#.component1()
lval y: <implicit> = <destruct>#.component2()
lval x: <implicit> = R|<local>/<destruct>|.component1()
lval y: <implicit> = R|<local>/<destruct>|.component2()
x#.plus#(y#)
}
)
@@ -5,7 +5,7 @@ FILE: nullability.kt
Int(42)
}
else -> {
<elvis>#
R|<local>/<elvis>|
}
}
@@ -16,7 +16,7 @@ FILE: nullability.kt
throw KotlinNullPointerException#()
}
else -> {
<bangbang>#
R|<local>/<bangbang>|
}
}
@@ -3,26 +3,26 @@ FILE: unary.kt
lvar x: <implicit> = Int(0)
lval x1: <implicit> = {
lval <unary>: <implicit> = x#
x# = <unary>#.inc#()
<unary>#
x# = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
}
lval x2: <implicit> = {
lval <unary>: <implicit> = x#
x# = <unary>#.inc#()
x# = R|<local>/<unary>|.inc#()
x#
}
lval x3: <implicit> = {
lval <unary>: <implicit> = x#
x# = <unary>#.dec#()
x# = R|<local>/<unary>|.dec#()
x#
}
lval x4: <implicit> = {
lval <unary>: <implicit> = x#
x# = <unary>#.dec#()
<unary>#
x# = R|<local>/<unary>|.dec#()
R|<local>/<unary>|
}
when () {
@@ -46,30 +46,30 @@ FILE: unary.kt
public? final? fun test2(x: X): kotlin/Unit {
lval x1: <implicit> = {
lval <unary>: <implicit> = x#.i#
x#.i# = <unary>#.inc#()
<unary>#
x#.i# = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
}
lval x2: <implicit> = {
lval <unary>: <implicit> = x#.i#
lval <unary-result>: <implicit> = <unary>#.inc#()
x#.i# = <unary-result>#
<unary-result>#
lval <unary-result>: <implicit> = R|<local>/<unary>|.inc#()
x#.i# = R|<local>/<unary-result>|
R|<local>/<unary-result>|
}
}
public? final? fun test3(arr: Array<Int>): kotlin/Unit {
lval x1: <implicit> = {
lval <unary>: <implicit> = arr#.get#(Int(0))
arr#.set#(Int(0), <unary>#.inc#())
<unary>#
arr#.set#(Int(0), R|<local>/<unary>|.inc#())
R|<local>/<unary>|
}
lval x2: <implicit> = {
lval <unary>: <implicit> = arr#.get#(Int(1))
lval <unary-result>: <implicit> = <unary>#.inc#()
arr#.set#(Int(1), <unary-result>#)
<unary-result>#
lval <unary-result>: <implicit> = R|<local>/<unary>|.inc#()
arr#.set#(Int(1), R|<local>/<unary-result>|)
R|<local>/<unary-result>|
}
}
@@ -85,15 +85,15 @@ FILE: unary.kt
public? final? fun test4(y: Y): kotlin/Unit {
lval x1: <implicit> = {
lval <unary>: <implicit> = y#.arr#.get#(Int(0))
y#.arr#.set#(Int(0), <unary>#.inc#())
<unary>#
y#.arr#.set#(Int(0), R|<local>/<unary>|.inc#())
R|<local>/<unary>|
}
lval x2: <implicit> = {
lval <unary>: <implicit> = y#.arr#.get#(Int(1))
lval <unary-result>: <implicit> = <unary>#.inc#()
y#.arr#.set#(Int(1), <unary-result>#)
<unary-result>#
lval <unary-result>: <implicit> = R|<local>/<unary>|.inc#()
y#.arr#.set#(Int(1), R|<local>/<unary-result>|)
R|<local>/<unary-result>|
}
}
@@ -3,13 +3,13 @@ FILE: while.kt
lvar k: <implicit> = Int(0)
some@while(<(k#, limit#)) {
lval <unary>: <implicit> = k#
k# = <unary>#.inc#()
<unary>#
k# = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
println#(k#)
while(==(k#, Int(13))) {
lval <unary>: <implicit> = k#
k# = <unary>#.inc#()
<unary>#
k# = R|<local>/<unary>|.inc#()
R|<local>/<unary>|
when () {
<(k#, limit#) -> {
break@@@[<(k#, limit#)]
@@ -35,8 +35,8 @@ FILE: while.kt
lvar k: <implicit> = limit#
do {
lval <unary>: <implicit> = k#
k# = <unary>#.dec#()
<unary>#
k# = R|<local>/<unary>|.dec#()
R|<local>/<unary>|
println#(k#)
}
while(>=(k#, Int(0)))