mirror of
https://github.com/github/codeql.git
synced 2026-04-25 16:55:19 +02:00
Port CFG implementation to public AST interface
This commit is contained in:
@@ -440,6 +440,9 @@ class ConditionalLoop extends Loop, TConditionalLoop {
|
||||
or
|
||||
pred = "getCondition" and result = this.getCondition()
|
||||
}
|
||||
|
||||
/** Holds if the loop body is entered when the condition is `condValue`. */
|
||||
predicate entersLoopWhenConditionIs(boolean condValue) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -463,6 +466,12 @@ class WhileExpr extends ConditionalLoop, TWhileExpr {
|
||||
|
||||
final override Expr getCondition() { toGenerated(result) = g.getCondition() }
|
||||
|
||||
/**
|
||||
* Holds if the loop body is entered when the condition is `condValue`. For
|
||||
* `while` loops, this holds when `condValue` is true.
|
||||
*/
|
||||
final override predicate entersLoopWhenConditionIs(boolean condValue) { condValue = true }
|
||||
|
||||
final override string toString() { result = "while ..." }
|
||||
}
|
||||
|
||||
@@ -487,6 +496,12 @@ class UntilExpr extends ConditionalLoop, TUntilExpr {
|
||||
|
||||
final override Expr getCondition() { toGenerated(result) = g.getCondition() }
|
||||
|
||||
/**
|
||||
* Holds if the loop body is entered when the condition is `condValue`. For
|
||||
* `until` loops, this holds when `condValue` is false.
|
||||
*/
|
||||
final override predicate entersLoopWhenConditionIs(boolean condValue) { condValue = false }
|
||||
|
||||
final override string toString() { result = "until ..." }
|
||||
}
|
||||
|
||||
@@ -505,6 +520,12 @@ class WhileModifierExpr extends ConditionalLoop, TWhileModifierExpr {
|
||||
|
||||
final override Expr getCondition() { toGenerated(result) = g.getCondition() }
|
||||
|
||||
/**
|
||||
* Holds if the loop body is entered when the condition is `condValue`. For
|
||||
* `while`-modifier loops, this holds when `condValue` is true.
|
||||
*/
|
||||
final override predicate entersLoopWhenConditionIs(boolean condValue) { condValue = true }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "WhileModifierExpr" }
|
||||
|
||||
final override string toString() { result = "... while ..." }
|
||||
@@ -525,6 +546,12 @@ class UntilModifierExpr extends ConditionalLoop, TUntilModifierExpr {
|
||||
|
||||
final override Expr getCondition() { toGenerated(result) = g.getCondition() }
|
||||
|
||||
/**
|
||||
* Holds if the loop body is entered when the condition is `condValue`. For
|
||||
* `until`-modifier loops, this holds when `condValue` is false.
|
||||
*/
|
||||
final override predicate entersLoopWhenConditionIs(boolean condValue) { condValue = false }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "UntilModifierExpr" }
|
||||
|
||||
final override string toString() { result = "... until ..." }
|
||||
|
||||
@@ -4,7 +4,7 @@ private import internal.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/** A callable. */
|
||||
class Callable extends Expr, CfgScope, TCallable {
|
||||
class Callable extends Expr, TCallable {
|
||||
/** Gets the number of parameters of this callable. */
|
||||
final int getNumberOfParameters() { result = count(this.getAParameter()) }
|
||||
|
||||
|
||||
@@ -47,7 +47,8 @@ class Toplevel extends ModuleBase, TToplevel {
|
||||
* Gets the `n`th `BEGIN` block.
|
||||
*/
|
||||
final BeginBlock getBeginBlock(int n) {
|
||||
toGenerated(result) = rank[n](int i, Generated::BeginBlock b | b = g.getChild(i) | b order by i)
|
||||
toGenerated(result) =
|
||||
rank[n + 1](int i, Generated::BeginBlock b | b = g.getChild(i) | b order by i)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,7 @@ class Stmt extends AstNode, TStmt {
|
||||
CfgNodes::AstCfgNode getAControlFlowNode() { result.getNode() = this }
|
||||
|
||||
/** Gets the control-flow scope of this statement, if any. */
|
||||
CfgScope getCfgScope() { result = getCfgScope(toGenerated(this)) }
|
||||
CfgScope getCfgScope() { result = getCfgScope(this) }
|
||||
|
||||
/** Gets the enclosing callable, if any. */
|
||||
Callable getEnclosingCallable() { result = this.getCfgScope() }
|
||||
|
||||
@@ -67,7 +67,7 @@ class AstCfgNode extends CfgNode, TAstCfgNode {
|
||||
private Splits splits;
|
||||
private AstNode n;
|
||||
|
||||
AstCfgNode() { this = TAstCfgNode(toGenerated(n), splits) }
|
||||
AstCfgNode() { this = TAstCfgNode(n, splits) }
|
||||
|
||||
final override AstNode getNode() { result = n }
|
||||
|
||||
@@ -132,7 +132,7 @@ abstract private class ExprChildMapping extends Expr {
|
||||
|
||||
pragma[noinline]
|
||||
private BasicBlock getABasicBlockInScope() {
|
||||
result.getANode() = TAstCfgNode(toGenerated(this.getAChildStar()), _)
|
||||
result.getANode() = TAstCfgNode(this.getAChildStar(), _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/** Provides classes representing the control flow graph. */
|
||||
|
||||
private import codeql.Locations
|
||||
private import codeql_ruby.AST as AST
|
||||
private import codeql_ruby.ast.internal.AST as ASTInternal
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.controlflow.BasicBlocks
|
||||
private import SuccessorTypes
|
||||
private import internal.ControlFlowGraphImpl
|
||||
@@ -10,14 +9,14 @@ private import internal.Splitting
|
||||
private import internal.Completion
|
||||
|
||||
/** An AST node with an associated control-flow graph. */
|
||||
class CfgScope extends AST::AstNode {
|
||||
CfgScope() { ASTInternal::toGenerated(this) instanceof CfgScope::Range_ }
|
||||
class CfgScope extends AstNode {
|
||||
CfgScope() { this instanceof CfgScope::Range_ }
|
||||
|
||||
/** Gets the CFG scope that this scope is nested under, if any. */
|
||||
final CfgScope getOuterCfgScope() {
|
||||
exists(AST::AstNode parent |
|
||||
exists(AstNode parent |
|
||||
parent = this.getParent() and
|
||||
result = getCfgScope(ASTInternal::toGenerated(parent))
|
||||
result = getCfgScope(parent)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -35,7 +34,7 @@ class CfgNode extends TCfgNode {
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets the AST node that this node corresponds to, if any. */
|
||||
AST::AstNode getNode() { none() }
|
||||
AstNode getNode() { none() }
|
||||
|
||||
/** Gets the location of this control flow node. */
|
||||
Location getLocation() { none() }
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
/**
|
||||
* Provides various helper classes for AST nodes. The definitions in this file
|
||||
* will likely be part of the hand-written user-facing AST layer.
|
||||
*/
|
||||
|
||||
private import codeql_ruby.ast.internal.TreeSitter::Generated
|
||||
private import codeql_ruby.controlflow.internal.Completion
|
||||
|
||||
class LogicalNotAstNode extends Unary {
|
||||
AstNode operand;
|
||||
|
||||
LogicalNotAstNode() {
|
||||
this.getOperator().toString() in ["!", "not"] and
|
||||
operand = this.getOperand()
|
||||
}
|
||||
}
|
||||
|
||||
class LogicalAndAstNode extends Binary {
|
||||
AstNode left;
|
||||
AstNode right;
|
||||
|
||||
LogicalAndAstNode() {
|
||||
this.getOperator().toString() in ["&&", "and"] and
|
||||
left = this.getLeft() and
|
||||
right = this.getRight()
|
||||
}
|
||||
|
||||
AstNode getAnOperand() { result in [left, right] }
|
||||
}
|
||||
|
||||
class LogicalOrAstNode extends Binary {
|
||||
AstNode left;
|
||||
AstNode right;
|
||||
|
||||
LogicalOrAstNode() {
|
||||
this.getOperator().toString() in ["||", "or"] and
|
||||
left = this.getLeft() and
|
||||
right = this.getRight()
|
||||
}
|
||||
|
||||
AstNode getAnOperand() { result in [left, right] }
|
||||
}
|
||||
|
||||
private class If_or_elisif =
|
||||
@if or @elsif or @conditional or @if_modifier or @unless or @unless_modifier;
|
||||
|
||||
class IfElsifAstNode extends AstNode, If_or_elisif {
|
||||
AstNode getConditionNode() { none() }
|
||||
|
||||
AstNode getBranch(boolean b) { none() }
|
||||
}
|
||||
|
||||
private class IfAstNode extends IfElsifAstNode, If {
|
||||
override AstNode getConditionNode() { result = this.getCondition() }
|
||||
|
||||
override AstNode getBranch(boolean b) {
|
||||
b = true and result = this.getConsequence()
|
||||
or
|
||||
b = false and result = this.getAlternative()
|
||||
}
|
||||
}
|
||||
|
||||
private class ElsifAstNode extends IfElsifAstNode, Elsif {
|
||||
override AstNode getConditionNode() { result = this.getCondition() }
|
||||
|
||||
override AstNode getBranch(boolean b) {
|
||||
b = true and result = this.getConsequence()
|
||||
or
|
||||
b = false and result = this.getAlternative()
|
||||
}
|
||||
}
|
||||
|
||||
private class ConditionalAstNode extends IfElsifAstNode, Conditional {
|
||||
override AstNode getConditionNode() { result = this.getCondition() }
|
||||
|
||||
override AstNode getBranch(boolean b) {
|
||||
b = true and result = this.getConsequence()
|
||||
or
|
||||
b = false and result = this.getAlternative()
|
||||
}
|
||||
}
|
||||
|
||||
private class IfModifierAstNode extends IfElsifAstNode, IfModifier {
|
||||
override AstNode getConditionNode() { result = this.getCondition() }
|
||||
|
||||
override AstNode getBranch(boolean b) { b = true and result = this.getBody() }
|
||||
}
|
||||
|
||||
private class UnlessAstNode extends IfElsifAstNode, Unless {
|
||||
override AstNode getConditionNode() { result = this.getCondition() }
|
||||
|
||||
override AstNode getBranch(boolean b) {
|
||||
b = false and result = this.getConsequence()
|
||||
or
|
||||
b = true and result = this.getAlternative()
|
||||
}
|
||||
}
|
||||
|
||||
private class UnlessModifierAstNode extends IfElsifAstNode, UnlessModifier {
|
||||
override AstNode getConditionNode() { result = this.getCondition() }
|
||||
|
||||
override AstNode getBranch(boolean b) { b = false and result = this.getBody() }
|
||||
}
|
||||
|
||||
private class CondLoop = @while or @while_modifier or @until or @until_modifier;
|
||||
|
||||
class ConditionalLoopAstNode extends AstNode, CondLoop {
|
||||
AstNode getConditionNode() { none() }
|
||||
|
||||
AstNode getBodyNode() { none() }
|
||||
|
||||
predicate continueLoop(BooleanCompletion c) { c instanceof TrueCompletion }
|
||||
|
||||
final predicate endLoop(BooleanCompletion c) { continueLoop(c.getDual()) }
|
||||
}
|
||||
|
||||
private class WhileLoop extends ConditionalLoopAstNode, While {
|
||||
override UnderscoreStatement getConditionNode() { result = this.getCondition() }
|
||||
|
||||
override Do getBodyNode() { result = this.getBody() }
|
||||
}
|
||||
|
||||
private class WhileModifierLoop extends ConditionalLoopAstNode, WhileModifier {
|
||||
override AstNode getConditionNode() { result = this.getCondition() }
|
||||
|
||||
override UnderscoreStatement getBodyNode() { result = this.getBody() }
|
||||
}
|
||||
|
||||
private class UntilLoop extends ConditionalLoopAstNode, Until {
|
||||
override UnderscoreStatement getConditionNode() { result = this.getCondition() }
|
||||
|
||||
override Do getBodyNode() { result = this.getBody() }
|
||||
|
||||
override predicate continueLoop(BooleanCompletion c) { c instanceof FalseCompletion }
|
||||
}
|
||||
|
||||
private class UntilModifierLoop extends ConditionalLoopAstNode, UntilModifier {
|
||||
override AstNode getConditionNode() { result = this.getCondition() }
|
||||
|
||||
override UnderscoreStatement getBodyNode() { result = this.getBody() }
|
||||
|
||||
override predicate continueLoop(BooleanCompletion c) { c instanceof FalseCompletion }
|
||||
}
|
||||
|
||||
class ParenthesizedStatement extends ParenthesizedStatements {
|
||||
ParenthesizedStatement() { strictcount(int i | exists(this.getChild(i))) = 1 }
|
||||
|
||||
AstNode getChild() { result = this.getChild(0) }
|
||||
}
|
||||
@@ -49,7 +49,7 @@ private predicate nestedEnsureCompletion(Completion outer, int nestLevel) {
|
||||
or
|
||||
outer = TExitCompletion()
|
||||
) and
|
||||
nestLevel = any(Trees::RescueEnsureBlockTree t).nestLevel()
|
||||
nestLevel = any(Trees::BodyStmtTree t).getNestLevel()
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
@@ -206,7 +206,7 @@ private predicate inMatchingContext(AstNode n) {
|
||||
w.getPattern(_) = n
|
||||
)
|
||||
or
|
||||
toGenerated(n).(Trees::DefaultValueParameterTree).hasDefaultValue()
|
||||
n.(Trees::DefaultValueParameterTree).hasDefaultValue()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,9 +2,7 @@
|
||||
* Provides classes and predicates relevant for splitting the control flow graph.
|
||||
*/
|
||||
|
||||
private import codeql_ruby.ast.internal.TreeSitter::Generated
|
||||
private import codeql_ruby.ast.internal.AST as ASTInternal
|
||||
private import codeql_ruby.AST as AST
|
||||
private import codeql_ruby.AST
|
||||
private import Completion
|
||||
private import ControlFlowGraphImpl
|
||||
private import SuccessorTypes
|
||||
@@ -18,13 +16,13 @@ private module Cached {
|
||||
cached
|
||||
newtype TSplitKind =
|
||||
TConditionalCompletionSplitKind() or
|
||||
TEnsureSplitKind(int nestLevel) { nestLevel = any(Trees::RescueEnsureBlockTree t).nestLevel() }
|
||||
TEnsureSplitKind(int nestLevel) { nestLevel = any(Trees::BodyStmtTree t).getNestLevel() }
|
||||
|
||||
cached
|
||||
newtype TSplit =
|
||||
TConditionalCompletionSplit(ConditionalCompletion c) or
|
||||
TEnsureSplit(EnsureSplitting::EnsureSplitType type, int nestLevel) {
|
||||
nestLevel = any(Trees::RescueEnsureBlockTree t).nestLevel()
|
||||
nestLevel = any(Trees::BodyStmtTree t).getNestLevel()
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -219,28 +217,19 @@ private module ConditionalCompletionSplitting {
|
||||
succ(pred, succ, c) and
|
||||
last(succ, _, completion) and
|
||||
(
|
||||
last(ASTInternal::toGenerated(ASTInternal::fromGenerated(succ).(AST::NotExpr).getOperand()),
|
||||
pred, c) and
|
||||
last(succ.(NotExpr).getOperand(), pred, c) and
|
||||
completion.(BooleanCompletion).getDual() = c
|
||||
or
|
||||
last(ASTInternal::toGenerated(ASTInternal::fromGenerated(succ)
|
||||
.(AST::LogicalAndExpr)
|
||||
.getAnOperand()), pred, c) and
|
||||
last(succ.(LogicalAndExpr).getAnOperand(), pred, c) and
|
||||
completion = c
|
||||
or
|
||||
last(ASTInternal::toGenerated(ASTInternal::fromGenerated(succ)
|
||||
.(AST::LogicalOrExpr)
|
||||
.getAnOperand()), pred, c) and
|
||||
last(succ.(LogicalOrExpr).getAnOperand(), pred, c) and
|
||||
completion = c
|
||||
or
|
||||
last(ASTInternal::toGenerated(ASTInternal::fromGenerated(succ)
|
||||
.(AST::ParenthesizedExpr)
|
||||
.getLastExpr()), pred, c) and
|
||||
last(succ.(ParenthesizedExpr).getLastExpr(), pred, c) and
|
||||
completion = c
|
||||
or
|
||||
last(ASTInternal::toGenerated(ASTInternal::fromGenerated(succ)
|
||||
.(AST::ConditionalExpr)
|
||||
.getBranch(_)), pred, c) and
|
||||
last(succ.(ConditionalExpr).getBranch(_), pred, c) and
|
||||
completion = c
|
||||
)
|
||||
}
|
||||
@@ -255,7 +244,7 @@ private module ConditionalCompletionSplitting {
|
||||
|
||||
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
|
||||
this.appliesTo(last) and
|
||||
succExit(ASTInternal::toGenerated(scope), last, c) and
|
||||
succExit(scope, last, c) and
|
||||
if c instanceof ConditionalCompletion then completion = c else any()
|
||||
}
|
||||
|
||||
@@ -288,12 +277,11 @@ module EnsureSplitting {
|
||||
|
||||
/** A node that belongs to an `ensure` block. */
|
||||
private class EnsureNode extends AstNode {
|
||||
private Trees::RescueEnsureBlockTree block;
|
||||
private Trees::BodyStmtTree block;
|
||||
|
||||
EnsureNode() { this = block.getAnEnsureDescendant() }
|
||||
|
||||
/** Gets the immediate block that this node belongs to. */
|
||||
Trees::RescueEnsureBlockTree getBlock() { result = block }
|
||||
int getNestLevel() { result = block.getNestLevel() }
|
||||
|
||||
/** Holds if this node is the entry node in the `ensure` block it belongs to. */
|
||||
predicate isEntryNode() { first(block.getEnsure(), this) }
|
||||
@@ -366,7 +354,7 @@ module EnsureSplitting {
|
||||
pragma[noinline]
|
||||
private predicate hasEntry0(AstNode pred, EnsureNode succ, int nestLevel, Completion c) {
|
||||
succ.isEntryNode() and
|
||||
nestLevel = succ.getBlock().nestLevel() and
|
||||
nestLevel = succ.getNestLevel() and
|
||||
succ(pred, succ, c)
|
||||
}
|
||||
|
||||
@@ -389,11 +377,9 @@ module EnsureSplitting {
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate exit0(
|
||||
AstNode pred, Trees::RescueEnsureBlockTree block, int nestLevel, Completion c
|
||||
) {
|
||||
private predicate exit0(AstNode pred, Trees::BodyStmtTree block, int nestLevel, Completion c) {
|
||||
this.appliesToPredecessor(pred) and
|
||||
nestLevel = block.nestLevel() and
|
||||
nestLevel = block.getNestLevel() and
|
||||
block.lastInner(pred, c)
|
||||
}
|
||||
|
||||
@@ -402,9 +388,7 @@ module EnsureSplitting {
|
||||
* `inherited` indicates whether `c` is an inherited completion from the
|
||||
* body.
|
||||
*/
|
||||
private predicate exit(
|
||||
Trees::RescueEnsureBlockTree block, AstNode pred, Completion c, boolean inherited
|
||||
) {
|
||||
private predicate exit(Trees::BodyStmtTree block, AstNode pred, Completion c, boolean inherited) {
|
||||
exists(EnsureSplitType type |
|
||||
exit0(pred, block, this.getNestLevel(), c) and
|
||||
type = this.getType()
|
||||
@@ -472,7 +456,7 @@ module EnsureSplitting {
|
||||
}
|
||||
|
||||
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
|
||||
succExit(ASTInternal::toGenerated(scope), last, c) and
|
||||
succExit(scope, last, c) and
|
||||
(
|
||||
exit(_, last, c, _)
|
||||
or
|
||||
@@ -488,10 +472,10 @@ module EnsureSplitting {
|
||||
if en.isEntryNode()
|
||||
then
|
||||
// entering a nested `ensure` block
|
||||
en.getBlock().nestLevel() > this.getNestLevel()
|
||||
en.getNestLevel() > this.getNestLevel()
|
||||
else
|
||||
// staying in the same (possibly nested) `ensure` block as `pred`
|
||||
en.getBlock().nestLevel() >= this.getNestLevel()
|
||||
en.getNestLevel() >= this.getNestLevel()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -517,7 +501,7 @@ class Splits extends TSplits {
|
||||
|
||||
private predicate succEntrySplitsFromRank(CfgScope pred, AstNode succ, Splits splits, int rnk) {
|
||||
splits = TSplitsNil() and
|
||||
succEntry(ASTInternal::toGenerated(pred), succ) and
|
||||
succEntry(pred, succ) and
|
||||
rnk = 0
|
||||
or
|
||||
exists(SplitImpl head, Splits tail | succEntrySplitsCons(pred, succ, head, tail, rnk) |
|
||||
@@ -540,7 +524,7 @@ private predicate succEntrySplitsCons(
|
||||
pragma[noinline]
|
||||
predicate succEntrySplits(CfgScope pred, AstNode succ, Splits succSplits, SuccessorType t) {
|
||||
exists(int rnk |
|
||||
succEntry(ASTInternal::toGenerated(pred), succ) and
|
||||
succEntry(pred, succ) and
|
||||
t instanceof NormalSuccessor and
|
||||
succEntrySplitsFromRank(pred, succ, succSplits, rnk)
|
||||
|
|
||||
@@ -559,7 +543,7 @@ predicate succExitSplits(AstNode last, Splits predSplits, CfgScope scope, Succes
|
||||
exists(Reachability::SameSplitsBlock b, Completion c | last = b.getANode() |
|
||||
b.isReachable(predSplits) and
|
||||
t = c.getAMatchingSuccessorType() and
|
||||
succExit(ASTInternal::toGenerated(scope), last, c) and
|
||||
succExit(scope, last, c) and
|
||||
forall(SplitImpl predSplit | predSplit = predSplits.getASplit() |
|
||||
predSplit.hasExitScope(scope, last, c)
|
||||
)
|
||||
|
||||
@@ -49,7 +49,7 @@ private predicate capturedExitRead(AnnotatedExitBasicBlock bb, int i, LocalVaria
|
||||
i = bb.length()
|
||||
}
|
||||
|
||||
private CfgScope getCaptureOuterCfgScope(Callable scope) {
|
||||
private CfgScope getCaptureOuterCfgScope(CfgScope scope) {
|
||||
result = scope.getOuterCfgScope() and
|
||||
(
|
||||
scope instanceof Block
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import ruby
|
||||
import codeql_ruby.ast.internal.TreeSitter
|
||||
|
||||
private string getMethodName(Call c) {
|
||||
result = c.(MethodCall).getMethodName()
|
||||
|
||||
@@ -3,6 +3,6 @@ toplevel
|
||||
| modules.rb:1:1:61:3 | modules.rb | Toplevel |
|
||||
| toplevel.rb:1:1:5:23 | toplevel.rb | Toplevel |
|
||||
beginBlocks
|
||||
| toplevel.rb:1:1:5:23 | toplevel.rb | 1 | toplevel.rb:5:1:5:22 | BEGIN { ... } |
|
||||
| toplevel.rb:1:1:5:23 | toplevel.rb | 0 | toplevel.rb:5:1:5:22 | BEGIN { ... } |
|
||||
endBlocks
|
||||
| toplevel.rb:1:1:5:23 | toplevel.rb | toplevel.rb:3:1:3:18 | END { ... } |
|
||||
|
||||
@@ -38,8 +38,8 @@ break_ensure.rb:
|
||||
#-----| -> In
|
||||
|
||||
# 3| ... > ...
|
||||
#-----| false -> if ...
|
||||
#-----| true -> break
|
||||
#-----| false -> if ...
|
||||
|
||||
# 3| element
|
||||
#-----| -> 0
|
||||
@@ -57,8 +57,8 @@ break_ensure.rb:
|
||||
#-----| -> exit m1 (normal)
|
||||
|
||||
# 8| call to nil?
|
||||
#-----| false -> if ...
|
||||
#-----| true -> "elements nil"
|
||||
#-----| false -> if ...
|
||||
|
||||
# 8| elements
|
||||
#-----| -> call to nil?
|
||||
@@ -100,8 +100,8 @@ break_ensure.rb:
|
||||
#-----| -> ensure ...
|
||||
|
||||
# 16| ... > ...
|
||||
#-----| false -> if ...
|
||||
#-----| true -> break
|
||||
#-----| false -> if ...
|
||||
|
||||
# 16| element
|
||||
#-----| -> 0
|
||||
@@ -125,12 +125,12 @@ break_ensure.rb:
|
||||
#-----| break -> for ... in ...
|
||||
|
||||
# 20| call to nil?
|
||||
#-----| false -> if ...
|
||||
#-----| true -> "elements nil"
|
||||
#-----| false -> if ...
|
||||
|
||||
# 20| [ensure: break] call to nil?
|
||||
#-----| false -> [ensure: break] if ...
|
||||
#-----| true -> [ensure: break] "elements nil"
|
||||
#-----| false -> [ensure: break] if ...
|
||||
|
||||
# 20| elements
|
||||
#-----| -> call to nil?
|
||||
@@ -168,8 +168,8 @@ break_ensure.rb:
|
||||
#-----| -> ensure ...
|
||||
|
||||
# 29| call to nil?
|
||||
#-----| false -> if ...
|
||||
#-----| true -> return
|
||||
#-----| false -> if ...
|
||||
|
||||
# 29| elements
|
||||
#-----| -> call to nil?
|
||||
@@ -216,12 +216,12 @@ break_ensure.rb:
|
||||
#-----| -> [ensure: return] In
|
||||
|
||||
# 35| ... > ...
|
||||
#-----| false -> if ...
|
||||
#-----| true -> break
|
||||
#-----| false -> if ...
|
||||
|
||||
# 35| [ensure: return] ... > ...
|
||||
#-----| false -> [ensure: return] if ...
|
||||
#-----| true -> [ensure: return] break
|
||||
#-----| false -> [ensure: return] if ...
|
||||
|
||||
# 35| call to x
|
||||
#-----| -> 0
|
||||
@@ -278,8 +278,8 @@ break_ensure.rb:
|
||||
#-----| -> ensure ...
|
||||
|
||||
# 47| ... > ...
|
||||
#-----| false -> if ...
|
||||
#-----| true -> ""
|
||||
#-----| false -> if ...
|
||||
|
||||
# 47| element
|
||||
#-----| -> 1
|
||||
@@ -306,12 +306,12 @@ break_ensure.rb:
|
||||
#-----| raise -> for ... in ...
|
||||
|
||||
# 51| ... > ...
|
||||
#-----| false -> if ...
|
||||
#-----| true -> 10
|
||||
#-----| false -> if ...
|
||||
|
||||
# 51| [ensure: raise] ... > ...
|
||||
#-----| false -> [ensure: raise] if ...
|
||||
#-----| true -> [ensure: raise] 10
|
||||
#-----| false -> [ensure: raise] if ...
|
||||
|
||||
# 51| element
|
||||
#-----| -> 0
|
||||
@@ -377,8 +377,8 @@ case.rb:
|
||||
#-----| -> (if ...)
|
||||
|
||||
# 3| call to x2
|
||||
#-----| false -> if ...
|
||||
#-----| true -> "x2"
|
||||
#-----| false -> if ...
|
||||
|
||||
# 3| call to puts
|
||||
#-----| -> if ...
|
||||
@@ -401,7 +401,7 @@ case.rb:
|
||||
|
||||
cfg.rb:
|
||||
# 1| enter cfg.rb
|
||||
#-----| -> bar
|
||||
#-----| -> BEGIN { ... }
|
||||
|
||||
# 1| bar
|
||||
#-----| -> alias ...
|
||||
@@ -460,24 +460,16 @@ cfg.rb:
|
||||
#-----| -> %w(...)
|
||||
|
||||
# 12| call to puts
|
||||
#-----| -> BEGIN { ... }
|
||||
#-----| -> END { ... }
|
||||
|
||||
# 12| 4
|
||||
#-----| -> call to puts
|
||||
|
||||
# 15| enter BEGIN { ... }
|
||||
# 15| BEGIN { ... }
|
||||
#-----| -> "hello"
|
||||
|
||||
# 15| BEGIN { ... }
|
||||
#-----| -> END { ... }
|
||||
|
||||
# 15| exit BEGIN { ... }
|
||||
|
||||
# 15| exit BEGIN { ... } (normal)
|
||||
#-----| -> exit BEGIN { ... }
|
||||
|
||||
# 16| call to puts
|
||||
#-----| -> exit BEGIN { ... } (normal)
|
||||
#-----| -> bar
|
||||
|
||||
# 16| "hello"
|
||||
#-----| -> call to puts
|
||||
@@ -560,9 +552,12 @@ cfg.rb:
|
||||
# 29| exit { ... } (normal)
|
||||
#-----| -> exit { ... }
|
||||
|
||||
# 29| x
|
||||
# 29| &x
|
||||
#-----| -> x
|
||||
|
||||
# 29| x
|
||||
#-----| -> &x
|
||||
|
||||
# 29| call to call
|
||||
#-----| -> exit { ... } (normal)
|
||||
|
||||
@@ -587,12 +582,12 @@ cfg.rb:
|
||||
# 35| false
|
||||
#-----| false -> if ...
|
||||
|
||||
# 39| call to puts
|
||||
#-----| -> case ...
|
||||
|
||||
# 39| self
|
||||
#-----| -> 42
|
||||
|
||||
# 39| call to puts
|
||||
#-----| -> case ...
|
||||
|
||||
# 39| 42
|
||||
#-----| -> call to puts
|
||||
|
||||
@@ -619,12 +614,12 @@ cfg.rb:
|
||||
#-----| -> 2
|
||||
|
||||
# 43| 2
|
||||
#-----| no-match -> 3
|
||||
#-----| match -> "some"
|
||||
#-----| no-match -> 3
|
||||
|
||||
# 43| 3
|
||||
#-----| no-match -> 4
|
||||
#-----| match -> "some"
|
||||
#-----| no-match -> 4
|
||||
|
||||
# 43| 4
|
||||
#-----| match -> "some"
|
||||
@@ -668,8 +663,8 @@ cfg.rb:
|
||||
#-----| -> b
|
||||
|
||||
# 49| ... == ...
|
||||
#-----| false -> b
|
||||
#-----| true -> "some"
|
||||
#-----| false -> b
|
||||
|
||||
# 49| b
|
||||
#-----| -> 0
|
||||
@@ -775,6 +770,9 @@ cfg.rb:
|
||||
# 62| ... = ...
|
||||
#-----| -> pattern
|
||||
|
||||
# 62| (..., ...)
|
||||
#-----| -> (..., ...)
|
||||
|
||||
# 62| (..., ...)
|
||||
#-----| -> ... = ...
|
||||
|
||||
@@ -987,8 +985,8 @@ cfg.rb:
|
||||
#-----| -> x
|
||||
|
||||
# 91| ... > ...
|
||||
#-----| false -> if ...
|
||||
#-----| true -> next
|
||||
#-----| false -> if ...
|
||||
|
||||
# 91| x
|
||||
#-----| -> 3
|
||||
@@ -1023,21 +1021,21 @@ cfg.rb:
|
||||
# 97| {...}
|
||||
#-----| -> map1
|
||||
|
||||
# 97| Pair
|
||||
#-----| -> "c"
|
||||
|
||||
# 97| "a"
|
||||
#-----| -> "b"
|
||||
|
||||
# 97| Pair
|
||||
#-----| -> "c"
|
||||
|
||||
# 97| "b"
|
||||
#-----| -> Pair
|
||||
|
||||
# 97| Pair
|
||||
#-----| -> :e
|
||||
|
||||
# 97| "c"
|
||||
#-----| -> "d"
|
||||
|
||||
# 97| Pair
|
||||
#-----| -> :e
|
||||
|
||||
# 97| "d"
|
||||
#-----| -> Pair
|
||||
|
||||
@@ -1065,12 +1063,12 @@ cfg.rb:
|
||||
# 98| map1
|
||||
#-----| -> **...
|
||||
|
||||
# 98| Pair
|
||||
#-----| -> map1
|
||||
|
||||
# 98| "x"
|
||||
#-----| -> "y"
|
||||
|
||||
# 98| Pair
|
||||
#-----| -> map1
|
||||
|
||||
# 98| "y"
|
||||
#-----| -> Pair
|
||||
|
||||
@@ -1101,9 +1099,12 @@ cfg.rb:
|
||||
# 101| key
|
||||
#-----| -> kwargs
|
||||
|
||||
# 101| kwargs
|
||||
# 101| **kwargs
|
||||
#-----| -> value
|
||||
|
||||
# 101| kwargs
|
||||
#-----| -> **kwargs
|
||||
|
||||
# 102| call to puts
|
||||
#-----| -> kwargs
|
||||
|
||||
@@ -1161,18 +1162,18 @@ cfg.rb:
|
||||
# 110| call to type
|
||||
#-----| -> #{...}
|
||||
|
||||
# 113| ... if ...
|
||||
#-----| -> C
|
||||
|
||||
# 113| call to puts
|
||||
#-----| -> ... if ...
|
||||
|
||||
# 113| ... if ...
|
||||
#-----| -> C
|
||||
|
||||
# 113| "hi"
|
||||
#-----| -> call to puts
|
||||
|
||||
# 113| ... > ...
|
||||
#-----| false -> ... if ...
|
||||
#-----| true -> "hi"
|
||||
#-----| false -> ... if ...
|
||||
|
||||
# 113| b
|
||||
#-----| -> 10
|
||||
@@ -1372,6 +1373,9 @@ cfg.rb:
|
||||
# 135| ... = ...
|
||||
#-----| -> M
|
||||
|
||||
# 135| (..., ...)
|
||||
#-----| -> (..., ...)
|
||||
|
||||
# 135| (..., ...)
|
||||
#-----| -> ... = ...
|
||||
|
||||
@@ -1390,14 +1394,11 @@ cfg.rb:
|
||||
# 135| 3
|
||||
#-----| -> init
|
||||
|
||||
# 137| Constant
|
||||
#-----| -> M
|
||||
|
||||
# 137| M
|
||||
#-----| -> Constant
|
||||
|
||||
# 138| Constant
|
||||
#-----| -> class << ...
|
||||
# 137| Constant
|
||||
#-----| -> M
|
||||
|
||||
# 138| call to itself
|
||||
#-----| -> Constant
|
||||
@@ -1405,6 +1406,9 @@ cfg.rb:
|
||||
# 138| M
|
||||
#-----| -> call to itself
|
||||
|
||||
# 138| Constant
|
||||
#-----| -> class << ...
|
||||
|
||||
# 140| class << ...
|
||||
#-----| -> Silly
|
||||
|
||||
@@ -1469,9 +1473,12 @@ cfg.rb:
|
||||
# 149| silly
|
||||
#-----| -> method
|
||||
|
||||
# 149| x
|
||||
# 149| *x
|
||||
#-----| -> x
|
||||
|
||||
# 149| x
|
||||
#-----| -> *x
|
||||
|
||||
# 150| call to puts
|
||||
#-----| -> exit method (normal)
|
||||
|
||||
@@ -1619,18 +1626,18 @@ cfg.rb:
|
||||
# 169| "bye"
|
||||
#-----| -> call to puts
|
||||
|
||||
# 171| ... unless ...
|
||||
#-----| -> x
|
||||
|
||||
# 171| call to puts
|
||||
#-----| -> ... unless ...
|
||||
|
||||
# 171| ... unless ...
|
||||
#-----| -> x
|
||||
|
||||
# 171| "hi"
|
||||
#-----| -> call to puts
|
||||
|
||||
# 171| ... == ...
|
||||
#-----| true -> ... unless ...
|
||||
#-----| false -> "hi"
|
||||
#-----| true -> ... unless ...
|
||||
|
||||
# 171| x
|
||||
#-----| -> 0
|
||||
@@ -1675,12 +1682,12 @@ cfg.rb:
|
||||
# 175| 0
|
||||
#-----| -> i
|
||||
|
||||
# 176| ... until ...
|
||||
#-----| -> 0
|
||||
|
||||
# 176| (...; ...)
|
||||
#-----| -> i
|
||||
|
||||
# 176| ... until ...
|
||||
#-----| -> 0
|
||||
|
||||
# 176| call to puts
|
||||
#-----| -> i
|
||||
|
||||
@@ -1697,8 +1704,8 @@ cfg.rb:
|
||||
#-----| -> ... += ...
|
||||
|
||||
# 176| ... == ...
|
||||
#-----| true -> ... until ...
|
||||
#-----| false -> "hello"
|
||||
#-----| true -> ... until ...
|
||||
|
||||
# 176| i
|
||||
#-----| -> 10
|
||||
@@ -1719,8 +1726,8 @@ cfg.rb:
|
||||
#-----| -> i
|
||||
|
||||
# 179| ... < ...
|
||||
#-----| false -> while ...
|
||||
#-----| true -> x
|
||||
#-----| false -> while ...
|
||||
|
||||
# 179| x
|
||||
#-----| -> 10
|
||||
@@ -1741,8 +1748,8 @@ cfg.rb:
|
||||
#-----| -> x
|
||||
|
||||
# 181| ... == ...
|
||||
#-----| false -> if ...
|
||||
#-----| true -> redo
|
||||
#-----| false -> if ...
|
||||
|
||||
# 181| x
|
||||
#-----| -> 5
|
||||
@@ -1759,12 +1766,12 @@ cfg.rb:
|
||||
# 182| x
|
||||
#-----| -> call to puts
|
||||
|
||||
# 185| ... while ...
|
||||
#-----| -> run_block
|
||||
|
||||
# 185| (...; ...)
|
||||
#-----| -> i
|
||||
|
||||
# 185| ... while ...
|
||||
#-----| -> run_block
|
||||
|
||||
# 185| call to puts
|
||||
#-----| -> i
|
||||
|
||||
@@ -1781,8 +1788,8 @@ cfg.rb:
|
||||
#-----| -> ... -= ...
|
||||
|
||||
# 185| ... != ...
|
||||
#-----| false -> ... while ...
|
||||
#-----| true -> "hello"
|
||||
#-----| false -> ... while ...
|
||||
|
||||
# 185| i
|
||||
#-----| -> 0
|
||||
@@ -1796,10 +1803,16 @@ cfg.rb:
|
||||
# 187| run_block
|
||||
#-----| -> { ... }
|
||||
|
||||
# 187| exit run_block
|
||||
|
||||
# 187| exit run_block (normal)
|
||||
#-----| -> exit run_block
|
||||
|
||||
# 188| yield ...
|
||||
#-----| -> 42
|
||||
|
||||
# 188| 42
|
||||
#-----| -> exit run_block (normal)
|
||||
|
||||
# 191| call to run_block
|
||||
#-----| -> exit cfg.rb (normal)
|
||||
@@ -1854,8 +1867,8 @@ exit.rb:
|
||||
#-----| -> "x <= 2"
|
||||
|
||||
# 2| ... > ...
|
||||
#-----| false -> if ...
|
||||
#-----| true -> 1
|
||||
#-----| false -> if ...
|
||||
|
||||
# 2| x
|
||||
#-----| -> 2
|
||||
@@ -1896,8 +1909,8 @@ exit.rb:
|
||||
#-----| -> "x <= 2"
|
||||
|
||||
# 9| ... > ...
|
||||
#-----| false -> if ...
|
||||
#-----| true -> "abort!"
|
||||
#-----| false -> if ...
|
||||
|
||||
# 9| x
|
||||
#-----| -> 2
|
||||
@@ -2075,8 +2088,8 @@ ifs.rb:
|
||||
#-----| -> 1
|
||||
|
||||
# 12| b
|
||||
#-----| false -> if ...
|
||||
#-----| true -> 0
|
||||
#-----| false -> if ...
|
||||
|
||||
# 13| return
|
||||
#-----| return -> exit m2 (normal)
|
||||
@@ -2295,12 +2308,12 @@ ifs.rb:
|
||||
# 36| enter conditional_method_def
|
||||
#-----| -> "bla"
|
||||
|
||||
# 36| ... unless ...
|
||||
#-----| -> constant_condition
|
||||
|
||||
# 36| conditional_method_def
|
||||
#-----| -> ... unless ...
|
||||
|
||||
# 36| ... unless ...
|
||||
#-----| -> constant_condition
|
||||
|
||||
# 36| exit conditional_method_def
|
||||
|
||||
# 36| exit conditional_method_def (normal)
|
||||
@@ -2313,8 +2326,8 @@ ifs.rb:
|
||||
#-----| -> call to puts
|
||||
|
||||
# 38| ... == ...
|
||||
#-----| true -> ... unless ...
|
||||
#-----| false -> conditional_method_def
|
||||
#-----| true -> ... unless ...
|
||||
|
||||
# 38| 1
|
||||
#-----| -> 2
|
||||
@@ -2369,8 +2382,8 @@ loops.rb:
|
||||
#-----| -> exit m1 (normal)
|
||||
|
||||
# 2| ... >= ...
|
||||
#-----| false -> while ...
|
||||
#-----| true -> x
|
||||
#-----| false -> while ...
|
||||
|
||||
# 2| x
|
||||
#-----| -> 0
|
||||
@@ -2411,8 +2424,8 @@ loops.rb:
|
||||
#-----| -> "Done"
|
||||
|
||||
# 9| ... >= ...
|
||||
#-----| false -> while ...
|
||||
#-----| true -> x
|
||||
#-----| false -> while ...
|
||||
|
||||
# 9| x
|
||||
#-----| -> 0
|
||||
@@ -2471,8 +2484,8 @@ loops.rb:
|
||||
#-----| -> elsif ...
|
||||
|
||||
# 16| ... > ...
|
||||
#-----| false -> elsif ...
|
||||
#-----| true -> redo
|
||||
#-----| false -> elsif ...
|
||||
|
||||
# 16| x
|
||||
#-----| -> 10
|
||||
@@ -2506,12 +2519,12 @@ loops.rb:
|
||||
# 24| exit m3 (normal)
|
||||
#-----| -> exit m3
|
||||
|
||||
# 25| call to each
|
||||
#-----| -> exit m3 (normal)
|
||||
|
||||
# 25| [...]
|
||||
#-----| -> do ... end
|
||||
|
||||
# 25| call to each
|
||||
#-----| -> exit m3 (normal)
|
||||
|
||||
# 25| 1
|
||||
#-----| -> 2
|
||||
|
||||
@@ -2583,8 +2596,8 @@ raise.rb:
|
||||
#-----| -> "x <= 2"
|
||||
|
||||
# 8| ... > ...
|
||||
#-----| false -> if ...
|
||||
#-----| true -> "x > 2"
|
||||
#-----| false -> if ...
|
||||
|
||||
# 8| x
|
||||
#-----| -> 2
|
||||
@@ -2875,8 +2888,8 @@ raise.rb:
|
||||
#-----| -> if ...
|
||||
|
||||
# 71| ... < ...
|
||||
#-----| false -> elsif ...
|
||||
#-----| true -> "x < 0"
|
||||
#-----| false -> elsif ...
|
||||
|
||||
# 71| x
|
||||
#-----| -> 0
|
||||
@@ -2969,8 +2982,8 @@ raise.rb:
|
||||
#-----| -> if ...
|
||||
|
||||
# 84| ... < ...
|
||||
#-----| false -> elsif ...
|
||||
#-----| true -> "x < 0"
|
||||
#-----| false -> elsif ...
|
||||
|
||||
# 84| x
|
||||
#-----| -> 0
|
||||
@@ -3075,8 +3088,8 @@ raise.rb:
|
||||
#-----| -> if ...
|
||||
|
||||
# 99| ... < ...
|
||||
#-----| false -> elsif ...
|
||||
#-----| true -> "x < 0"
|
||||
#-----| false -> elsif ...
|
||||
|
||||
# 99| x
|
||||
#-----| -> 0
|
||||
@@ -3133,16 +3146,16 @@ raise.rb:
|
||||
#-----| -> [ensure: raise] ensure ...
|
||||
|
||||
# 106| b1
|
||||
#-----| false -> if ...
|
||||
#-----| true -> "b1 is true"
|
||||
#-----| false -> if ...
|
||||
|
||||
# 106| [ensure: return] b1
|
||||
#-----| false -> [ensure: return] if ...
|
||||
#-----| true -> [ensure: return] "b1 is true"
|
||||
#-----| false -> [ensure: return] if ...
|
||||
|
||||
# 106| [ensure: raise] b1
|
||||
#-----| false -> [ensure: raise] if ...
|
||||
#-----| true -> [ensure: raise] "b1 is true"
|
||||
#-----| false -> [ensure: raise] if ...
|
||||
|
||||
# 107| call to raise
|
||||
#-----| raise -> [ensure(1): raise] ensure ...
|
||||
@@ -3259,16 +3272,16 @@ raise.rb:
|
||||
#-----| raise -> exit m9 (abnormal)
|
||||
|
||||
# 116| b2
|
||||
#-----| false -> if ...
|
||||
#-----| true -> "b2 is true"
|
||||
#-----| false -> if ...
|
||||
|
||||
# 116| [ensure: return] b2
|
||||
#-----| false -> [ensure: return] if ...
|
||||
#-----| true -> [ensure: return] "b2 is true"
|
||||
#-----| false -> [ensure: return] if ...
|
||||
|
||||
# 116| [ensure: raise] b2
|
||||
#-----| false -> [ensure: raise] if ...
|
||||
#-----| true -> [ensure: raise] "b2 is true"
|
||||
#-----| false -> [ensure: raise] if ...
|
||||
|
||||
# 117| call to raise
|
||||
#-----| raise -> exit m9 (abnormal)
|
||||
@@ -3306,7 +3319,11 @@ raise.rb:
|
||||
#-----| no-match -> "Exception"
|
||||
#-----| match -> ensure ...
|
||||
|
||||
# 121| (call to raise)
|
||||
#-----| -> ensure ...
|
||||
|
||||
# 121| call to raise
|
||||
#-----| raise -> (call to raise)
|
||||
#-----| raise -> exit m10 (abnormal)
|
||||
|
||||
# 121| "Exception"
|
||||
@@ -3413,8 +3430,8 @@ raise.rb:
|
||||
#-----| -> ensure ...
|
||||
|
||||
# 143| b
|
||||
#-----| false -> if ...
|
||||
#-----| true -> ""
|
||||
#-----| false -> if ...
|
||||
|
||||
# 144| call to raise
|
||||
#-----| raise -> [ensure: raise] ensure ...
|
||||
@@ -3491,18 +3508,18 @@ raise.rb:
|
||||
# 155| elem
|
||||
#-----| -> element
|
||||
|
||||
# 155| ... if ...
|
||||
#-----| -> exit { ... } (normal)
|
||||
|
||||
# 155| call to raise
|
||||
#-----| raise -> exit { ... } (abnormal)
|
||||
|
||||
# 155| ... if ...
|
||||
#-----| -> exit { ... } (normal)
|
||||
|
||||
# 155| ""
|
||||
#-----| -> call to raise
|
||||
|
||||
# 155| call to nil?
|
||||
#-----| false -> ... if ...
|
||||
#-----| true -> ""
|
||||
#-----| false -> ... if ...
|
||||
|
||||
# 155| element
|
||||
#-----| -> call to nil?
|
||||
|
||||
Reference in New Issue
Block a user