RAW FIR: flatten if chains

This commit is contained in:
Jinseong Jeon
2022-02-13 01:00:30 -08:00
committed by teamcity
parent 5cec068d36
commit bb766a5235
6 changed files with 186 additions and 209 deletions
@@ -361,83 +361,66 @@ digraph implicitReceivers_kt {
} }
subgraph cluster_36 { subgraph cluster_36 {
color=blue color=blue
125 [label="Enter when branch condition else"]; 125 [label="Enter when branch condition "];
126 [label="Exit when branch condition"]; 126 [label="Access variable this@R|/test_4|"];
127 [label="Type operator: (this@R|/test_4| !is R|B|)"];
128 [label="Exit when branch condition"];
} }
127 [label="Enter when branch result"];
subgraph cluster_37 { subgraph cluster_37 {
color=blue color=blue
128 [label="Enter block"]; 129 [label="Enter when branch condition else"];
subgraph cluster_38 { 130 [label="Exit when branch condition"];
color=blue
129 [label="Enter when"];
subgraph cluster_39 {
color=blue
130 [label="Enter when branch condition "];
131 [label="Access variable this@R|/test_4|"];
132 [label="Type operator: (this@R|/test_4| !is R|B|)"];
133 [label="Exit when branch condition"];
}
subgraph cluster_40 {
color=blue
134 [label="Enter when branch condition else"];
135 [label="Exit when branch condition"];
}
136 [label="Enter when branch result"];
subgraph cluster_41 {
color=blue
137 [label="Enter block"];
138 [label="Access variable this@R|/test_4|"];
139 [label="Function call: this@R|/test_4|.R|/A.foo|()"];
140 [label="Function call: this@R|/test_4|.R|/A.foo|()"];
141 [label="Access variable this@R|/test_4|"];
142 [label="Function call: this@R|/test_4|.R|/B.bar|()"];
143 [label="Function call: this@R|/test_4|.R|/B.bar|()"];
144 [label="Exit block"];
}
145 [label="Exit when branch result"];
146 [label="Enter when branch result"];
subgraph cluster_42 {
color=blue
147 [label="Enter block"];
148 [label="Access variable this@R|/test_4|"];
149 [label="Function call: this@R|/test_4|.<Unresolved name: bar>#()"];
150 [label="Function call: <Unresolved name: bar>#()"];
151 [label="Access variable this@R|/test_4|"];
152 [label="Function call: this@R|/test_4|.R|/A.foo|()"];
153 [label="Function call: this@R|/test_4|.R|/A.foo|()"];
154 [label="Exit block"];
}
155 [label="Exit when branch result"];
156 [label="Exit when"];
}
157 [label="Exit block"];
} }
158 [label="Exit when branch result"]; 131 [label="Enter when branch result"];
159 [label="Enter when branch result"]; subgraph cluster_38 {
subgraph cluster_43 {
color=blue color=blue
160 [label="Enter block"]; 132 [label="Enter block"];
161 [label="Access variable this@R|/test_4|"]; 133 [label="Access variable this@R|/test_4|"];
162 [label="Function call: this@R|/test_4|.<Unresolved name: foo>#()"]; 134 [label="Function call: this@R|/test_4|.R|/A.foo|()"];
163 [label="Function call: <Unresolved name: foo>#()"]; 135 [label="Function call: this@R|/test_4|.R|/A.foo|()"];
164 [label="Access variable this@R|/test_4|"]; 136 [label="Access variable this@R|/test_4|"];
165 [label="Function call: this@R|/test_4|.<Unresolved name: bar>#()"]; 137 [label="Function call: this@R|/test_4|.R|/B.bar|()"];
166 [label="Function call: <Unresolved name: bar>#()"]; 138 [label="Function call: this@R|/test_4|.R|/B.bar|()"];
167 [label="Exit block"]; 139 [label="Exit block"];
} }
168 [label="Exit when branch result"]; 140 [label="Exit when branch result"];
169 [label="Exit when"]; 141 [label="Enter when branch result"];
subgraph cluster_39 {
color=blue
142 [label="Enter block"];
143 [label="Access variable this@R|/test_4|"];
144 [label="Function call: this@R|/test_4|.<Unresolved name: bar>#()"];
145 [label="Function call: <Unresolved name: bar>#()"];
146 [label="Access variable this@R|/test_4|"];
147 [label="Function call: this@R|/test_4|.R|/A.foo|()"];
148 [label="Function call: this@R|/test_4|.R|/A.foo|()"];
149 [label="Exit block"];
}
150 [label="Exit when branch result"];
151 [label="Enter when branch result"];
subgraph cluster_40 {
color=blue
152 [label="Enter block"];
153 [label="Access variable this@R|/test_4|"];
154 [label="Function call: this@R|/test_4|.<Unresolved name: foo>#()"];
155 [label="Function call: <Unresolved name: foo>#()"];
156 [label="Access variable this@R|/test_4|"];
157 [label="Function call: this@R|/test_4|.<Unresolved name: bar>#()"];
158 [label="Function call: <Unresolved name: bar>#()"];
159 [label="Exit block"];
}
160 [label="Exit when branch result"];
161 [label="Exit when"];
} }
170 [label="Access variable this@R|/test_4|"]; 162 [label="Access variable this@R|/test_4|"];
171 [label="Function call: this@R|/test_4|.<Unresolved name: foo>#()"]; 163 [label="Function call: this@R|/test_4|.<Unresolved name: foo>#()"];
172 [label="Function call: <Unresolved name: foo>#()"]; 164 [label="Function call: <Unresolved name: foo>#()"];
173 [label="Access variable this@R|/test_4|"]; 165 [label="Access variable this@R|/test_4|"];
174 [label="Function call: this@R|/test_4|.<Unresolved name: bar>#()"]; 166 [label="Function call: this@R|/test_4|.<Unresolved name: bar>#()"];
175 [label="Function call: <Unresolved name: bar>#()"]; 167 [label="Function call: <Unresolved name: bar>#()"];
176 [label="Exit block"]; 168 [label="Exit block"];
} }
177 [label="Exit function test_4" style="filled" fillcolor=red]; 169 [label="Exit function test_4" style="filled" fillcolor=red];
} }
118 -> {119}; 118 -> {119};
119 -> {120}; 119 -> {120};
@@ -445,33 +428,33 @@ digraph implicitReceivers_kt {
121 -> {122}; 121 -> {122};
122 -> {123}; 122 -> {123};
123 -> {124}; 123 -> {124};
124 -> {159 125}; 124 -> {151 125};
125 -> {126}; 125 -> {126};
126 -> {127}; 126 -> {127};
127 -> {128}; 127 -> {128};
128 -> {129}; 128 -> {141 129};
129 -> {130}; 129 -> {130};
130 -> {131}; 130 -> {131};
131 -> {132}; 131 -> {132};
132 -> {133}; 132 -> {133};
133 -> {146 134}; 133 -> {134};
134 -> {135}; 134 -> {135};
135 -> {136}; 135 -> {136};
136 -> {137}; 136 -> {137};
137 -> {138}; 137 -> {138};
138 -> {139}; 138 -> {139};
139 -> {140}; 139 -> {140};
140 -> {141}; 140 -> {161};
141 -> {142}; 141 -> {142};
142 -> {143}; 142 -> {143};
143 -> {144}; 143 -> {144};
144 -> {145}; 144 -> {145};
145 -> {156}; 145 -> {146};
146 -> {147}; 146 -> {147};
147 -> {148}; 147 -> {148};
148 -> {149}; 148 -> {149};
149 -> {150}; 149 -> {150};
150 -> {151}; 150 -> {161};
151 -> {152}; 151 -> {152};
152 -> {153}; 152 -> {153};
153 -> {154}; 153 -> {154};
@@ -479,7 +462,7 @@ digraph implicitReceivers_kt {
155 -> {156}; 155 -> {156};
156 -> {157}; 156 -> {157};
157 -> {158}; 157 -> {158};
158 -> {169}; 158 -> {159};
159 -> {160}; 159 -> {160};
160 -> {161}; 160 -> {161};
161 -> {162}; 161 -> {162};
@@ -490,70 +473,62 @@ digraph implicitReceivers_kt {
166 -> {167}; 166 -> {167};
167 -> {168}; 167 -> {168};
168 -> {169}; 168 -> {169};
169 -> {170};
170 -> {171};
171 -> {172};
172 -> {173};
173 -> {174};
174 -> {175};
175 -> {176};
176 -> {177};
subgraph cluster_44 { subgraph cluster_41 {
color=red color=red
178 [label="Enter function test_5" style="filled" fillcolor=red]; 170 [label="Enter function test_5" style="filled" fillcolor=red];
subgraph cluster_45 { subgraph cluster_42 {
color=blue color=blue
179 [label="Enter block"]; 171 [label="Enter block"];
subgraph cluster_46 { subgraph cluster_43 {
color=blue color=blue
180 [label="Enter when"]; 172 [label="Enter when"];
subgraph cluster_44 {
color=blue
173 [label="Enter when branch condition "];
174 [label="Access variable this@R|/test_5|"];
175 [label="Type operator: (this@R|/test_5| is R|kotlin/collections/List<*>|)"];
176 [label="Exit when branch condition"];
}
subgraph cluster_45 {
color=blue
177 [label="Enter when branch condition "];
178 [label="Access variable this@R|/test_5|"];
179 [label="Type operator: (this@R|/test_5| is R|kotlin/String|)"];
180 [label="Exit when branch condition"];
}
subgraph cluster_46 {
color=blue
181 [label="Enter when branch condition else"];
182 [label="Exit when branch condition"];
}
183 [label="Enter when branch result"];
subgraph cluster_47 { subgraph cluster_47 {
color=blue color=blue
181 [label="Enter when branch condition "]; 184 [label="Enter block"];
182 [label="Access variable this@R|/test_5|"]; 185 [label="Const: Int(0)"];
183 [label="Type operator: (this@R|/test_5| is R|kotlin/collections/List<*>|)"]; 186 [label="Exit block"];
184 [label="Exit when branch condition"];
} }
187 [label="Exit when branch result"];
188 [label="Enter when branch result"];
subgraph cluster_48 { subgraph cluster_48 {
color=blue color=blue
185 [label="Enter when branch condition "]; 189 [label="Enter block"];
186 [label="Access variable this@R|/test_5|"]; 190 [label="Access variable R|kotlin/String.length|"];
187 [label="Type operator: (this@R|/test_5| is R|kotlin/String|)"]; 191 [label="Exit block"];
188 [label="Exit when branch condition"];
} }
192 [label="Exit when branch result"];
193 [label="Enter when branch result"];
subgraph cluster_49 { subgraph cluster_49 {
color=blue color=blue
189 [label="Enter when branch condition else"]; 194 [label="Enter block"];
190 [label="Exit when branch condition"]; 195 [label="Access variable R|SubstitutionOverride<kotlin/collections/List.size: R|kotlin/Int|>|"];
196 [label="Exit block"];
} }
191 [label="Enter when branch result"]; 197 [label="Exit when branch result"];
subgraph cluster_50 { 198 [label="Exit when"];
color=blue
192 [label="Enter block"];
193 [label="Const: Int(0)"];
194 [label="Exit block"];
}
195 [label="Exit when branch result"];
196 [label="Enter when branch result"];
subgraph cluster_51 {
color=blue
197 [label="Enter block"];
198 [label="Access variable R|kotlin/String.length|"];
199 [label="Exit block"];
}
200 [label="Exit when branch result"];
201 [label="Enter when branch result"];
subgraph cluster_52 {
color=blue
202 [label="Enter block"];
203 [label="Access variable R|SubstitutionOverride<kotlin/collections/List.size: R|kotlin/Int|>|"];
204 [label="Exit block"];
}
205 [label="Exit when branch result"];
206 [label="Exit when"];
} }
207 [label="Jump: ^test_5 when () { 199 [label="Jump: ^test_5 when () {
(this@R|/test_5| is R|kotlin/collections/List<*>|) -> { (this@R|/test_5| is R|kotlin/collections/List<*>|) -> {
this@R|/test_5|.R|SubstitutionOverride<kotlin/collections/List.size: R|kotlin/Int|>| this@R|/test_5|.R|SubstitutionOverride<kotlin/collections/List.size: R|kotlin/Int|>|
} }
@@ -565,69 +540,69 @@ digraph implicitReceivers_kt {
} }
} }
"]; "];
208 [label="Stub" style="filled" fillcolor=gray]; 200 [label="Stub" style="filled" fillcolor=gray];
209 [label="Exit block" style="filled" fillcolor=gray]; 201 [label="Exit block" style="filled" fillcolor=gray];
} }
210 [label="Exit function test_5" style="filled" fillcolor=red]; 202 [label="Exit function test_5" style="filled" fillcolor=red];
} }
170 -> {171};
171 -> {172};
172 -> {173};
173 -> {174};
174 -> {175};
175 -> {176};
176 -> {193 177};
177 -> {178};
178 -> {179}; 178 -> {179};
179 -> {180}; 179 -> {180};
180 -> {181}; 180 -> {188 181};
181 -> {182}; 181 -> {182};
182 -> {183}; 182 -> {183};
183 -> {184}; 183 -> {184};
184 -> {201 185}; 184 -> {185};
185 -> {186}; 185 -> {186};
186 -> {187}; 186 -> {187};
187 -> {188}; 187 -> {198};
188 -> {196 189}; 188 -> {189};
189 -> {190}; 189 -> {190};
190 -> {191}; 190 -> {191};
191 -> {192}; 191 -> {192};
192 -> {193}; 192 -> {198};
193 -> {194}; 193 -> {194};
194 -> {195}; 194 -> {195};
195 -> {206}; 195 -> {196};
196 -> {197}; 196 -> {197};
197 -> {198}; 197 -> {198};
198 -> {199}; 198 -> {199};
199 -> {200}; 199 -> {202};
200 -> {206}; 199 -> {200} [style=dotted];
201 -> {202}; 200 -> {201} [style=dotted];
202 -> {203}; 201 -> {202} [style=dotted];
subgraph cluster_50 {
color=red
203 [label="Enter function test_6" style="filled" fillcolor=red];
subgraph cluster_51 {
color=blue
204 [label="Enter block"];
205 [label="Access variable this@R|/test_6|"];
206 [label="Type operator: (this@R|/test_6| as R|kotlin/collections/List<*>|)"];
207 [label="Access variable R|SubstitutionOverride<kotlin/collections/List.size: R|kotlin/Int|>|"];
208 [label="Access variable this@R|/test_6|"];
209 [label="Type operator: (this@R|/test_6| as R|kotlin/String|)"];
210 [label="Access variable R|kotlin/String.length|"];
211 [label="Exit block"];
}
212 [label="Exit function test_6" style="filled" fillcolor=red];
}
203 -> {204}; 203 -> {204};
204 -> {205}; 204 -> {205};
205 -> {206}; 205 -> {206};
206 -> {207}; 206 -> {207};
207 -> {210}; 207 -> {208};
207 -> {208} [style=dotted]; 208 -> {209};
208 -> {209} [style=dotted]; 209 -> {210};
209 -> {210} [style=dotted]; 210 -> {211};
subgraph cluster_53 {
color=red
211 [label="Enter function test_6" style="filled" fillcolor=red];
subgraph cluster_54 {
color=blue
212 [label="Enter block"];
213 [label="Access variable this@R|/test_6|"];
214 [label="Type operator: (this@R|/test_6| as R|kotlin/collections/List<*>|)"];
215 [label="Access variable R|SubstitutionOverride<kotlin/collections/List.size: R|kotlin/Int|>|"];
216 [label="Access variable this@R|/test_6|"];
217 [label="Type operator: (this@R|/test_6| as R|kotlin/String|)"];
218 [label="Access variable R|kotlin/String.length|"];
219 [label="Exit block"];
}
220 [label="Exit function test_6" style="filled" fillcolor=red];
}
211 -> {212}; 211 -> {212};
212 -> {213};
213 -> {214};
214 -> {215};
215 -> {216};
216 -> {217};
217 -> {218};
218 -> {219};
219 -> {220};
} }
@@ -73,22 +73,17 @@ FILE: implicitReceivers.kt
this@R|/test_4|.<Unresolved name: bar>#() this@R|/test_4|.<Unresolved name: bar>#()
<Unresolved name: bar>#() <Unresolved name: bar>#()
} }
(this@R|/test_4| !is R|B|) -> {
this@R|/test_4|.<Unresolved name: bar>#()
<Unresolved name: bar>#()
this@R|/test_4|.R|/A.foo|()
this@R|/test_4|.R|/A.foo|()
}
else -> { else -> {
when () { this@R|/test_4|.R|/A.foo|()
(this@R|/test_4| !is R|B|) -> { this@R|/test_4|.R|/A.foo|()
this@R|/test_4|.<Unresolved name: bar>#() this@R|/test_4|.R|/B.bar|()
<Unresolved name: bar>#() this@R|/test_4|.R|/B.bar|()
this@R|/test_4|.R|/A.foo|()
this@R|/test_4|.R|/A.foo|()
}
else -> {
this@R|/test_4|.R|/A.foo|()
this@R|/test_4|.R|/A.foo|()
this@R|/test_4|.R|/B.bar|()
this@R|/test_4|.R|/B.bar|()
}
}
} }
} }
@@ -1909,19 +1909,30 @@ open class RawFirBuilder(
override fun visitIfExpression(expression: KtIfExpression, data: Unit): FirElement { override fun visitIfExpression(expression: KtIfExpression, data: Unit): FirElement {
return buildWhenExpression { return buildWhenExpression {
source = expression.toFirSourceElement() source = expression.toFirSourceElement()
val ktCondition = expression.condition
branches += buildWhenBranch { var ktLastIf: KtIfExpression = expression
source = ktCondition?.toFirSourceElement(KtFakeSourceElementKind.WhenCondition) whenBranches@ while (true) {
condition = ktCondition.toFirExpression("If statement should have condition") val ktCondition = ktLastIf.condition
result = expression.then.toFirBlock()
}
if (expression.elseKeyword != null) {
branches += buildWhenBranch { branches += buildWhenBranch {
source = expression.elseKeyword?.toKtPsiSourceElement() source = ktCondition?.toFirSourceElement(KtFakeSourceElementKind.WhenCondition)
condition = buildElseIfTrueCondition() condition = ktCondition.toFirExpression("If statement should have condition")
result = expression.`else`.toFirBlock() result = ktLastIf.then.toFirBlock()
}
when (val ktElse = ktLastIf.`else`) {
null -> break@whenBranches
is KtIfExpression -> ktLastIf = ktElse
else -> {
branches += buildWhenBranch {
source = ktLastIf.elseKeyword?.toKtPsiSourceElement()
condition = buildElseIfTrueCondition()
result = ktLastIf.`else`.toFirBlock()
}
break@whenBranches
}
} }
} }
usedAsExpression = expression.usedAsExpression usedAsExpression = expression.usedAsExpression
} }
} }
@@ -4,7 +4,7 @@ fun example() {
val a = if (true) true else false val a = if (true) true else false
val b = if (true) else false val b = if (true) else false
val c = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) true val c = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) true
val d = if (true) true else; val d = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) true else;
val e = if (true) {} else false val e = if (true) {} else false
val f = if (true) true else {} val f = if (true) true else {}
+8 -10
View File
@@ -9,17 +9,14 @@ FILE fqName:<root> fileName:/ifElseIf.kt
arg0: GET_VAR 'i: kotlin.Int declared in <root>.test' type=kotlin.Int origin=null arg0: GET_VAR 'i: kotlin.Int declared in <root>.test' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=0 arg1: CONST Int type=kotlin.Int value=0
then: CONST Int type=kotlin.Int value=1 then: CONST Int type=kotlin.Int value=1
BRANCH
if: CALL 'public final fun less (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: GET_VAR 'i: kotlin.Int declared in <root>.test' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=0
then: CONST Int type=kotlin.Int value=-1
BRANCH BRANCH
if: CONST Boolean type=kotlin.Boolean value=true if: CONST Boolean type=kotlin.Boolean value=true
then: WHEN type=kotlin.Int origin=IF then: CONST Int type=kotlin.Int value=0
BRANCH
if: CALL 'public final fun less (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT
arg0: GET_VAR 'i: kotlin.Int declared in <root>.test' type=kotlin.Int origin=null
arg1: CONST Int type=kotlin.Int value=0
then: CONST Int type=kotlin.Int value=-1
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CONST Int type=kotlin.Int value=0
FUN name:testEmptyBranches1 visibility:public modality:FINAL <> (flag:kotlin.Boolean) returnType:kotlin.Unit FUN name:testEmptyBranches1 visibility:public modality:FINAL <> (flag:kotlin.Boolean) returnType:kotlin.Unit
VALUE_PARAMETER name:flag index:0 type:kotlin.Boolean VALUE_PARAMETER name:flag index:0 type:kotlin.Boolean
BLOCK_BODY BLOCK_BODY
@@ -34,7 +31,8 @@ FILE fqName:<root> fileName:/ifElseIf.kt
WHEN type=kotlin.Unit origin=IF WHEN type=kotlin.Unit origin=IF
BRANCH BRANCH
if: GET_VAR 'flag: kotlin.Boolean declared in <root>.testEmptyBranches1' type=kotlin.Boolean origin=null if: GET_VAR 'flag: kotlin.Boolean declared in <root>.testEmptyBranches1' type=kotlin.Boolean origin=null
then: CONST Boolean type=kotlin.Boolean value=true then: TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
CONST Boolean type=kotlin.Boolean value=true
FUN name:testEmptyBranches2 visibility:public modality:FINAL <> (flag:kotlin.Boolean) returnType:kotlin.Unit FUN name:testEmptyBranches2 visibility:public modality:FINAL <> (flag:kotlin.Boolean) returnType:kotlin.Unit
VALUE_PARAMETER name:flag index:0 type:kotlin.Boolean VALUE_PARAMETER name:flag index:0 type:kotlin.Boolean
BLOCK_BODY BLOCK_BODY
@@ -1,10 +1,8 @@
fun test(i: Int): Int { fun test(i: Int): Int {
return when { return when {
greater(arg0 = i, arg1 = 0) -> 1 greater(arg0 = i, arg1 = 0) -> 1
else -> when { less(arg0 = i, arg1 = 0) -> -1
less(arg0 = i, arg1 = 0) -> -1 else -> 0
else -> 0
}
} }
} }
@@ -15,7 +13,7 @@ fun testEmptyBranches1(flag: Boolean) {
else -> true else -> true
} /*~> Unit */ } /*~> Unit */
when { when {
flag -> true flag -> true /*~> Unit */
} }
} }