[FIR] Handle pre/postfix dec/increment of labeled expression

This commit is contained in:
Mark Punzalan
2020-09-18 22:42:29 -07:00
committed by Mikhail Glukhikh
parent f55ff8eb1b
commit 8cac3f654c
5 changed files with 44 additions and 31 deletions
@@ -62,20 +62,29 @@ open class BaseConverter(
return null return null
} }
override fun LighterASTNode.getExpressionInParentheses(): LighterASTNode? { override fun LighterASTNode.getExpressionInParentheses() = getFirstChildExpression()
this.forEachChildren {
override fun LighterASTNode.getAnnotatedExpression() = getFirstChildExpression()
override fun LighterASTNode.getLabeledExpression() = getLastChildExpression()
private fun LighterASTNode.getFirstChildExpression(): LighterASTNode? {
forEachChildren {
if (it.isExpression()) return it if (it.isExpression()) return it
} }
return null return null
} }
override fun LighterASTNode.getAnnotatedExpression(): LighterASTNode? { private fun LighterASTNode.getLastChildExpression(): LighterASTNode? {
this.forEachChildren { var result: LighterASTNode? = null
if (it.isExpression()) return it forEachChildren {
if (it.isExpression()) {
result = it
}
} }
return null return result
} }
override fun LighterASTNode.getChildNodeByType(type: IElementType): LighterASTNode? { override fun LighterASTNode.getChildNodeByType(type: IElementType): LighterASTNode? {
@@ -122,6 +122,10 @@ class RawFirBuilder(
return (this as KtAnnotatedExpression).baseExpression return (this as KtAnnotatedExpression).baseExpression
} }
override fun PsiElement.getLabeledExpression(): PsiElement? {
return (this as KtLabeledExpression).baseExpression
}
override val PsiElement?.receiverExpression: PsiElement? override val PsiElement?.receiverExpression: PsiElement?
get() = (this as? KtQualifiedExpression)?.receiverExpression get() = (this as? KtQualifiedExpression)?.receiverExpression
@@ -51,6 +51,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
abstract fun T.getLabelName(): String? abstract fun T.getLabelName(): String?
abstract fun T.getExpressionInParentheses(): T? abstract fun T.getExpressionInParentheses(): T?
abstract fun T.getAnnotatedExpression(): T? abstract fun T.getAnnotatedExpression(): T?
abstract fun T.getLabeledExpression(): T?
abstract fun T.getChildNodeByType(type: IElementType): T? abstract fun T.getChildNodeByType(type: IElementType): T?
abstract val T?.receiverExpression: T? abstract val T?.receiverExpression: T?
abstract val T?.selectorExpression: T? abstract val T?.selectorExpression: T?
@@ -405,29 +406,29 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
prefix: Boolean, prefix: Boolean,
convert: T.() -> FirExpression convert: T.() -> FirExpression
): FirExpression { ): FirExpression {
if (argument == null) { // NOTE: By removing surrounding parentheses and labels, FirLabels will NOT be created for those labels.
// This should be fine since the label is meaningless and unusable for a ++/-- argument.
var unwrappedArgument = argument
while (true) {
unwrappedArgument = when (unwrappedArgument?.elementType) {
PARENTHESIZED -> unwrappedArgument?.getExpressionInParentheses()
LABELED_EXPRESSION -> unwrappedArgument?.getLabeledExpression()
else -> break
}
}
if (unwrappedArgument == null) {
return buildErrorExpression { return buildErrorExpression {
source = argument source = unwrappedArgument
diagnostic = ConeSimpleDiagnostic("Inc/dec without operand", DiagnosticKind.Syntax) diagnostic = ConeSimpleDiagnostic("Inc/dec without operand", DiagnosticKind.Syntax)
} }
} }
if (argument.elementType == PARENTHESIZED) { if (unwrappedArgument.elementType == DOT_QUALIFIED_EXPRESSION) {
return generateIncrementOrDecrementBlock(
baseExpression,
operationReference,
argument.getExpressionInParentheses(),
callName,
prefix,
convert
)
}
if (argument.elementType == DOT_QUALIFIED_EXPRESSION) {
return generateIncrementOrDecrementBlockForQualifiedAccess( return generateIncrementOrDecrementBlockForQualifiedAccess(
baseExpression, baseExpression,
operationReference, operationReference,
argument, unwrappedArgument,
callName, callName,
prefix, prefix,
convert convert
@@ -444,7 +445,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
this@BaseFirBuilder.baseSession, this@BaseFirBuilder.baseSession,
desugaredSource, desugaredSource,
Name.special("<unary>"), Name.special("<unary>"),
argument.convert() unwrappedArgument.convert()
) )
// resultInitializer is the expression for `argument.inc()` // resultInitializer is the expression for `argument.inc()`
@@ -455,7 +456,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
name = callName name = callName
} }
explicitReceiver = if (prefix) { explicitReceiver = if (prefix) {
argument.convert() unwrappedArgument.convert()
} else { } else {
generateResolvedAccessExpression(desugaredSource, initialValueVar) generateResolvedAccessExpression(desugaredSource, initialValueVar)
} }
@@ -469,10 +470,10 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
resultInitializer resultInitializer
) )
val assignment = argument.generateAssignment( val assignment = unwrappedArgument.generateAssignment(
desugaredSource, desugaredSource,
null, null,
if (prefix && argument.elementType != REFERENCE_EXPRESSION) if (prefix && unwrappedArgument.elementType != REFERENCE_EXPRESSION)
generateResolvedAccessExpression(source, resultVar) generateResolvedAccessExpression(source, resultVar)
else else
resultInitializer, resultInitializer,
@@ -488,13 +489,13 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
} }
if (prefix) { if (prefix) {
if (argument.elementType != REFERENCE_EXPRESSION) { if (unwrappedArgument.elementType != REFERENCE_EXPRESSION) {
statements += resultVar statements += resultVar
appendAssignment() appendAssignment()
statements += generateResolvedAccessExpression(desugaredSource, resultVar) statements += generateResolvedAccessExpression(desugaredSource, resultVar)
} else { } else {
appendAssignment() appendAssignment()
statements += generateAccessExpression(desugaredSource, argument.getReferencedNameAsName()) statements += generateAccessExpression(desugaredSource, unwrappedArgument.getReferencedNameAsName())
} }
} else { } else {
statements += initialValueVar statements += initialValueVar
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String { fun box(): String {
var x = 1 var x = 1
(foo@ x)++ (foo@ x)++
@@ -78,10 +78,10 @@ class Test() {
(f@ <!VARIABLE_EXPECTED!>getInt()<!>) += 343 (f@ <!VARIABLE_EXPECTED!>getInt()<!>) += 343
<!VARIABLE_EXPECTED!>1<!>++ <!VARIABLE_EXPECTED!>1<!>++
(<!VARIABLE_EXPECTED!>r@ 1<!>)++ (r@ <!VARIABLE_EXPECTED!>1<!>)++
<!VARIABLE_EXPECTED!>getInt()<!>++ <!VARIABLE_EXPECTED!>getInt()<!>++
(<!VARIABLE_EXPECTED!>m@ getInt()<!>)++ (m@ <!VARIABLE_EXPECTED!>getInt()<!>)++
this<!UNRESOLVED_REFERENCE!>++<!> this<!UNRESOLVED_REFERENCE!>++<!>
@@ -106,7 +106,7 @@ class Test() {
<!VARIABLE_EXPECTED!>b<!> += 34 <!VARIABLE_EXPECTED!>b<!> += 34
a++ a++
(<!VARIABLE_EXPECTED!>l@ a<!>)++ (l@ a)++
(a)++ (a)++
} }