JS: decomposition of "while" and "do while"
This commit is contained in:
@@ -77,6 +77,40 @@ class ExpressionDecomposer private (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun visit(x: JsWhile, ctx: JsContext<*>): Boolean {
|
||||||
|
x.process(true)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visit(x: JsDoWhile, ctx: JsContext<*>): Boolean {
|
||||||
|
x.process(false)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JsWhile.process(addBreakToBegin: Boolean) {
|
||||||
|
if (test !in containsExtractable) return
|
||||||
|
|
||||||
|
withNewAdditionalStatements {
|
||||||
|
test = accept(test)
|
||||||
|
val breakIfNotTest = JsIf(not(test), JsBreak())
|
||||||
|
// Body can be JsBlock or other JsStatement.
|
||||||
|
// Convert to statements list to avoid nested block.
|
||||||
|
val bodyStatements = flattenStatement(body)
|
||||||
|
|
||||||
|
if (addBreakToBegin) {
|
||||||
|
addStatement(breakIfNotTest)
|
||||||
|
addStatements(bodyStatements)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addStatements(0, bodyStatements)
|
||||||
|
addStatement(breakIfNotTest)
|
||||||
|
}
|
||||||
|
|
||||||
|
body = additionalStatements.toStatement()
|
||||||
|
test = JsLiteral.TRUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: comma operator?
|
// TODO: comma operator?
|
||||||
override fun visit(x: JsBinaryOperation, ctx: JsContext<*>): Boolean {
|
override fun visit(x: JsBinaryOperation, ctx: JsContext<*>): Boolean {
|
||||||
x.arg1 = accept(x.arg1)
|
x.arg1 = accept(x.arg1)
|
||||||
@@ -249,6 +283,9 @@ class ExpressionDecomposer private (
|
|||||||
private fun addStatements(statements: List<JsStatement>) =
|
private fun addStatements(statements: List<JsStatement>) =
|
||||||
additionalStatements.addAll(statements)
|
additionalStatements.addAll(statements)
|
||||||
|
|
||||||
|
private fun addStatements(index: Int, statements: List<JsStatement>) =
|
||||||
|
additionalStatements.addAll(index, statements)
|
||||||
|
|
||||||
private fun JsExpression.extractToTemporary(): JsExpression {
|
private fun JsExpression.extractToTemporary(): JsExpression {
|
||||||
val tmp = Temporary(this)
|
val tmp = Temporary(this)
|
||||||
addStatement(tmp.variable)
|
addStatement(tmp.variable)
|
||||||
@@ -320,8 +357,15 @@ private open class JsExpressionVisitor() : JsVisitorWithContextImpl() {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(x: JsWhile, ctx: JsContext<*>): Boolean = false
|
override fun visit(x: JsWhile, ctx: JsContext<*>): Boolean {
|
||||||
override fun visit(x: JsDoWhile, ctx: JsContext<*>): Boolean = false
|
x.test = accept(x.test)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visit(x: JsDoWhile, ctx: JsContext<*>): Boolean {
|
||||||
|
x.test = accept(x.test)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
override fun visit(x: JsArrayAccess, ctx: JsContext<*>): Boolean = true
|
override fun visit(x: JsArrayAccess, ctx: JsContext<*>): Boolean = true
|
||||||
override fun visit(x: JsArrayLiteral, ctx: JsContext<*>): Boolean = true
|
override fun visit(x: JsArrayLiteral, ctx: JsContext<*>): Boolean = true
|
||||||
|
|||||||
@@ -60,6 +60,14 @@ public var JsNameRef.qualifier: JsExpression?
|
|||||||
get() = getQualifier()
|
get() = getQualifier()
|
||||||
set(value) = setQualifier(value)
|
set(value) = setQualifier(value)
|
||||||
|
|
||||||
|
public var JsWhile.test: JsExpression
|
||||||
|
get() = getCondition()
|
||||||
|
set(value) = setCondition(value)
|
||||||
|
|
||||||
|
public var JsWhile.body: JsStatement
|
||||||
|
get() = getBody()
|
||||||
|
set(value) = setBody(value)
|
||||||
|
|
||||||
public var JsArrayAccess.index: JsExpression
|
public var JsArrayAccess.index: JsExpression
|
||||||
get() = getIndexExpression()
|
get() = getIndexExpression()
|
||||||
set(value) = setIndexExpression(value)
|
set(value) = setIndexExpression(value)
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var c = 2
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (c > 4) throw Exception("Timeout!")
|
||||||
|
c++
|
||||||
|
} while (buzz(c) < 4)
|
||||||
|
|
||||||
|
assertEquals("buzz(3);buzz(4);", pullLog())
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var c = 1
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (c > 4) throw Exception("Timeout!")
|
||||||
|
c++
|
||||||
|
} while (fizz(c) % 2 == 0 || buzz(c) % 3 == 0)
|
||||||
|
|
||||||
|
assertEquals("fizz(2);fizz(3);buzz(3);fizz(4);fizz(5);buzz(5);", pullLog())
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var c = 2
|
||||||
|
|
||||||
|
while (buzz(c) <= 4) {
|
||||||
|
if (c > 4) throw Exception("Timeout!")
|
||||||
|
c++
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals("buzz(2);buzz(3);buzz(4);buzz(5);", pullLog())
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var c = 2
|
||||||
|
|
||||||
|
while (fizz(c) % 2 == 0 || buzz(c) % 3 == 0) {
|
||||||
|
if (c > 4) throw Exception("Timeout!")
|
||||||
|
c++
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals("fizz(2);fizz(3);buzz(3);fizz(4);fizz(5);buzz(5);", pullLog())
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user