FIR: Extract putIncrementOrDecrementStatements

This commit is contained in:
Denis.Zharkov
2022-01-19 19:14:30 +03:00
parent 32ba136366
commit 0dd5042e62
@@ -516,38 +516,16 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
val desugaredSource = baseSource?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement) val desugaredSource = baseSource?.fakeElement(KtFakeSourceElementKind.DesugaredIncrementOrDecrement)
source = desugaredSource source = desugaredSource
// initialValueVar is only used for postfix increment/decrement (stores the argument value before increment/decrement). val convertedReceiver = unwrappedReceiver.convert()
val initialValueVar = generateTemporaryVariable(
baseModuleData, putIncrementOrDecrementStatements(
convertedReceiver,
operationReference,
callName,
prefix,
unwrappedReceiver.takeIf { it.elementType == REFERENCE_EXPRESSION }?.getReferencedNameAsName(),
desugaredSource, desugaredSource,
SpecialNames.UNARY, ) { resultInitializer: FirExpression, resultVar: FirVariable ->
unwrappedReceiver.convert()
)
// resultInitializer is the expression for `argument.inc()`
val resultInitializer = buildFunctionCall {
source = desugaredSource
calleeReference = buildSimpleNamedReference {
source = operationReference?.toFirSourceElement()
name = callName
}
explicitReceiver = if (prefix) {
unwrappedReceiver.convert()
} else {
generateResolvedAccessExpression(desugaredSource, initialValueVar)
}
origin = FirFunctionCallOrigin.Operator
}
// resultVar is only used for prefix increment/decrement.
val resultVar = generateTemporaryVariable(
baseModuleData,
desugaredSource,
Name.special("<unary-result>"),
resultInitializer
)
fun appendAssignment() {
val assignment = unwrappedReceiver.generateAssignment( val assignment = unwrappedReceiver.generateAssignment(
desugaredSource, desugaredSource,
null, null,
@@ -567,23 +545,89 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
statements += assignment statements += assignment
} }
} }
}
}
/**
* given:
* receiver++
*
* result:
* {
* val <unary> = receiver
* val resultVar = <unary>.inc()
* appendAssignment(resultVar)
* ^<unary>
* }
*
* given:
* ++receiver
*
* result:
* {
* val <unary-result> = receiver.inc()
* val resultVar = <unary-result>
* appendAssignment(resultVar)
* ^<unary-result>
* }
*
*/
private fun FirBlockBuilder.putIncrementOrDecrementStatements(
receiver: FirExpression,
operationReference: T?,
callName: Name, // 'inc' or 'dec'
prefix: Boolean,
nameIfSimpleReference: Name?, // 'b' if whole expression is simple `b++` or `a.b++`, but not `a[1]++`
desugaredSource: KtSourceElement?,
appendAssignment: FirBlockBuilder.(resultInitializer: FirExpression, resultVar: FirVariable) -> Unit
) {
// initialValueVar is only used for postfix increment/decrement (stores the argument value before increment/decrement).
val initialValueVar = generateTemporaryVariable(
baseModuleData,
desugaredSource,
SpecialNames.UNARY,
receiver
)
// resultInitializer is the expression for `argument.inc()`
val resultInitializer = buildFunctionCall {
source = desugaredSource
calleeReference = buildSimpleNamedReference {
source = operationReference?.toFirSourceElement()
name = callName
}
explicitReceiver = if (prefix) {
receiver
} else {
generateResolvedAccessExpression(desugaredSource, initialValueVar)
}
origin = FirFunctionCallOrigin.Operator
}
// resultVar is only used for prefix increment/decrement.
val resultVar = generateTemporaryVariable(
baseModuleData,
desugaredSource,
Name.special("<unary-result>"),
resultInitializer
)
if (prefix) { if (prefix) {
if (unwrappedReceiver.elementType != REFERENCE_EXPRESSION) { if (nameIfSimpleReference != null) {
statements += resultVar appendAssignment(resultInitializer, resultVar)
appendAssignment() statements += generateAccessExpression(desugaredSource, desugaredSource, nameIfSimpleReference)
statements += generateResolvedAccessExpression(desugaredSource, resultVar)
} else { } else {
appendAssignment() statements += resultVar
statements += generateAccessExpression(desugaredSource, desugaredSource, unwrappedReceiver.getReferencedNameAsName()) appendAssignment(resultInitializer, resultVar)
statements += generateResolvedAccessExpression(desugaredSource, resultVar)
} }
} else { } else {
statements += initialValueVar statements += initialValueVar
appendAssignment() appendAssignment(resultInitializer, resultVar)
statements += generateResolvedAccessExpression(desugaredSource, initialValueVar) statements += generateResolvedAccessExpression(desugaredSource, initialValueVar)
} }
} }
}
private fun T?.unwrap(): T? { private fun T?.unwrap(): T? {
// NOTE: By removing surrounding parentheses and labels, FirLabels will NOT be created for those labels. // NOTE: By removing surrounding parentheses and labels, FirLabels will NOT be created for those labels.
@@ -657,39 +701,11 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
firArgumentSelector.also { if (it is FirQualifiedAccessExpression) it.replaceExplicitReceiver(receiver) } firArgumentSelector.also { if (it is FirQualifiedAccessExpression) it.replaceExplicitReceiver(receiver) }
} }
// initialValueVar is only used for postfix increment/decrement (stores the argument value before increment/decrement). putIncrementOrDecrementStatements(
val initialValueVar = generateTemporaryVariable( firArgument, operationReference, callName, prefix,
baseModuleData, nameIfSimpleReference = null, desugaredSource
desugaredSource, ) { resultInitializer: FirExpression, resultVar: FirVariable ->
SpecialNames.UNARY, if (firArgument !is FirQualifiedAccessExpression) return@putIncrementOrDecrementStatements
firArgument
)
// resultInitializer is the expression for `argument.inc()`
val resultInitializer = buildFunctionCall {
source = desugaredSource
calleeReference = buildSimpleNamedReference {
source = operationReference?.toFirSourceElement()
name = callName
}
explicitReceiver = if (prefix) {
firArgument
} else {
generateResolvedAccessExpression(desugaredSource, initialValueVar)
}
origin = FirFunctionCallOrigin.Operator
}
// resultVar is only used for prefix increment/decrement.
val resultVar = generateTemporaryVariable(
baseModuleData,
desugaredSource,
Name.special("<unary-result>"),
resultInitializer
)
fun appendAssignment() {
if (firArgument is FirQualifiedAccessExpression) {
statements += buildVariableAssignment { statements += buildVariableAssignment {
source = desugaredSource source = desugaredSource
rValue = if (prefix) { rValue = if (prefix) {
@@ -705,17 +721,6 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
} }
} }
} }
if (prefix) {
statements += resultVar
appendAssignment()
statements += generateResolvedAccessExpression(desugaredSource, resultVar)
} else {
statements += initialValueVar
appendAssignment()
statements += generateResolvedAccessExpression(desugaredSource, initialValueVar)
}
}
} }
/** /**
@@ -797,38 +802,10 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
origin = FirFunctionCallOrigin.Operator origin = FirFunctionCallOrigin.Operator
} }
// initialValueVar is only used for postfix increment/decrement (stores the argument value before increment/decrement). putIncrementOrDecrementStatements(
val initialValueVar = generateTemporaryVariable( firArgument, operationReference, callName, prefix,
baseModuleData, nameIfSimpleReference = null, desugaredSource
desugaredSource, ) { resultInitializer: FirExpression, resultVar: FirVariable ->
SpecialNames.UNARY,
firArgument
)
// resultInitializer is the expression for `argument.inc()`
val resultInitializer = buildFunctionCall {
source = desugaredSource
calleeReference = buildSimpleNamedReference {
source = operationReference?.toFirSourceElement()
name = callName
}
explicitReceiver = if (prefix) {
firArgument
} else {
generateResolvedAccessExpression(desugaredSource, initialValueVar)
}
origin = FirFunctionCallOrigin.Operator
}
// resultVar is only used for prefix increment/decrement.
val resultVar = generateTemporaryVariable(
baseModuleData,
desugaredSource,
Name.special("<unary-result>"),
resultInitializer
)
fun appendAssignment() {
statements += buildFunctionCall { statements += buildFunctionCall {
source = desugaredSource source = desugaredSource
calleeReference = buildSimpleNamedReference { calleeReference = buildSimpleNamedReference {
@@ -849,16 +826,6 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
origin = FirFunctionCallOrigin.Operator origin = FirFunctionCallOrigin.Operator
} }
} }
if (prefix) {
statements += resultVar
appendAssignment()
statements += generateResolvedAccessExpression(desugaredSource, resultVar)
} else {
statements += initialValueVar
appendAssignment()
statements += generateResolvedAccessExpression(desugaredSource, initialValueVar)
}
} }
} }