Merge pull request #116 from github/aibaars/cfg-loop-post-order

CFG: make loop expressions post order
This commit is contained in:
Arthur Baars
2021-02-08 09:53:25 +01:00
committed by GitHub
4 changed files with 131 additions and 108 deletions

View File

@@ -54,6 +54,9 @@ private predicate nestedEnsureCompletion(Completion outer, int nestLevel) {
pragma[noinline]
private predicate completionIsValidForStmt(AstNode n, Completion c) {
n instanceof In and
c instanceof EmptinessCompletion
or
n instanceof Break and
c = TBreakCompletion()
or

View File

@@ -339,7 +339,7 @@ private class LeftToRightPostOrderTree extends StandardPostOrderTree, LeftToRigh
}
private class LeftToRightPreOrderNodes =
@alias or @block_parameters or @class or @do or @else or @ensure or @in or @lambda_parameters or
@alias or @block_parameters or @class or @do or @else or @ensure or @lambda_parameters or
@method_parameters or @pattern or @program or @then or @undef or @yield;
private class LeftToRightPreOrderTree extends StandardPreOrderTree, LeftToRightPreOrderNodes {
@@ -347,7 +347,6 @@ private class LeftToRightPreOrderTree extends StandardPreOrderTree, LeftToRightP
this instanceof BlockParameters or
this instanceof Do or
this instanceof Else or
this instanceof In or
this instanceof LambdaParameters or
this instanceof MethodParameters or
this instanceof Pattern or
@@ -593,66 +592,71 @@ module Trees {
* ```
* args
* |
* for------<-----
* in------<-----
* / \ \
* / \ |
* / \ |
* / \ |
* empty non-empty |
* | \ |
* puts "done" \ |
* arg |
* | |
* puts arg |
* for \ |
* | arg |
* | | |
* puts "done" puts arg |
* \___/
* ```
*/
private class ForTree extends ControlFlowTree, For {
private class ForTree extends PostOrderTree, For {
final override predicate propagatesAbnormal(AstNode child) {
child = this.getPattern() or child = this.getValue()
child = this.getPattern() or child = this.getArray()
}
final override predicate first(AstNode node) { node = this.getValue() }
final override predicate first(AstNode first) { first(this.getArray(), first) }
final override predicate last(AstNode last, Completion c) {
last = this and
c.(EmptinessCompletion).getValue() = true
or
last(this.getBody(), last, c) and
not c.continuesLoop() and
not c instanceof BreakCompletion and
not c instanceof RedoCompletion
or
last(this.getBody(), last, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion())
}
private In getIn() { result = this.getValue() }
private UnderscoreArg getArray() { result = this.getValue().getChild() }
/**
* for pattern in value do body end
* for pattern in array do body end
* ```
* value +-> for +--[non empty]--> pattern -> body -> for
* |--[empty]--> exit
* array +-> in +--[non empty]--> pattern -> body -> in
* |--[empty]--> for
* ```
*/
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
last(this.getValue(), pred, c) and
succ = this and
last(this.getArray(), pred, c) and
first(this.getIn(), succ) and
c instanceof SimpleCompletion
or
pred = this and
last(this.getIn(), pred, c) and
first(this.getPattern(), succ) and
c.(EmptinessCompletion).getValue() = false
or
first(this.getBody(), succ) and
last(this.getPattern(), pred, c) and
first(this.getBody(), succ) and
c instanceof NormalCompletion
or
last(this.getBody(), pred, c) and
succ = this and
first(this.getIn(), succ) and
c.continuesLoop()
or
last(this.getBody(), pred, c) and
first(this.getBody(), succ) and
c instanceof RedoCompletion
or
succ = this and
(
last(this.getIn(), pred, c) and
c.(EmptinessCompletion).getValue() = true
or
last(this.getBody(), pred, c) and
not c.continuesLoop() and
not c instanceof BreakCompletion and
not c instanceof RedoCompletion
or
last(this.getBody(), pred, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion())
)
}
}
@@ -712,6 +716,8 @@ module Trees {
}
}
private class InTree extends LeafTree, In { }
private class InstanceVariableTree extends LeafTree, InstanceVariable { }
private class IntegerTree extends LeafTree, Integer { }
@@ -1224,26 +1230,12 @@ module Trees {
}
}
private class ConditionalLoopTree extends PreOrderTree, ConditionalLoopAstNode {
private class ConditionalLoopTree extends PostOrderTree, ConditionalLoopAstNode {
final override predicate propagatesAbnormal(AstNode child) { child = this.getConditionNode() }
final override predicate last(AstNode last, Completion c) {
last(this.getConditionNode(), last, c) and
this.endLoop(c)
or
last(this.getBodyNode(), last, c) and
not c.continuesLoop() and
not c instanceof BreakCompletion and
not c instanceof RedoCompletion
or
last(this.getBodyNode(), last, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion())
}
final override predicate first(AstNode first) { first(this.getConditionNode(), first) }
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
pred = this and
first(this.getConditionNode(), succ) and
c instanceof SimpleCompletion
or
last(this.getConditionNode(), pred, c) and
this.continueLoop(c) and
first(this.getBodyNode(), succ)
@@ -1255,6 +1247,19 @@ module Trees {
last(this.getBodyNode(), pred, c) and
first(this.getBodyNode(), succ) and
c instanceof RedoCompletion
or
succ = this and
(
last(this.getConditionNode(), pred, c) and
this.endLoop(c)
or
last(this.getBodyNode(), pred, c) and
not c.continuesLoop() and
not c instanceof BreakCompletion and
not c instanceof RedoCompletion
or
last(this.getBodyNode(), pred, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion())
)
}
}
}