JS: decomposition of ternary operator
This commit is contained in:
@@ -97,6 +97,35 @@ class ExpressionDecomposer private (
|
||||
index = accept(index)
|
||||
}
|
||||
|
||||
override fun visit(x: JsConditional, ctx: JsContext<*>): Boolean {
|
||||
x.process(ctx)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun JsConditional.process(ctx: JsContext<*>) {
|
||||
test = accept(test)
|
||||
if (then !in containsExtractable && otherwise !in containsExtractable) return
|
||||
|
||||
val tmp = Temporary()
|
||||
addStatement(tmp.variable)
|
||||
|
||||
val thenBlock = withNewAdditionalStatements {
|
||||
then = accept(then)
|
||||
addStatement(tmp.assign(then))
|
||||
additionalStatements.toStatement()
|
||||
}
|
||||
|
||||
val elseBlock = withNewAdditionalStatements {
|
||||
otherwise = accept(otherwise)
|
||||
addStatement(tmp.assign(otherwise))
|
||||
additionalStatements.toStatement()
|
||||
}
|
||||
|
||||
val lazyEval = JsIf(test, thenBlock, elseBlock)
|
||||
addStatement(lazyEval)
|
||||
ctx.replaceMe(tmp.nameRef)
|
||||
}
|
||||
|
||||
override fun visit(x: JsInvocation, ctx: JsContext<*>): Boolean {
|
||||
CallableInvocationAdapter(x).process()
|
||||
return false
|
||||
@@ -153,9 +182,21 @@ class ExpressionDecomposer private (
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
private fun withNewAdditionalStatements<T>(fn: ()->T): T {
|
||||
val backup = additionalStatements
|
||||
additionalStatements = SmartList<JsStatement>()
|
||||
val result = fn()
|
||||
additionalStatements = backup
|
||||
return result
|
||||
}
|
||||
|
||||
private fun addStatement(statement: JsStatement) =
|
||||
additionalStatements.add(statement)
|
||||
|
||||
private fun addStatements(statements: List<JsStatement>) =
|
||||
additionalStatements.addAll(statements)
|
||||
|
||||
private fun JsExpression.extractToTemporary(): JsExpression {
|
||||
val tmp = Temporary(this)
|
||||
addStatement(tmp.variable)
|
||||
@@ -294,3 +335,10 @@ private fun JsNode.withParentsOfNodes(nodes: Set<JsNode>): Set<JsNode> {
|
||||
visitor.accept(this)
|
||||
return visitor.matched
|
||||
}
|
||||
|
||||
private fun List<JsStatement>.toStatement(): JsStatement =
|
||||
when (size()) {
|
||||
0 -> JsEmpty
|
||||
1 -> get(0)
|
||||
else -> JsBlock(this)
|
||||
}
|
||||
|
||||
@@ -63,3 +63,15 @@ public var JsArrayAccess.index: JsExpression
|
||||
public var JsArrayAccess.array: JsExpression
|
||||
get() = getArrayExpression()
|
||||
set(value) = setArrayExpression(value)
|
||||
|
||||
public var JsConditional.test: JsExpression
|
||||
get() = getTestExpression()
|
||||
set(value) = setTestExpression(value)
|
||||
|
||||
public var JsConditional.then: JsExpression
|
||||
get() = getThenExpression()
|
||||
set(value) = setThenExpression(value)
|
||||
|
||||
public var JsConditional.otherwise: JsExpression
|
||||
get() = getElseExpression()
|
||||
set(value) = setElseExpression(value)
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package foo
|
||||
|
||||
fun test(x: Boolean): Boolean =
|
||||
if (fizz(x)) buzz(true) else buzz(false)
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(true, test(true))
|
||||
assertEquals("fizz(true);buzz(true);", pullLog())
|
||||
assertEquals(false, test(false))
|
||||
assertEquals("fizz(false);buzz(false);", pullLog())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package foo
|
||||
|
||||
fun test(x: Boolean?): Boolean = fizz(x) ?: buzz(true)
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(true, test(null))
|
||||
assertEquals("fizz(null);buzz(true);", pullLog())
|
||||
assertEquals(false, test(false))
|
||||
assertEquals("fizz(false);", pullLog())
|
||||
assertEquals(true, test(true))
|
||||
assertEquals("fizz(true);", pullLog())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package foo
|
||||
|
||||
fun test(x: Boolean, y: Boolean): Int =
|
||||
if (fizz(x))
|
||||
if (fizz(y)) buzz(1) else buzz(2)
|
||||
else
|
||||
if (fizz(y)) buzz(3) else buzz(4)
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(1, test(true, true))
|
||||
assertEquals("fizz(true);fizz(true);buzz(1);", pullLog())
|
||||
|
||||
assertEquals(2, test(true, false))
|
||||
assertEquals("fizz(true);fizz(false);buzz(2);", pullLog())
|
||||
|
||||
assertEquals(3, test(false, true))
|
||||
assertEquals("fizz(false);fizz(true);buzz(3);", pullLog())
|
||||
|
||||
assertEquals(4, test(false, false))
|
||||
assertEquals("fizz(false);fizz(false);buzz(4);", pullLog())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package foo
|
||||
|
||||
fun test(x: Boolean): Boolean =
|
||||
if (buzz(x)) buzz(true) else fizz(false)
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(true, test(true))
|
||||
assertEquals("buzz(true);buzz(true);", pullLog())
|
||||
assertEquals(false, test(false))
|
||||
assertEquals("buzz(false);fizz(false);", pullLog())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package foo
|
||||
|
||||
fun test(x: Boolean?): Boolean = buzz(x) ?: fizz(true)
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(true, test(null))
|
||||
assertEquals("buzz(null);fizz(true);", pullLog())
|
||||
assertEquals(false, test(false))
|
||||
assertEquals("buzz(false);", pullLog())
|
||||
assertEquals(true, test(true))
|
||||
assertEquals("buzz(true);", pullLog())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user