Merge pull request #7394 from aibaars/ruby-cfg-expr-post

Ruby: CFG: make all expressions "post-order" nodes
This commit is contained in:
Arthur Baars
2021-12-21 16:36:42 +01:00
committed by GitHub
15 changed files with 327 additions and 262 deletions

View File

@@ -1 +1,20 @@
import codeql.ruby.controlflow.internal.ControlFlowGraphImplShared::Consistency
import codeql.ruby.AST
import codeql.ruby.controlflow.internal.Completion
import codeql.ruby.controlflow.internal.ControlFlowGraphImpl
/**
* All `Expr` nodes are `PostOrderTree`s
*/
query predicate nonPostOrderExpr(Expr e, string cls) {
cls = e.getPrimaryQlClasses() and
not exists(e.getDesugared()) and
not e instanceof BeginExpr and
not e instanceof Namespace and
not e instanceof Toplevel and
exists(AstNode last, Completion c |
last(e, last, c) and
last != e and
c instanceof NormalCompletion
)
}

View File

@@ -361,22 +361,22 @@ class CaseExpr extends ControlExpr instanceof CaseExprImpl {
final Expr getValue() { result = super.getValue() }
/**
* Gets the `n`th branch of this case expression, either a `WhenExpr`, an
* Gets the `n`th branch of this case expression, either a `WhenClause`, an
* `InClause`, or a `StmtSequence`.
*/
final Expr getBranch(int n) { result = super.getBranch(n) }
final AstNode getBranch(int n) { result = super.getBranch(n) }
/**
* Gets a branch of this case expression, either a `WhenExpr`, an
* Gets a branch of this case expression, either a `WhenClause`, an
* `InClause`, or a `StmtSequence`.
*/
final Expr getABranch() { result = this.getBranch(_) }
final AstNode getABranch() { result = this.getBranch(_) }
/** Gets the `n`th `when` branch of this case expression. */
deprecated final WhenExpr getWhenBranch(int n) { result = this.getBranch(n) }
deprecated final WhenClause getWhenBranch(int n) { result = this.getBranch(n) }
/** Gets a `when` branch of this case expression. */
deprecated final WhenExpr getAWhenBranch() { result = this.getABranch() }
deprecated final WhenClause getAWhenBranch() { result = this.getABranch() }
/** Gets the `else` branch of this case expression, if any. */
final StmtSequence getElseBranch() { result = this.getABranch() }
@@ -401,6 +401,11 @@ class CaseExpr extends ControlExpr instanceof CaseExprImpl {
}
}
/**
* DEPRECATED: Use `WhenClause` instead.
*/
deprecated class WhenExpr = WhenClause;
/**
* A `when` branch of a `case` expression.
* ```rb
@@ -409,12 +414,12 @@ class CaseExpr extends ControlExpr instanceof CaseExprImpl {
* end
* ```
*/
class WhenExpr extends Expr, TWhenExpr {
class WhenClause extends AstNode, TWhenClause {
private Ruby::When g;
WhenExpr() { this = TWhenExpr(g) }
WhenClause() { this = TWhenClause(g) }
final override string getAPrimaryQlClass() { result = "WhenExpr" }
final override string getAPrimaryQlClass() { result = "WhenClause" }
/** Gets the body of this case-when expression. */
final Stmt getBody() { toGenerated(result) = g.getBody() }
@@ -461,7 +466,7 @@ class WhenExpr extends Expr, TWhenExpr {
* end
* ```
*/
class InClause extends Expr, TInClause {
class InClause extends AstNode, TInClause {
private Ruby::InClause g;
InClause() { this = TInClause(g) }

View File

@@ -305,7 +305,7 @@ private module Cached {
TUntilExpr(Ruby::Until g) or
TUntilModifierExpr(Ruby::UntilModifier g) or
TVariableReferencePattern(Ruby::VariableReferencePattern g) or
TWhenExpr(Ruby::When g) or
TWhenClause(Ruby::When g) or
TWhileExpr(Ruby::While g) or
TWhileModifierExpr(Ruby::WhileModifier g) or
TYieldCall(Ruby::Yield g)
@@ -344,7 +344,7 @@ private module Cached {
TTernaryIfExpr or TThen or TTokenConstantAccess or TTokenMethodName or TTokenSuperCall or
TToplevel or TTrueLiteral or TUnaryMinusExpr or TUnaryPlusExpr or TUndefStmt or
TUnlessExpr or TUnlessModifierExpr or TUntilExpr or TUntilModifierExpr or
TVariableReferencePattern or TWhenExpr or TWhileExpr or TWhileModifierExpr or TYieldCall;
TVariableReferencePattern or TWhenClause or TWhileExpr or TWhileModifierExpr or TYieldCall;
class TAstNodeSynth =
TAddExprSynth or TAssignExprSynth or TBitwiseAndExprSynth or TBitwiseOrExprSynth or
@@ -511,7 +511,7 @@ private module Cached {
n = TUntilExpr(result) or
n = TUntilModifierExpr(result) or
n = TVariableReferencePattern(result) or
n = TWhenExpr(result) or
n = TWhenClause(result) or
n = TWhileExpr(result) or
n = TWhileModifierExpr(result) or
n = TYieldCall(result)
@@ -657,10 +657,9 @@ class TSelf = TSelfReal or TSelfSynth;
class TDestructuredLhsExpr = TDestructuredLeftAssignment or TLeftAssignmentList;
class TExpr =
TSelf or TArgumentList or TInClause or TRescueClause or TRescueModifierExpr or TPair or
TStringConcatenation or TCall or TBlockArgument or TConstantAccess or TControlExpr or
TWhenExpr or TLiteral or TCallable or TVariableAccess or TStmtSequence or TOperation or
TForwardArgument or TDestructuredLhsExpr;
TSelf or TArgumentList or TRescueClause or TRescueModifierExpr or TPair or TStringConcatenation or
TCall or TBlockArgument or TConstantAccess or TControlExpr or TLiteral or TCallable or
TVariableAccess or TStmtSequence or TOperation or TForwardArgument or TDestructuredLhsExpr;
class TSplatExpr = TSplatExprReal or TSplatExprSynth;

View File

@@ -5,17 +5,17 @@ private import codeql.ruby.ast.internal.AST
abstract class CaseExprImpl extends ControlExpr, TCase {
abstract Expr getValue();
abstract Expr getBranch(int n);
abstract AstNode getBranch(int n);
}
class CaseWhenExpr extends CaseExprImpl, TCaseExpr {
class CaseWhenClause extends CaseExprImpl, TCaseExpr {
private Ruby::Case g;
CaseWhenExpr() { this = TCaseExpr(g) }
CaseWhenClause() { this = TCaseExpr(g) }
final override Expr getValue() { toGenerated(result) = g.getValue() }
final override Expr getBranch(int n) {
final override AstNode getBranch(int n) {
toGenerated(result) = g.getChild(n) or
toGenerated(result) = g.getChild(n)
}
@@ -28,7 +28,7 @@ class CaseMatch extends CaseExprImpl, TCaseMatch {
final override Expr getValue() { toGenerated(result) = g.getValue() }
final override Expr getBranch(int n) {
final override AstNode getBranch(int n) {
toGenerated(result) = g.getClauses(n)
or
n = count(g.getClauses(_)) and toGenerated(result) = g.getElse()

View File

@@ -338,7 +338,7 @@ module ExprNodes {
}
private class CaseExprChildMapping extends ExprChildMapping, CaseExpr {
override predicate relevantChild(Expr e) { e = this.getValue() or e = this.getBranch(_) }
override predicate relevantChild(Expr e) { e = this.getValue() }
}
/** A control-flow node that wraps a `MethodCall` AST expression. */
@@ -356,11 +356,6 @@ module ExprNodes {
/** Gets the expression being compared, if any. */
final ExprCfgNode getValue() { e.hasCfgChild(e.getValue(), this, result) }
/**
* Gets the `n`th branch of this case expression.
*/
final ExprCfgNode getBranch(int n) { e.hasCfgChild(e.getBranch(n), this, result) }
}
private class ConditionalExprChildMapping extends ExprChildMapping, ConditionalExpr {

View File

@@ -107,11 +107,7 @@ abstract class Completion extends TCompletion {
n = any(RescueModifierExpr parent).getBody() and
this = [TSimpleCompletion().(TCompletion), TRaiseCompletion()]
or
(
mayRaise(n)
or
n instanceof CaseMatch and not exists(n.(CaseExpr).getElseBranch())
) and
mayRaise(n) and
(
this = TRaiseCompletion()
or
@@ -209,7 +205,7 @@ private predicate inBooleanContext(AstNode n) {
or
n = any(StmtSequence parent | inBooleanContext(parent)).getLastStmt()
or
exists(CaseExpr c, WhenExpr w |
exists(CaseExpr c, WhenClause w |
not exists(c.getValue()) and
c.getABranch() = w and
w.getPattern(_) = n
@@ -231,7 +227,7 @@ private predicate mustHaveMatchingCompletion(AstNode n) {
private predicate inMatchingContext(AstNode n) {
n = any(RescueClause r).getException(_)
or
exists(CaseExpr c, WhenExpr w |
exists(CaseExpr c, WhenClause w |
exists(c.getValue()) and
c.getABranch() = w and
w.getPattern(_) = n

View File

@@ -107,14 +107,8 @@ module Trees {
}
}
private class ArgumentListTree extends StandardTree, ArgumentList {
private class ArgumentListTree extends StandardPostOrderTree, ArgumentList {
final override ControlFlowTree getChildElement(int i) { result = this.getElement(i) }
final override predicate first(AstNode first) { first(this.getFirstChildElement(), first) }
final override predicate last(AstNode last, Completion c) {
last(this.getLastChildElement(), last, c)
}
}
private class AssignExprTree extends StandardPostOrderTree, AssignExpr {
@@ -252,7 +246,7 @@ module Trees {
)
or
// Last element from any matching `rescue` block continues to the `ensure` block
this.getRescue(_).(RescueTree).lastMatch(result, c) and
last(this.getRescue(_), result, c) and
ensurable = true
or
// If the last `rescue` block does not match, continue to the `ensure` block
@@ -378,35 +372,18 @@ module Trees {
override ControlFlowTree getChildElement(int i) { result = this.getArgument(i) }
}
private class CaseTree extends PreOrderTree, CaseExpr, ASTInternal::TCaseExpr {
private class CaseTree extends PostOrderTree, CaseExpr, ASTInternal::TCaseExpr {
final override predicate propagatesAbnormal(AstNode child) {
child = this.getValue() or child = this.getABranch()
}
final override predicate last(AstNode last, Completion c) {
last(this.getValue(), last, c) and not exists(this.getABranch())
final override predicate first(AstNode first) {
first(this.getValue(), first)
or
last(this.getABranch().(WhenExpr).getBody(), last, c)
or
exists(int i, ControlFlowTree lastBranch |
lastBranch = this.getBranch(i) and
not exists(this.getBranch(i + 1)) and
last(lastBranch, last, c)
)
not exists(this.getValue()) and first(this.getBranch(0), first)
}
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
exists(AstNode next |
pred = this and
first(next, succ) and
c instanceof SimpleCompletion
|
next = this.getValue()
or
not exists(this.getValue()) and
next = this.getBranch(0)
)
or
last(this.getValue(), pred, c) and
first(this.getBranch(0), succ) and
c instanceof SimpleCompletion
@@ -416,20 +393,35 @@ module Trees {
first(this.getBranch(i + 1), succ) and
c.(ConditionalCompletion).getValue() = false
)
or
succ = this and
c instanceof NormalCompletion and
(
last(this.getValue(), pred, c) and not exists(this.getABranch())
or
last(this.getABranch().(WhenClause).getBody(), pred, c)
or
exists(int i, ControlFlowTree lastBranch |
lastBranch = this.getBranch(i) and
not exists(this.getBranch(i + 1)) and
last(lastBranch, pred, c)
)
)
}
}
private class CaseMatchTree extends PreOrderTree, CaseExpr, ASTInternal::TCaseMatch {
private class CaseMatchTree extends PostOrderTree, CaseExpr, ASTInternal::TCaseMatch {
final override predicate propagatesAbnormal(AstNode child) {
child = this.getValue() or child = this.getABranch()
}
final override predicate first(AstNode first) { first(this.getValue(), first) }
final override predicate last(AstNode last, Completion c) {
last(this.getABranch(), last, c) and
not c.(MatchingCompletion).getValue() = false
super.last(last, c)
or
not exists(this.getElseBranch()) and
exists(MatchingCompletion lc, Expr lastBranch |
exists(MatchingCompletion lc, AstNode lastBranch |
lastBranch = max(int i | | this.getBranch(i) order by i) and
lc.getValue() = false and
last(lastBranch, last, lc) and
@@ -439,19 +431,24 @@ module Trees {
}
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
pred = this and
first(this.getValue(), succ) and
c instanceof SimpleCompletion
or
last(this.getValue(), pred, c) and
first(this.getBranch(0), succ) and
c instanceof SimpleCompletion
or
exists(int i, Expr branch | branch = this.getBranch(i) |
exists(int i, AstNode branch | branch = this.getBranch(i) |
last(branch, pred, c) and
first(this.getBranch(i + 1), succ) and
c.(MatchingCompletion).getValue() = false
)
or
succ = this and
c instanceof NormalCompletion and
(
last(this.getABranch(), pred, c) and
not c.(MatchingCompletion).getValue() = false
or
last(this.getElseBranch(), pred, c)
)
}
}
@@ -981,6 +978,8 @@ module Trees {
}
}
private class ForwardedArgumentsTree extends LeafTree, ForwardedArguments { }
private class ForwardParameterTree extends LeafTree, ForwardParameter { }
private class GlobalVariableTree extends LeafTree, GlobalVariableAccess { }
@@ -993,7 +992,7 @@ module Trees {
private class HashSplatParameterTree extends NonDefaultValueParameterTree, HashSplatParameter { }
private class HereDocTree extends StandardPreOrderTree, HereDoc {
private class HereDocTree extends StandardPostOrderTree, HereDoc {
final override ControlFlowTree getChildElement(int i) { result = this.getComponent(i) }
}
@@ -1155,90 +1154,70 @@ module Trees {
private class RedoStmtTree extends LeafTree, RedoStmt { }
private class RescueModifierTree extends PreOrderTree, RescueModifierExpr {
private class RescueModifierTree extends PostOrderTree, RescueModifierExpr {
final override predicate propagatesAbnormal(AstNode child) { child = this.getHandler() }
final override predicate last(AstNode last, Completion c) {
last(this.getBody(), last, c) and
not c instanceof RaiseCompletion
or
last(this.getHandler(), last, c)
}
final override predicate first(AstNode first) { first(this.getBody(), first) }
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
pred = this and
first(this.getBody(), succ) and
c instanceof SimpleCompletion
or
last(this.getBody(), pred, c) and
c instanceof RaiseCompletion and
first(this.getHandler(), succ)
(
c instanceof RaiseCompletion and
first(this.getHandler(), succ)
or
not c instanceof RaiseCompletion and
succ = this
)
or
last(this.getHandler(), pred, c) and
c instanceof NormalCompletion and
succ = this
}
}
private class RescueTree extends PreOrderTree, RescueClause {
final override predicate propagatesAbnormal(AstNode child) { child = this.getAnException() }
private Expr getLastException() {
exists(int i | result = this.getException(i) and not exists(this.getException(i + 1)))
private class RescueTree extends PostOrderTree, RescueClause {
final override predicate propagatesAbnormal(AstNode child) {
child = this.getAnException() or
child = this.getBody()
}
predicate lastMatch(AstNode last, Completion c) {
last(this.getBody(), last, c)
final override predicate first(AstNode first) {
first(this.getException(0), first)
or
not exists(this.getBody()) and
not exists(this.getException(0)) and
(
last(this.getVariableExpr(), last, c)
first(this.getVariableExpr(), first)
or
not exists(this.getVariableExpr()) and
(
last(this.getAnException(), last, c) and
c.(MatchingCompletion).getValue() = true
first(this.getBody(), first)
or
not exists(this.getAnException()) and
last = this and
c.isValidFor(this)
not exists(this.getBody()) and first = this
)
)
}
private Expr getLastException() {
exists(int i | result = this.getException(i) and not exists(this.getException(i + 1)))
}
predicate lastNoMatch(AstNode last, Completion c) {
last(this.getLastException(), last, c) and
c.(MatchingCompletion).getValue() = false
}
final override predicate last(AstNode last, Completion c) {
this.lastNoMatch(last, c)
or
this.lastMatch(last, c)
}
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
exists(AstNode next |
pred = this and
first(next, succ) and
c instanceof SimpleCompletion
|
next = this.getException(0)
or
not exists(this.getException(0)) and
(
next = this.getVariableExpr()
or
not exists(this.getVariableExpr()) and
next = this.getBody()
)
)
or
exists(AstNode next |
last(this.getAnException(), pred, c) and
first(next, succ) and
c.(MatchingCompletion).getValue() = true
|
next = this.getVariableExpr()
last(this.getAnException(), pred, c) and
c.(MatchingCompletion).getValue() = true and
(
first(this.getVariableExpr(), succ)
or
not exists(this.getVariableExpr()) and
next = this.getBody()
(
first(this.getBody(), succ)
or
not exists(this.getBody()) and succ = this
)
)
or
exists(int i |
@@ -1248,8 +1227,16 @@ module Trees {
)
or
last(this.getVariableExpr(), pred, c) and
first(this.getBody(), succ) and
c instanceof NormalCompletion
c instanceof NormalCompletion and
(
first(this.getBody(), succ)
or
not exists(this.getBody()) and succ = this
)
or
last(this.getBody(), pred, c) and
c instanceof NormalCompletion and
succ = this
}
}
@@ -1353,14 +1340,8 @@ module Trees {
}
}
private class StringConcatenationTree extends StandardTree, StringConcatenation {
private class StringConcatenationTree extends StandardPostOrderTree, StringConcatenation {
final override ControlFlowTree getChildElement(int i) { result = this.getString(i) }
final override predicate first(AstNode first) { first(this.getFirstChildElement(), first) }
final override predicate last(AstNode last, Completion c) {
last(this.getLastChildElement(), last, c)
}
}
private class StringlikeLiteralTree extends StandardPostOrderTree, StringlikeLiteral {
@@ -1389,7 +1370,7 @@ module Trees {
final override ControlFlowTree getChildElement(int i) { result = this.getMethodName(i) }
}
private class WhenTree extends PreOrderTree, WhenExpr {
private class WhenTree extends PreOrderTree, WhenClause {
final override predicate propagatesAbnormal(AstNode child) { child = this.getAPattern() }
final Expr getLastPattern() {

View File

@@ -126,7 +126,16 @@ module LocalFlow {
or
nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::ConditionalExprCfgNode).getBranch(_)
or
nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::CaseExprCfgNode).getBranch(_)
exists(CfgNode n, Stmt stmt, CaseExpr c |
c = nodeTo.asExpr().getExpr() and
n = nodeFrom.asExpr() and
n = nodeTo.asExpr().getAPredecessor() and
stmt = n.getNode()
|
stmt = c.getElseBranch() or
stmt = c.getABranch().(InClause).getBody() or
stmt = c.getABranch().(WhenClause).getBody()
)
or
exists(CfgNodes::ExprCfgNode exprTo, ReturningStatementNode n |
nodeFrom = n and

View File

@@ -170,7 +170,7 @@ calls/calls.rb:
# 106| getStmt: [CaseExpr] case ...
# 106| getValue: [MethodCall] call to foo
# 106| getReceiver: [Self, SelfVariableAccess] self
# 107| getBranch: [WhenExpr] when ...
# 107| getBranch: [WhenClause] when ...
# 107| getPattern: [MethodCall] call to bar
# 107| getReceiver: [Self, SelfVariableAccess] self
# 107| getBody: [StmtSequence] then ...
@@ -179,7 +179,7 @@ calls/calls.rb:
# 110| getStmt: [CaseExpr] case ...
# 110| getValue: [MethodCall] call to foo
# 110| getReceiver: [ConstantReadAccess] X
# 111| getBranch: [WhenExpr] when ...
# 111| getBranch: [WhenClause] when ...
# 111| getPattern: [MethodCall] call to bar
# 111| getReceiver: [ConstantReadAccess] X
# 111| getBody: [StmtSequence] then ...
@@ -689,11 +689,11 @@ control/cases.rb:
# 5| getAnOperand/getRightOperand: [IntegerLiteral] 0
# 8| getStmt: [CaseExpr] case ...
# 8| getValue: [LocalVariableAccess] a
# 9| getBranch: [WhenExpr] when ...
# 9| getBranch: [WhenClause] when ...
# 9| getPattern: [LocalVariableAccess] b
# 9| getBody: [StmtSequence] then ...
# 10| getStmt: [IntegerLiteral] 100
# 11| getBranch: [WhenExpr] when ...
# 11| getBranch: [WhenClause] when ...
# 11| getPattern: [LocalVariableAccess] c
# 11| getPattern: [LocalVariableAccess] d
# 11| getBody: [StmtSequence] then ...
@@ -701,19 +701,19 @@ control/cases.rb:
# 13| getBranch/getElseBranch: [StmtSequence] else ...
# 14| getStmt: [IntegerLiteral] 300
# 18| getStmt: [CaseExpr] case ...
# 19| getBranch: [WhenExpr] when ...
# 19| getBranch: [WhenClause] when ...
# 19| getPattern: [GTExpr] ... > ...
# 19| getAnOperand/getGreaterOperand/getLeftOperand/getReceiver: [LocalVariableAccess] a
# 19| getAnOperand/getArgument/getLesserOperand/getRightOperand: [LocalVariableAccess] b
# 19| getBody: [StmtSequence] then ...
# 19| getStmt: [IntegerLiteral] 10
# 20| getBranch: [WhenExpr] when ...
# 20| getBranch: [WhenClause] when ...
# 20| getPattern: [EqExpr] ... == ...
# 20| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] a
# 20| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] b
# 20| getBody: [StmtSequence] then ...
# 20| getStmt: [IntegerLiteral] 20
# 21| getBranch: [WhenExpr] when ...
# 21| getBranch: [WhenClause] when ...
# 21| getPattern: [LTExpr] ... < ...
# 21| getAnOperand/getLeftOperand/getLesserOperand/getReceiver: [LocalVariableAccess] a
# 21| getAnOperand/getArgument/getGreaterOperand/getRightOperand: [LocalVariableAccess] b

View File

@@ -10,10 +10,10 @@ query predicate caseElseBranches(CaseExpr c, StmtSequence elseBranch) {
query predicate caseNoElseBranches(CaseExpr c) { not exists(c.getElseBranch()) }
query predicate caseWhenBranches(CaseExpr c, WhenExpr when, int pIndex, Expr p, StmtSequence body) {
query predicate caseWhenBranches(CaseExpr c, WhenClause when, int pIndex, Expr p, StmtSequence body) {
when = c.getABranch() and
p = when.getPattern(pIndex) and
body = when.getBody()
}
query predicate caseAllBranches(CaseExpr c, int n, Expr branch) { branch = c.getBranch(n) }
query predicate caseAllBranches(CaseExpr c, int n, AstNode branch) { branch = c.getBranch(n) }

View File

@@ -486,7 +486,7 @@ break_ensure.rb:
case.rb:
# 1| enter if_in_case
#-----| -> case ...
#-----| -> self
# 1| enter case.rb
#-----| -> if_in_case
@@ -505,7 +505,7 @@ case.rb:
#-----| -> exit case.rb
# 2| case ...
#-----| -> self
#-----| -> exit if_in_case (normal)
# 2| call to x1
#-----| -> when ...
@@ -521,7 +521,7 @@ case.rb:
#-----| match -> self
# 3| then ...
#-----| -> exit if_in_case (normal)
#-----| -> case ...
# 3| ( ... )
#-----| -> then ...
@@ -552,11 +552,11 @@ case.rb:
#-----| -> 2
# 4| 2
#-----| no-match -> case ...
#-----| match -> self
#-----| no-match -> exit if_in_case (normal)
# 4| then ...
#-----| -> exit if_in_case (normal)
#-----| -> case ...
# 4| call to puts
#-----| -> then ...
@@ -579,10 +579,10 @@ case.rb:
#-----| -> exit case_match
# 8| value
#-----| -> case ...
#-----| -> value
# 9| case ...
#-----| -> value
#-----| -> exit case_match (normal)
# 9| value
#-----| -> in ... then ...
@@ -591,8 +591,8 @@ case.rb:
#-----| -> 0
# 10| 0
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match (normal)
# 11| in ... then ...
#-----| -> 1
@@ -602,7 +602,7 @@ case.rb:
#-----| match -> 3
# 11| then ...
#-----| -> exit case_match (normal)
#-----| -> case ...
# 11| 3
#-----| -> then ...
@@ -615,7 +615,7 @@ case.rb:
#-----| match -> 4
# 12| then ...
#-----| -> exit case_match (normal)
#-----| -> case ...
# 13| 4
#-----| -> then ...
@@ -637,7 +637,7 @@ case.rb:
#-----| -> ... == ...
# 14| then ...
#-----| -> exit case_match (normal)
#-----| -> case ...
# 14| 6
#-----| -> then ...
@@ -659,13 +659,13 @@ case.rb:
#-----| -> ... < ...
# 15| then ...
#-----| -> exit case_match (normal)
#-----| -> case ...
# 15| 7
#-----| -> then ...
# 16| else ...
#-----| -> exit case_match (normal)
#-----| -> case ...
# 16| 8
#-----| -> else ...
@@ -685,10 +685,10 @@ case.rb:
#-----| -> exit case_match_no_match
# 20| value
#-----| -> case ...
#-----| -> value
# 21| case ...
#-----| -> value
#-----| -> exit case_match_no_match (normal)
# 21| value
#-----| -> in ... then ...
@@ -697,8 +697,8 @@ case.rb:
#-----| -> 1
# 22| 1
#-----| match -> case ...
#-----| raise -> exit case_match_no_match (abnormal)
#-----| match -> exit case_match_no_match (normal)
# 26| enter case_match_raise
#-----| -> value
@@ -715,10 +715,10 @@ case.rb:
#-----| -> exit case_match_raise
# 26| value
#-----| -> case ...
#-----| -> value
# 27| case ...
#-----| -> value
#-----| -> exit case_match_raise (normal)
# 27| value
#-----| -> in ... then ...
@@ -730,8 +730,8 @@ case.rb:
#-----| -> x
# 28| -> { ... }
#-----| match -> case ...
#-----| raise -> exit case_match_raise (abnormal)
#-----| match -> exit case_match_raise (normal)
# 28| exit -> { ... }
@@ -765,10 +765,10 @@ case.rb:
#-----| -> exit case_match_array
# 32| value
#-----| -> case ...
#-----| -> value
# 33| case ...
#-----| -> value
#-----| -> exit case_match_array (normal)
# 33| value
#-----| -> in ... then ...
@@ -777,8 +777,8 @@ case.rb:
#-----| -> [ ..., * ]
# 34| [ ..., * ]
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_array (normal)
# 35| in ... then ...
#-----| -> [ ..., * ]
@@ -788,7 +788,7 @@ case.rb:
#-----| match -> x
# 35| x
#-----| match -> exit case_match_array (normal)
#-----| match -> case ...
# 36| in ... then ...
#-----| -> [ ..., * ]
@@ -798,7 +798,7 @@ case.rb:
#-----| match -> x
# 36| x
#-----| match -> exit case_match_array (normal)
#-----| match -> case ...
# 37| in ... then ...
#-----| -> Bar
@@ -824,7 +824,7 @@ case.rb:
#-----| match -> e
# 37| e
#-----| match -> exit case_match_array (normal)
#-----| match -> case ...
# 41| enter case_match_find
#-----| -> value
@@ -841,10 +841,10 @@ case.rb:
#-----| -> exit case_match_find
# 41| value
#-----| -> case ...
#-----| -> value
# 42| case ...
#-----| -> value
#-----| -> exit case_match_find (normal)
# 42| value
#-----| -> in ... then ...
@@ -868,7 +868,7 @@ case.rb:
#-----| raise -> exit case_match_find (abnormal)
# 43| y
#-----| -> exit case_match_find (normal)
#-----| -> case ...
# 47| enter case_match_hash
#-----| -> value
@@ -885,10 +885,10 @@ case.rb:
#-----| -> exit case_match_hash
# 47| value
#-----| -> case ...
#-----| -> value
# 48| case ...
#-----| -> value
#-----| -> exit case_match_hash (normal)
# 48| value
#-----| -> in ... then ...
@@ -912,7 +912,7 @@ case.rb:
#-----| match -> rest
# 49| rest
#-----| -> exit case_match_hash (normal)
#-----| -> case ...
# 50| in ... then ...
#-----| -> Bar
@@ -926,15 +926,15 @@ case.rb:
#-----| no-match -> in ... then ...
# 50| 1
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_hash (normal)
# 51| in ... then ...
#-----| -> Bar
# 51| { ..., ** }
#-----| match -> case ...
#-----| raise -> exit case_match_hash (abnormal)
#-----| match -> exit case_match_hash (normal)
# 51| Bar
#-----| match -> { ..., ** }
@@ -952,10 +952,10 @@ case.rb:
#-----| -> exit case_match_variable
# 55| value
#-----| -> case ...
#-----| -> value
# 56| case ...
#-----| -> value
#-----| -> exit case_match_variable (normal)
# 56| value
#-----| -> in ... then ...
@@ -964,14 +964,14 @@ case.rb:
#-----| -> 5
# 57| 5
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_variable (normal)
# 58| in ... then ...
#-----| -> var
# 58| var
#-----| match -> exit case_match_variable (normal)
#-----| match -> case ...
# 63| enter case_match_underscore
#-----| -> value
@@ -985,10 +985,10 @@ case.rb:
#-----| -> exit case_match_underscore
# 63| value
#-----| -> case ...
#-----| -> value
# 64| case ...
#-----| -> value
#-----| -> exit case_match_underscore (normal)
# 64| value
#-----| -> in ... then ...
@@ -1000,11 +1000,11 @@ case.rb:
#-----| -> 5
# 65| 5
#-----| match -> case ...
#-----| no-match -> _
#-----| match -> exit case_match_underscore (normal)
# 65| _
#-----| match -> exit case_match_underscore (normal)
#-----| match -> case ...
# 69| enter case_match_various
#-----| -> value
@@ -1024,7 +1024,7 @@ case.rb:
#-----| -> foo
# 70| ... = ...
#-----| -> case ...
#-----| -> value
# 70| foo
#-----| -> 42
@@ -1033,7 +1033,7 @@ case.rb:
#-----| -> ... = ...
# 72| case ...
#-----| -> value
#-----| -> exit case_match_various (normal)
# 72| value
#-----| -> in ... then ...
@@ -1042,8 +1042,8 @@ case.rb:
#-----| -> 5
# 73| 5
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 74| in ... then ...
#-----| -> ^...
@@ -1052,22 +1052,22 @@ case.rb:
#-----| -> foo
# 74| foo
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 75| in ... then ...
#-----| -> "string"
# 75| "string"
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 76| in ... then ...
#-----| -> Array
# 76| call to []
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 76| Array
#-----| -> "foo"
@@ -1082,8 +1082,8 @@ case.rb:
#-----| -> Array
# 77| call to []
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 77| Array
#-----| -> :"foo"
@@ -1098,8 +1098,8 @@ case.rb:
#-----| -> /.*abc[0-9]/
# 78| /.*abc[0-9]/
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 79| in ... then ...
#-----| -> 5
@@ -1108,8 +1108,8 @@ case.rb:
#-----| -> 10
# 79| _ .. _
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 79| 10
#-----| -> _ .. _
@@ -1118,8 +1118,8 @@ case.rb:
#-----| -> 10
# 80| _ .. _
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 80| 10
#-----| -> _ .. _
@@ -1131,8 +1131,8 @@ case.rb:
#-----| -> _ .. _
# 81| _ .. _
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 82| in ... then ...
#-----| -> ... => ...
@@ -1145,7 +1145,7 @@ case.rb:
#-----| match -> x
# 82| x
#-----| -> exit case_match_various (normal)
#-----| -> case ...
# 83| in ... then ...
#-----| -> ... | ...
@@ -1154,26 +1154,26 @@ case.rb:
#-----| -> 5
# 83| 5
#-----| match -> case ...
#-----| no-match -> ^...
#-----| match -> exit case_match_various (normal)
# 83| ^...
#-----| -> foo
# 83| foo
#-----| match -> case ...
#-----| no-match -> "string"
#-----| match -> exit case_match_various (normal)
# 83| "string"
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 84| in ... then ...
#-----| -> Foo
# 84| Bar
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 84| Foo
#-----| -> Bar
@@ -1185,8 +1185,8 @@ case.rb:
#-----| -> x
# 85| -> { ... }
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 85| exit -> { ... }
@@ -1209,15 +1209,15 @@ case.rb:
#-----| -> :foo
# 86| :foo
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 87| in ... then ...
#-----| -> :"foo bar"
# 87| :"foo bar"
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 88| in ... then ...
#-----| -> ... | ...
@@ -1226,15 +1226,15 @@ case.rb:
#-----| -> 5
# 88| - ...
#-----| match -> case ...
#-----| no-match -> 10
#-----| match -> exit case_match_various (normal)
# 88| 5
#-----| -> - ...
# 88| + ...
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 88| 10
#-----| -> + ...
@@ -1246,32 +1246,32 @@ case.rb:
#-----| -> nil
# 89| nil
#-----| match -> case ...
#-----| no-match -> self
#-----| match -> exit case_match_various (normal)
# 89| self
#-----| match -> case ...
#-----| no-match -> true
#-----| match -> exit case_match_various (normal)
# 89| true
#-----| match -> case ...
#-----| no-match -> false
#-----| match -> exit case_match_various (normal)
# 89| false
#-----| match -> case ...
#-----| no-match -> __LINE__
#-----| match -> exit case_match_various (normal)
# 89| __LINE__
#-----| match -> case ...
#-----| no-match -> __FILE__
#-----| match -> exit case_match_various (normal)
# 89| __FILE__
#-----| match -> case ...
#-----| no-match -> __ENCODING__
#-----| match -> exit case_match_various (normal)
# 89| __ENCODING__
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 90| in ... then ...
#-----| -> ( ... )
@@ -1283,8 +1283,8 @@ case.rb:
#-----| -> _ .. _
# 90| _ .. _
#-----| match -> case ...
#-----| no-match -> in ... then ...
#-----| match -> exit case_match_various (normal)
# 91| in ... then ...
#-----| -> ( ... )
@@ -1296,20 +1296,20 @@ case.rb:
#-----| -> 0
# 91| 0
#-----| match -> case ...
#-----| no-match -> ""
#-----| match -> exit case_match_various (normal)
# 91| ""
#-----| no-match -> [ ..., * ]
#-----| match -> exit case_match_various (normal)
#-----| match -> case ...
# 91| [ ..., * ]
#-----| match -> case ...
#-----| no-match -> { ..., ** }
#-----| match -> exit case_match_various (normal)
# 91| { ..., ** }
#-----| match -> case ...
#-----| raise -> exit case_match_various (abnormal)
#-----| match -> exit case_match_various (normal)
# 95| enter case_match_guard_no_else
#-----| -> value
@@ -1326,10 +1326,10 @@ case.rb:
#-----| -> exit case_match_guard_no_else
# 95| value
#-----| -> case ...
#-----| -> value
# 96| case ...
#-----| -> value
#-----| -> exit case_match_guard_no_else (normal)
# 96| value
#-----| -> in ... then ...
@@ -1351,7 +1351,7 @@ case.rb:
#-----| -> ... == ...
# 97| then ...
#-----| -> exit case_match_guard_no_else (normal)
#-----| -> case ...
# 97| 6
#-----| -> then ...
@@ -1703,7 +1703,7 @@ cfg.rb:
#-----| false -> if ...
# 39| call to puts
#-----| -> case ...
#-----| -> 10
# 39| self
#-----| -> 42
@@ -1712,7 +1712,7 @@ cfg.rb:
#-----| -> call to puts
# 41| case ...
#-----| -> 10
#-----| -> when ...
# 41| 10
#-----| -> when ...
@@ -1776,7 +1776,7 @@ cfg.rb:
#-----| -> call to puts
# 47| case ...
#-----| -> when ...
#-----| -> chained
# 48| when ...
#-----| -> b
@@ -1792,7 +1792,7 @@ cfg.rb:
#-----| -> ... == ...
# 48| then ...
#-----| -> chained
#-----| -> case ...
# 48| call to puts
#-----| -> then ...
@@ -1817,7 +1817,7 @@ cfg.rb:
#-----| -> ... == ...
# 49| ... > ...
#-----| false -> chained
#-----| false -> case ...
#-----| true -> self
# 49| b
@@ -1827,7 +1827,7 @@ cfg.rb:
#-----| -> ... > ...
# 49| then ...
#-----| -> chained
#-----| -> case ...
# 49| call to puts
#-----| -> then ...
@@ -1847,6 +1847,9 @@ cfg.rb:
# 52| "a"
#-----| -> chained
# 52| "..." "..."
#-----| -> ... = ...
# 52| "#{...}"
#-----| -> "string"
@@ -1857,7 +1860,7 @@ cfg.rb:
#-----| -> #{...}
# 52| "string"
#-----| -> ... = ...
#-----| -> "..." "..."
# 54| ... = ...
#-----| -> Silly
@@ -2416,13 +2419,13 @@ cfg.rb:
#-----| -> b
# 108| self
#-----| -> <<SQL
#-----| -> table
# 108| ( ... )
#-----| -> call to puts
# 108| <<SQL
#-----| -> table
#-----| -> ( ... )
# 109| #{...}
#-----| -> type
@@ -2431,7 +2434,7 @@ cfg.rb:
#-----| -> #{...}
# 110| #{...}
#-----| -> ( ... )
#-----| -> <<SQL
# 110| type
#-----| -> #{...}
@@ -2641,23 +2644,23 @@ cfg.rb:
#-----| -> EmptyModule
# 134| EmptyModule
#-----| -> ... rescue ...
#-----| -> 1
# 136| ... / ...
#-----| -> ... rescue ...
#-----| raise -> self
#-----| -> __synth__0
# 136| 1
#-----| -> 0
# 136| ... rescue ...
#-----| -> 1
#-----| -> __synth__0
# 136| 0
#-----| -> ... / ...
# 136| call to puts
#-----| -> __synth__0
#-----| -> ... rescue ...
# 136| self
#-----| -> "div by zero"
@@ -2704,6 +2707,9 @@ cfg.rb:
# 138| __synth__0
#-----| -> -1
# 138| ..., ...
#-----| -> * ...
# 138| 1
#-----| -> 2
@@ -2720,7 +2726,7 @@ cfg.rb:
#-----| -> 3
# 138| 3
#-----| -> * ...
#-----| -> ..., ...
# 140| M
#-----| -> Constant
@@ -3270,6 +3276,9 @@ cfg.rb:
#-----| -> b
# 197| b
#-----| -> ...
# 197| ...
#-----| -> call to bar
desugar.rb:
@@ -4905,7 +4914,7 @@ raise.rb:
#-----| true -> self
# 17| call to raise
#-----| raise -> rescue ...
#-----| raise -> ExceptionA
# 17| self
#-----| -> ExceptionA
@@ -4914,14 +4923,14 @@ raise.rb:
#-----| -> call to raise
# 19| rescue ...
#-----| -> ExceptionA
#-----| -> self
# 19| ExceptionA
#-----| match -> self
#-----| raise -> exit m2 (abnormal)
# 19| then ...
#-----| -> self
#-----| -> rescue ...
# 20| call to puts
#-----| -> then ...
@@ -4963,7 +4972,7 @@ raise.rb:
#-----| true -> self
# 28| call to raise
#-----| raise -> rescue ...
#-----| raise -> self
# 28| self
#-----| -> ExceptionA
@@ -4975,7 +4984,7 @@ raise.rb:
#-----| -> self
# 30| then ...
#-----| -> self
#-----| -> rescue ...
# 31| call to puts
#-----| -> then ...
@@ -5017,7 +5026,7 @@ raise.rb:
#-----| true -> self
# 39| call to raise
#-----| raise -> rescue ...
#-----| raise -> e
# 39| self
#-----| -> ExceptionA
@@ -5026,13 +5035,13 @@ raise.rb:
#-----| -> call to raise
# 41| rescue ...
#-----| -> e
#-----| -> self
# 41| e
#-----| -> self
# 41| then ...
#-----| -> self
#-----| -> rescue ...
# 42| call to puts
#-----| -> then ...
@@ -5074,7 +5083,7 @@ raise.rb:
#-----| true -> self
# 50| call to raise
#-----| raise -> rescue ...
#-----| raise -> e
# 50| self
#-----| -> ExceptionA
@@ -5083,10 +5092,10 @@ raise.rb:
#-----| -> call to raise
# 52| rescue ...
#-----| -> e
#-----| -> self
# 52| e
#-----| -> self
#-----| -> rescue ...
# 54| call to puts
#-----| -> exit m5 (normal)
@@ -5122,7 +5131,7 @@ raise.rb:
#-----| true -> self
# 60| call to raise
#-----| raise -> rescue ...
#-----| raise -> ExceptionA
# 60| self
#-----| -> ExceptionA
@@ -5131,7 +5140,7 @@ raise.rb:
#-----| -> call to raise
# 62| rescue ...
#-----| -> ExceptionA
#-----| -> self
# 62| ExceptionA
#-----| no-match -> ExceptionB
@@ -5145,7 +5154,7 @@ raise.rb:
#-----| -> self
# 62| then ...
#-----| -> self
#-----| -> rescue ...
# 63| call to puts
#-----| -> then ...
@@ -5804,7 +5813,7 @@ raise.rb:
#-----| true -> self
# 131| call to raise
#-----| raise -> rescue ...
#-----| raise -> ExceptionA
# 131| self
#-----| -> ExceptionA
@@ -5813,21 +5822,21 @@ raise.rb:
#-----| -> call to raise
# 133| rescue ...
#-----| -> ExceptionA
#-----| -> self
# 133| ExceptionA
#-----| no-match -> rescue ...
#-----| match -> self
#-----| match -> rescue ...
#-----| no-match -> ExceptionB
# 134| rescue ...
#-----| -> ExceptionB
#-----| -> self
# 134| ExceptionB
#-----| match -> self
#-----| raise -> [ensure: raise] self
# 134| then ...
#-----| -> self
#-----| -> rescue ...
# 135| call to puts
#-----| -> then ...

View File

@@ -191,6 +191,7 @@ positionalArguments
| cfg.rb:191:3:191:10 | yield ... | cfg.rb:191:9:191:10 | 42 |
| cfg.rb:194:16:194:21 | call to puts | cfg.rb:194:21:194:21 | x |
| cfg.rb:197:3:197:13 | call to bar | cfg.rb:197:7:197:7 | b |
| cfg.rb:197:3:197:13 | call to bar | cfg.rb:197:10:197:12 | ... |
| desugar.rb:2:5:2:6 | ... + ... | desugar.rb:2:8:2:8 | 1 |
| desugar.rb:6:3:6:13 | call to count= | desugar.rb:6:3:6:13 | ... = ... |
| desugar.rb:10:3:10:10 | call to []= | desugar.rb:10:3:10:10 | ... = ... |

View File

@@ -70,3 +70,33 @@
| local_dataflow.rb:50:18:50:18 | [post] x | local_dataflow.rb:51:20:51:20 | x |
| local_dataflow.rb:50:18:50:18 | x | local_dataflow.rb:51:20:51:20 | x |
| local_dataflow.rb:51:9:51:15 | "break" | local_dataflow.rb:51:3:51:15 | break |
| local_dataflow.rb:60:15:60:15 | x | local_dataflow.rb:60:15:60:15 | x |
| local_dataflow.rb:60:15:60:15 | x | local_dataflow.rb:61:12:61:12 | x |
| local_dataflow.rb:61:7:68:5 | case ... | local_dataflow.rb:61:3:68:5 | ... = ... |
| local_dataflow.rb:61:12:61:12 | x | local_dataflow.rb:63:15:63:15 | x |
| local_dataflow.rb:61:12:61:12 | x | local_dataflow.rb:65:6:65:6 | x |
| local_dataflow.rb:61:12:61:12 | x | local_dataflow.rb:67:5:67:5 | x |
| local_dataflow.rb:61:12:61:12 | x | local_dataflow.rb:69:12:69:12 | x |
| local_dataflow.rb:62:10:62:15 | then ... | local_dataflow.rb:61:7:68:5 | case ... |
| local_dataflow.rb:62:15:62:15 | 3 | local_dataflow.rb:62:10:62:15 | then ... |
| local_dataflow.rb:63:10:63:15 | then ... | local_dataflow.rb:61:7:68:5 | case ... |
| local_dataflow.rb:63:15:63:15 | x | local_dataflow.rb:63:10:63:15 | then ... |
| local_dataflow.rb:63:15:63:15 | x | local_dataflow.rb:69:12:69:12 | x |
| local_dataflow.rb:64:9:65:6 | then ... | local_dataflow.rb:61:7:68:5 | case ... |
| local_dataflow.rb:65:6:65:6 | x | local_dataflow.rb:64:9:65:6 | then ... |
| local_dataflow.rb:65:6:65:6 | x | local_dataflow.rb:69:12:69:12 | x |
| local_dataflow.rb:66:3:67:5 | else ... | local_dataflow.rb:61:7:68:5 | case ... |
| local_dataflow.rb:67:5:67:5 | x | local_dataflow.rb:66:3:67:5 | else ... |
| local_dataflow.rb:67:5:67:5 | x | local_dataflow.rb:69:12:69:12 | x |
| local_dataflow.rb:69:7:76:5 | case ... | local_dataflow.rb:69:3:76:5 | ... = ... |
| local_dataflow.rb:69:12:69:12 | x | local_dataflow.rb:71:13:71:13 | x |
| local_dataflow.rb:69:12:69:12 | x | local_dataflow.rb:73:7:73:7 | x |
| local_dataflow.rb:69:12:69:12 | x | local_dataflow.rb:75:6:75:6 | x |
| local_dataflow.rb:70:8:70:13 | then ... | local_dataflow.rb:69:7:76:5 | case ... |
| local_dataflow.rb:70:13:70:13 | 4 | local_dataflow.rb:70:8:70:13 | then ... |
| local_dataflow.rb:71:8:71:13 | then ... | local_dataflow.rb:69:7:76:5 | case ... |
| local_dataflow.rb:71:13:71:13 | x | local_dataflow.rb:71:8:71:13 | then ... |
| local_dataflow.rb:72:7:73:7 | then ... | local_dataflow.rb:69:7:76:5 | case ... |
| local_dataflow.rb:73:7:73:7 | x | local_dataflow.rb:72:7:73:7 | then ... |
| local_dataflow.rb:74:3:75:6 | else ... | local_dataflow.rb:69:7:76:5 | case ... |
| local_dataflow.rb:75:6:75:6 | x | local_dataflow.rb:74:3:75:6 | else ... |

View File

@@ -12,6 +12,7 @@ ret
| local_dataflow.rb:50:3:50:13 | next |
| local_dataflow.rb:51:3:51:15 | break |
| local_dataflow.rb:52:3:52:10 | "normal" |
| local_dataflow.rb:69:3:76:5 | ... = ... |
arg
| local_dataflow.rb:3:8:3:10 | self | local_dataflow.rb:3:8:3:10 | call to p | -1 |
| local_dataflow.rb:3:10:3:10 | a | local_dataflow.rb:3:8:3:10 | call to p | 0 |

View File

@@ -56,3 +56,23 @@ foo([1, 2, 3])
def foo x
end
def test_case x
y = case x
when 1 then 3
when 2 then x
when 3
x
else
x
end
z = case x
in 1 then 4
in 2 then x
in 3
x
else
x
end
end