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?
|
||||
override fun visit(x: JsBinaryOperation, ctx: JsContext<*>): Boolean {
|
||||
x.arg1 = accept(x.arg1)
|
||||
@@ -249,12 +283,15 @@ class ExpressionDecomposer private (
|
||||
private fun addStatements(statements: List<JsStatement>) =
|
||||
additionalStatements.addAll(statements)
|
||||
|
||||
private fun addStatements(index: Int, statements: List<JsStatement>) =
|
||||
additionalStatements.addAll(index, statements)
|
||||
|
||||
private fun JsExpression.extractToTemporary(): JsExpression {
|
||||
val tmp = Temporary(this)
|
||||
addStatement(tmp.variable)
|
||||
return tmp.nameRef
|
||||
}
|
||||
|
||||
|
||||
private inner class Temporary(val value: JsExpression? = null) {
|
||||
val name: JsName = scope.declareTemporary()
|
||||
|
||||
@@ -320,8 +357,15 @@ private open class JsExpressionVisitor() : JsVisitorWithContextImpl() {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun visit(x: JsWhile, ctx: JsContext<*>): Boolean = false
|
||||
override fun visit(x: JsDoWhile, ctx: JsContext<*>): Boolean = false
|
||||
override fun visit(x: JsWhile, ctx: JsContext<*>): Boolean {
|
||||
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: JsArrayLiteral, ctx: JsContext<*>): Boolean = true
|
||||
|
||||
@@ -60,6 +60,14 @@ public var JsNameRef.qualifier: JsExpression?
|
||||
get() = getQualifier()
|
||||
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
|
||||
get() = getIndexExpression()
|
||||
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