Merge pull request #198 from github/hvitved/desugar-compound-assignment

This commit is contained in:
Tom Hvitved
2021-06-10 19:39:54 +02:00
committed by GitHub
18 changed files with 1155 additions and 386 deletions

View File

@@ -752,31 +752,25 @@ class HashLiteral extends Literal, THashLiteral {
* ```
*/
class RangeLiteral extends Literal, TRangeLiteral {
private Generated::Range g;
RangeLiteral() { this = TRangeLiteral(g) }
final override string getAPrimaryQlClass() { result = "RangeLiteral" }
/** Gets the begin expression of this range, if any. */
final Expr getBegin() { toGenerated(result) = g.getBegin() }
Expr getBegin() { none() }
/** Gets the end expression of this range, if any. */
final Expr getEnd() { toGenerated(result) = g.getEnd() }
Expr getEnd() { none() }
/**
* Holds if the range is inclusive of the end value, i.e. uses the `..`
* operator.
*/
final predicate isInclusive() { g instanceof @range_dotdot }
predicate isInclusive() { none() }
/**
* Holds if the range is exclusive of the end value, i.e. uses the `...`
* operator.
*/
final predicate isExclusive() { g instanceof @range_dotdotdot }
final override string toString() { result = "_ " + g.getOperator() + " _" }
predicate isExclusive() { none() }
final override AstNode getAChild(string pred) {
result = super.getAChild(pred)
@@ -785,6 +779,44 @@ class RangeLiteral extends Literal, TRangeLiteral {
or
pred = "getEnd" and result = this.getEnd()
}
final override string toString() {
exists(string op |
this.isInclusive() and op = ".."
or
this.isExclusive() and op = "..."
|
result = "_ " + op + " _"
)
}
}
private class RangeLiteralReal extends RangeLiteral, TRangeLiteralReal {
private Generated::Range g;
RangeLiteralReal() { this = TRangeLiteralReal(g) }
final override Expr getBegin() { toGenerated(result) = g.getBegin() }
final override Expr getEnd() { toGenerated(result) = g.getEnd() }
final override predicate isInclusive() { g instanceof @range_dotdot }
final override predicate isExclusive() { g instanceof @range_dotdotdot }
}
private class RangeLiteralSynth extends RangeLiteral, TRangeLiteralSynth {
private boolean inclusive;
RangeLiteralSynth() { this = TRangeLiteralSynth(_, _, inclusive) }
final override Expr getBegin() { result = TIntegerLiteralSynth(this, 0, _) }
final override Expr getEnd() { result = TIntegerLiteralSynth(this, 1, _) }
final override predicate isInclusive() { inclusive = true }
final override predicate isExclusive() { inclusive = false }
}
/**

View File

@@ -91,12 +91,8 @@ class UnaryMinusExpr extends UnaryArithmeticOperation, TUnaryMinusExpr {
* foo(*args)
* ```
*/
class SplatExpr extends UnaryOperation, TSplatArgument {
private Generated::SplatArgument g;
SplatExpr() { this = TSplatArgument(g) }
final override Expr getOperand() { toGenerated(result) = g.getChild() }
class SplatExpr extends UnaryOperation, TSplatExpr {
final override Expr getOperand() { result = this.(SplatExprImpl).getOperandImpl() }
final override string getOperator() { result = "*" }
@@ -109,10 +105,10 @@ class SplatExpr extends UnaryOperation, TSplatArgument {
* foo(**options)
* ```
*/
class HashSplatExpr extends UnaryOperation, THashSplatArgument {
class HashSplatExpr extends UnaryOperation, THashSplatExpr {
private Generated::HashSplatArgument g;
HashSplatExpr() { this = THashSplatArgument(g) }
HashSplatExpr() { this = THashSplatExpr(g) }
final override Expr getOperand() { toGenerated(result) = g.getChild() }

View File

@@ -1,6 +1,7 @@
private import codeql_ruby.AST
private import codeql.Locations
private import internal.AST
private import internal.Pattern
private import internal.TreeSitter
private import internal.Variable
@@ -62,20 +63,9 @@ class VariablePattern extends Pattern, LhsExpr, TVariablePattern { }
class TuplePattern extends Pattern, TTuplePattern {
override string getAPrimaryQlClass() { result = "TuplePattern" }
private Generated::AstNode getChild(int i) {
result = toGenerated(this).(Generated::DestructuredParameter).getChild(i)
or
result = toGenerated(this).(Generated::DestructuredLeftAssignment).getChild(i)
or
toGenerated(this) =
any(Generated::LeftAssignmentList lal |
if
strictcount(int j | exists(lal.getChild(j))) = 1 and
lal.getChild(0) instanceof Generated::DestructuredLeftAssignment
then result = lal.getChild(0).(Generated::DestructuredLeftAssignment).getChild(i)
else result = lal.getChild(i)
)
}
private TuplePatternImpl getImpl() { result = toGenerated(this) }
private Generated::AstNode getChild(int i) { result = this.getImpl().getChildNode(i) }
/** Gets the `i`th pattern in this tuple pattern. */
final Pattern getElement(int i) {
@@ -96,9 +86,7 @@ class TuplePattern extends Pattern, TTuplePattern {
* a, b, *rest, c, d = value
* ```
*/
final int getRestIndex() {
result = unique(int i | getChild(i) instanceof Generated::RestAssignment)
}
final int getRestIndex() { result = this.getImpl().getRestIndex() }
override Variable getAVariable() { result = this.getElement(_).getAVariable() }

View File

@@ -138,7 +138,7 @@ private module Cached {
} or
THashKeySymbolLiteral(Generated::HashKeySymbol g) or
THashLiteral(Generated::Hash g) or
THashSplatArgument(Generated::HashSplatArgument g) or
THashSplatExpr(Generated::HashSplatArgument g) or
THashSplatParameter(Generated::HashSplatParameter g) or
THereDoc(Generated::HeredocBeginning g) or
TIdentifierMethodCall(Generated::Identifier g) { isIdentifierMethodCall(g) } or
@@ -198,7 +198,10 @@ private module Cached {
TParenthesizedExpr(Generated::ParenthesizedStatements g) or
TRShiftExprReal(Generated::Binary g) { g instanceof @binary_ranglerangle } or
TRShiftExprSynth(AST::AstNode parent, int i) { mkSynthChild(RShiftExprKind(), parent, i) } or
TRangeLiteral(Generated::Range g) or
TRangeLiteralReal(Generated::Range g) or
TRangeLiteralSynth(AST::AstNode parent, int i, boolean inclusive) {
mkSynthChild(RangeLiteralKind(inclusive), parent, i)
} or
TRationalLiteral(Generated::Rational g) or
TRedoStmt(Generated::Redo g) or
TRegexLiteral(Generated::Regex g) or
@@ -232,7 +235,8 @@ private module Cached {
TSingletonClass(Generated::SingletonClass g) or
TSingletonMethod(Generated::SingletonMethod g) or
TSpaceshipExpr(Generated::Binary g) { g instanceof @binary_langleequalrangle } or
TSplatArgument(Generated::SplatArgument g) or
TSplatExprReal(Generated::SplatArgument g) or
TSplatExprSynth(AST::AstNode parent, int i) { mkSynthChild(SplatExprKind(), parent, i) } or
TSplatParameter(Generated::SplatParameter g) or
TStmtSequenceSynth(AST::AstNode parent, int i) { mkSynthChild(StmtSequenceKind(), parent, i) } or
TStringArrayLiteral(Generated::StringArray g) or
@@ -337,7 +341,7 @@ private module Cached {
n = TGlobalVariableAccessReal(result, _) or
n = THashKeySymbolLiteral(result) or
n = THashLiteral(result) or
n = THashSplatArgument(result) or
n = THashSplatExpr(result) or
n = THashSplatParameter(result) or
n = THereDoc(result) or
n = TIdentifierMethodCall(result) or
@@ -367,7 +371,7 @@ private module Cached {
n = TPair(result) or
n = TParenthesizedExpr(result) or
n = TRShiftExprReal(result) or
n = TRangeLiteral(result) or
n = TRangeLiteralReal(result) or
n = TRationalLiteral(result) or
n = TRedoStmt(result) or
n = TRegexLiteral(result) or
@@ -388,7 +392,7 @@ private module Cached {
n = TSingletonClass(result) or
n = TSingletonMethod(result) or
n = TSpaceshipExpr(result) or
n = TSplatArgument(result) or
n = TSplatExprReal(result) or
n = TSplatParameter(result) or
n = TStringArrayLiteral(result) or
n = TStringConcatenation(result) or
@@ -458,10 +462,14 @@ private module Cached {
or
result = TMulExprSynth(parent, i)
or
result = TRangeLiteralSynth(parent, i, _)
or
result = TRShiftExprSynth(parent, i)
or
result = TSelfSynth(parent, i)
or
result = TSplatExprSynth(parent, i)
or
result = TStmtSequenceSynth(parent, i)
or
result = TSubExprSynth(parent, i)
@@ -493,18 +501,11 @@ private module Cached {
)
}
private Location synthLocation(AST::AstNode n) {
exists(Synthesis s, AST::AstNode parent, int i |
s.child(parent, i, _, SomeLocation(result)) and
n = getSynthChild(parent, i)
)
}
cached
Location getLocation(AST::AstNode n) {
result = synthLocation(n)
synthLocation(n, result)
or
not exists(synthLocation(n)) and
not synthLocation(n, _) and
result = toGeneratedInclSynth(n).getLocation()
}
}
@@ -538,9 +539,10 @@ class TSelf = TSelfReal or TSelfSynth;
class TExpr =
TSelf or TArgumentList or TRescueClause or TRescueModifierExpr or TPair or TStringConcatenation or
TCall or TBlockArgument or TSplatArgument or THashSplatArgument or TConstantAccess or
TControlExpr or TWhenExpr or TLiteral or TCallable or TVariableAccess or TStmtSequence or
TOperation or TSimpleParameter;
TCall or TBlockArgument or TConstantAccess or TControlExpr or TWhenExpr or TLiteral or
TCallable or TVariableAccess or TStmtSequence or TOperation or TSimpleParameter;
class TSplatExpr = TSplatExprReal or TSplatExprSynth;
class TStmtSequence =
TBeginBlock or TEndBlock or TThen or TElse or TDo or TEnsure or TStringInterpolationComponent or
@@ -586,7 +588,7 @@ class TOperation = TUnaryOperation or TBinaryOperation or TAssignment;
class TUnaryOperation =
TUnaryLogicalOperation or TUnaryArithmeticOperation or TUnaryBitwiseOperation or TDefinedExpr or
TSplatArgument or THashSplatArgument;
TSplatExpr or THashSplatExpr;
class TUnaryLogicalOperation = TNotExpr;
@@ -624,6 +626,8 @@ class TBinaryBitwiseOperation =
class TLShiftExpr = TLShiftExprReal or TLShiftExprSynth;
class TRangeLiteral = TRangeLiteralReal or TRangeLiteralSynth;
class TRShiftExpr = TRShiftExprReal or TRShiftExprSynth;
class TBitwiseAndExpr = TBitwiseAndExprReal or TBitwiseAndExprSynth;

View File

@@ -13,7 +13,7 @@ predicate isScopeResolutionMethodCall(Generated::ScopeResolution g, Generated::I
}
abstract class CallImpl extends Call {
abstract Expr getArgumentImpl(int n);
abstract AstNode getArgumentImpl(int n);
/**
* It is not possible to define this predicate as
@@ -28,7 +28,7 @@ abstract class CallImpl extends Call {
}
abstract class MethodCallImpl extends CallImpl, MethodCall {
abstract Expr getReceiverImpl();
abstract AstNode getReceiverImpl();
abstract string getMethodNameImpl();
}
@@ -42,9 +42,9 @@ class MethodCallSynth extends MethodCallImpl, TMethodCallSynth {
)
}
final override Expr getReceiverImpl() { synthChild(this, 0, result) }
final override AstNode getReceiverImpl() { synthChild(this, 0, result) }
final override Expr getArgumentImpl(int n) { synthChild(this, n + 1, result) and n >= 0 }
final override AstNode getArgumentImpl(int n) { synthChild(this, n + 1, result) and n >= 0 }
final override int getNumberOfArgumentsImpl() { this = TMethodCallSynth(_, _, _, _, result) }
}
@@ -56,7 +56,7 @@ class IdentifierMethodCall extends MethodCallImpl, TIdentifierMethodCall {
final override string getMethodNameImpl() { result = g.getValue() }
final override Self getReceiverImpl() { result = TSelfSynth(this, 0) }
final override AstNode getReceiverImpl() { result = TSelfSynth(this, 0) }
final override Expr getArgumentImpl(int n) { none() }

View File

@@ -3,9 +3,9 @@ private import AST
private import TreeSitter
class AssignmentImpl extends Operation, TAssignment {
abstract Pattern getLeftOperandImpl();
abstract AstNode getLeftOperandImpl();
abstract Expr getRightOperandImpl();
abstract AstNode getRightOperandImpl();
}
class AssignExprReal extends AssignmentImpl, AssignExpr, TAssignExprReal {
@@ -13,19 +13,35 @@ class AssignExprReal extends AssignmentImpl, AssignExpr, TAssignExprReal {
AssignExprReal() { this = TAssignExprReal(g) }
final override Pattern getLeftOperandImpl() { toGenerated(result) = g.getLeft() }
final override AstNode getLeftOperandImpl() { toGenerated(result) = g.getLeft() }
final override Expr getRightOperandImpl() { toGenerated(result) = g.getRight() }
final override AstNode getRightOperandImpl() { toGenerated(result) = g.getRight() }
}
class AssignExprSynth extends AssignmentImpl, AssignExpr, TAssignExprSynth {
final override Pattern getLeftOperandImpl() { synthChild(this, 0, result) }
final override AstNode getLeftOperandImpl() { synthChild(this, 0, result) }
final override Expr getRightOperandImpl() { synthChild(this, 1, result) }
final override AstNode getRightOperandImpl() { synthChild(this, 1, result) }
}
class AssignOperationImpl extends AssignmentImpl, AssignOperation {
final override LhsExpr getLeftOperandImpl() { toGenerated(result) = g.getLeft() }
final override AstNode getLeftOperandImpl() { toGenerated(result) = g.getLeft() }
final override Expr getRightOperandImpl() { toGenerated(result) = g.getRight() }
final override AstNode getRightOperandImpl() { toGenerated(result) = g.getRight() }
}
abstract class SplatExprImpl extends SplatExpr {
abstract Expr getOperandImpl();
}
class SplatExprReal extends SplatExprImpl, TSplatExprReal {
private Generated::SplatArgument g;
SplatExprReal() { this = TSplatExprReal(g) }
final override Expr getOperandImpl() { toGenerated(result) = g.getChild() }
}
class SplatExprSynth extends SplatExprImpl, TSplatExprSynth {
final override Expr getOperandImpl() { synthChild(this, 0, result) }
}

View File

@@ -0,0 +1,32 @@
private import codeql_ruby.AST
private import AST
private import TreeSitter
abstract class TuplePatternImpl extends Generated::AstNode {
abstract Generated::AstNode getChildNode(int i);
final int getRestIndex() {
result = unique(int i | this.getChildNode(i) instanceof Generated::RestAssignment)
}
}
class TuplePatternParameterImpl extends TuplePatternImpl, Generated::DestructuredParameter {
override Generated::AstNode getChildNode(int i) { result = this.getChild(i) }
}
class DestructuredLeftAssignmentImpl extends TuplePatternImpl, Generated::DestructuredLeftAssignment {
override Generated::AstNode getChildNode(int i) { result = this.getChild(i) }
}
class LeftAssignmentListImpl extends TuplePatternImpl, Generated::LeftAssignmentList {
override Generated::AstNode getChildNode(int i) {
this =
any(Generated::LeftAssignmentList lal |
if
strictcount(int j | exists(lal.getChild(j))) = 1 and
lal.getChild(0) instanceof Generated::DestructuredLeftAssignment
then result = lal.getChild(0).(Generated::DestructuredLeftAssignment).getChild(i)
else result = lal.getChild(i)
)
}
}

View File

@@ -3,9 +3,8 @@
private import AST
private import TreeSitter
private import codeql_ruby.ast.internal.Call
private import codeql_ruby.ast.internal.Operation
private import codeql_ruby.ast.internal.Parameter
private import codeql_ruby.ast.internal.Variable
private import codeql_ruby.ast.internal.Pattern
private import codeql_ruby.AST
/** A synthesized AST node kind. */
@@ -20,7 +19,7 @@ newtype SynthKind =
ExponentExprKind() or
GlobalVariableAccessKind(GlobalVariable v) or
InstanceVariableAccessKind(InstanceVariable v) or
IntegerLiteralKind(int i) { i in [0 .. 1000] } or
IntegerLiteralKind(int i) { i in [-1000 .. 1000] } or
LShiftExprKind() or
LocalVariableAccessRealKind(LocalVariableReal v) or
LocalVariableAccessSynthKind(TLocalVariableSynth v) or
@@ -31,8 +30,10 @@ newtype SynthKind =
} or
ModuloExprKind() or
MulExprKind() or
StmtSequenceKind() or
RangeLiteralKind(boolean inclusive) { inclusive in [false, true] } or
RShiftExprKind() or
SplatExprKind() or
StmtSequenceKind() or
SelfKind() or
SubExprKind()
@@ -110,7 +111,7 @@ private predicate assign(
i = assignIndex and
child = SynthChild(AssignExprKind())
or
parent = getSynthChild(assignParent, assignIndex) and
parent = TAssignExprSynth(assignParent, assignIndex) and
(
i = 0 and
child = SynthChild(LocalVariableAccessSynthKind(v))
@@ -120,43 +121,138 @@ private predicate assign(
)
}
bindingset[arity, setter]
private SynthKind getCallKind(MethodCall mc, boolean setter, int arity) {
result = MethodCallKind(mc.getMethodName(), setter, arity)
/** Holds if synthesized node `n` should have location `l`. */
predicate synthLocation(AstNode n, Location l) {
exists(Synthesis s, AstNode parent, int i |
s.child(parent, i, _, SomeLocation(l)) and
n = getSynthChild(parent, i)
)
}
private SomeLocation getSomeLocation(AstNode n) {
result = SomeLocation(toGenerated(n).getLocation())
or
result = SomeLocation(any(Location l | synthLocation(n, l)))
}
private module ImplicitSelfSynthesis {
pragma[nomagic]
private predicate identifierMethodCallSelfSynthesis(
AstNode mc, int i, Child child, LocationOption l
) {
child = SynthChild(SelfKind()) and
mc = TIdentifierMethodCall(_) and
i = 0 and
l = NoneLocation()
}
private class IdentifierMethodCallSelfSynthesis extends Synthesis {
final override predicate child(AstNode parent, int i, Child child, LocationOption l) {
child = SynthChild(SelfKind()) and
parent = TIdentifierMethodCall(_) and
i = 0 and
l = NoneLocation()
identifierMethodCallSelfSynthesis(parent, i, child, l)
}
}
pragma[nomagic]
private predicate regularMethodCallSelfSynthesis(
TRegularMethodCall mc, int i, Child child, LocationOption l
) {
exists(Generated::AstNode g |
mc = TRegularMethodCall(g) and
// If there's no explicit receiver (or scope resolution that acts like a
// receiver), then the receiver is implicitly `self`. N.B. `::Foo()` is
// not valid Ruby.
not exists(g.(Generated::Call).getReceiver()) and
not exists(g.(Generated::Call).getMethod().(Generated::ScopeResolution).getScope())
) and
child = SynthChild(SelfKind()) and
i = 0 and
l = NoneLocation()
}
private class RegularMethodCallSelfSynthesis extends Synthesis {
final override predicate child(AstNode parent, int i, Child child, LocationOption l) {
child = SynthChild(SelfKind()) and
i = 0 and
exists(Generated::AstNode g |
parent = TRegularMethodCall(g) and
// If there's no explicit receiver (or scope resolution that acts like a
// receiver), then the receiver is implicitly `self`. N.B. `::Foo()` is
// not valid Ruby.
not exists(g.(Generated::Call).getReceiver()) and
not exists(g.(Generated::Call).getMethod().(Generated::ScopeResolution).getScope())
) and
l = NoneLocation()
regularMethodCallSelfSynthesis(parent, i, child, l)
}
}
}
private module SetterDesugar {
/** An assignment where the left-hand side is a method call. */
private class SetterAssignExpr extends AssignExpr {
private MethodCall mc;
pragma[nomagic]
SetterAssignExpr() { mc = this.getLeftOperand() }
MethodCall getMethodCall() { result = mc }
pragma[nomagic]
MethodCallKind getCallKind(boolean setter, int arity) {
result = MethodCallKind(mc.getMethodName(), setter, arity)
}
pragma[nomagic]
Expr getReceiver() { result = mc.getReceiver() }
pragma[nomagic]
Expr getArgument(int i) { result = mc.getArgument(i) }
pragma[nomagic]
int getNumberOfArguments() { result = mc.getNumberOfArguments() }
pragma[nomagic]
LocationOption getMethodCallLocation() { result = getSomeLocation(mc) }
}
pragma[nomagic]
private predicate setterMethodCallSynthesis(AstNode parent, int i, Child child, LocationOption l) {
exists(SetterAssignExpr sae |
parent = sae and
i = -1 and
child = SynthChild(StmtSequenceKind()) and
l = NoneLocation()
or
exists(AstNode seq | seq = TStmtSequenceSynth(sae, -1) |
parent = seq and
i = 0 and
child = SynthChild(sae.getCallKind(true, sae.getNumberOfArguments() + 1)) and
l = sae.getMethodCallLocation()
or
exists(AstNode call | call = TMethodCallSynth(seq, 0, _, _, _) |
parent = call and
i = 0 and
child = RealChild(sae.getReceiver()) and
l = NoneLocation()
or
parent = call and
child = RealChild(sae.getArgument(i - 1)) and
l = NoneLocation()
or
l = sae.getMethodCallLocation() and
exists(int valueIndex | valueIndex = sae.getNumberOfArguments() + 1 |
parent = call and
i = valueIndex and
child = SynthChild(AssignExprKind())
or
parent = TAssignExprSynth(call, valueIndex) and
(
i = 0 and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(sae, 0)))
or
i = 1 and
child = RealChild(sae.getRightOperand())
)
)
)
or
parent = seq and
i = 1 and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(sae, 0))) and
l = sae.getMethodCallLocation()
)
)
}
/**
* ```rb
* x.foo = y
@@ -171,68 +267,23 @@ private module SetterDesugar {
*/
private class SetterMethodCallSynthesis extends Synthesis {
final override predicate child(AstNode parent, int i, Child child, LocationOption l) {
exists(AssignExpr ae, MethodCall mc | mc = ae.getLeftOperand() |
parent = ae and
i = -1 and
child = SynthChild(StmtSequenceKind()) and
l = NoneLocation()
or
exists(AstNode seq | seq = getSynthChild(ae, -1) |
parent = seq and
i = 0 and
child = SynthChild(getCallKind(mc, true, mc.getNumberOfArguments() + 1)) and
l = getSomeLocation(mc)
or
exists(AstNode call | call = getSynthChild(seq, 0) |
parent = call and
i = 0 and
child = RealChild(mc.getReceiver()) and
l = NoneLocation()
or
parent = call and
child = RealChild(mc.getArgument(i - 1)) and
l = NoneLocation()
or
l = getSomeLocation(mc) and
exists(int valueIndex | valueIndex = mc.getNumberOfArguments() + 1 |
parent = call and
i = valueIndex and
child = SynthChild(AssignExprKind())
or
parent = getSynthChild(call, valueIndex) and
(
i = 0 and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(ae, 0)))
or
i = 1 and
child = RealChild(ae.getRightOperand())
)
)
)
or
parent = seq and
i = 1 and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(ae, 0))) and
l = getSomeLocation(mc)
)
)
setterMethodCallSynthesis(parent, i, child, l)
}
final override predicate excludeFromControlFlowTree(AstNode n) {
n.(MethodCall) = any(AssignExpr ae).getLeftOperand()
n = any(SetterAssignExpr sae).getMethodCall()
}
final override predicate localVariable(AstNode n, int i) {
n.(AssignExpr).getLeftOperand() instanceof MethodCall and
n instanceof SetterAssignExpr and
i = 0
}
final override predicate methodCall(string name, boolean setter, int arity) {
exists(AssignExpr ae, MethodCall mc |
mc = ae.getLeftOperand() and
name = mc.getMethodName() and
exists(SetterAssignExpr sae |
name = sae.getMethodCall().getMethodName() and
setter = true and
arity = mc.getNumberOfArguments() + 1
arity = sae.getNumberOfArguments() + 1
)
}
}
@@ -279,6 +330,57 @@ private module AssignOperationDesugar {
)
}
/** An assignment operation where the left-hand side is a variable. */
private class VariableAssignOperation extends AssignOperation {
private Variable v;
pragma[nomagic]
VariableAssignOperation() { v = this.getLeftOperand().(VariableAccess).getVariable() }
pragma[nomagic]
SynthKind getVariableAccessKind() {
result in [
LocalVariableAccessRealKind(v).(SynthKind), InstanceVariableAccessKind(v),
ClassVariableAccessKind(v), GlobalVariableAccessKind(v)
]
}
}
pragma[nomagic]
private predicate variableAssignOperationSynthesis(
AstNode parent, int i, Child child, LocationOption l
) {
exists(VariableAssignOperation vao |
parent = vao and
i = -1 and
child = SynthChild(AssignExprKind()) and
l = NoneLocation()
or
exists(AstNode assign | assign = TAssignExprSynth(vao, -1) |
parent = assign and
i = 0 and
child = RealChild(vao.getLeftOperand()) and
l = NoneLocation()
or
parent = assign and
i = 1 and
child = SynthChild(getKind(vao)) and
l = SomeLocation(getAssignOperationLocation(vao))
or
parent = getSynthChild(assign, 1) and
(
i = 0 and
child = SynthChild(vao.getVariableAccessKind()) and
l = getSomeLocation(vao.getLeftOperand())
or
i = 1 and
child = RealChild(vao.getRightOperand()) and
l = NoneLocation()
)
)
)
}
/**
* ```rb
* x += y
@@ -294,46 +396,133 @@ private module AssignOperationDesugar {
*/
private class VariableAssignOperationSynthesis extends Synthesis {
final override predicate child(AstNode parent, int i, Child child, LocationOption l) {
exists(AssignOperation ao, VariableReal v |
v = ao.getLeftOperand().(VariableAccess).getVariable()
|
parent = ao and
i = -1 and
child = SynthChild(AssignExprKind()) and
l = NoneLocation()
or
exists(AstNode assign | assign = getSynthChild(ao, -1) |
parent = assign and
i = 0 and
child = RealChild(ao.getLeftOperand()) and
l = NoneLocation()
or
parent = assign and
i = 1 and
child = SynthChild(getKind(ao)) and
l = SomeLocation(getAssignOperationLocation(ao))
or
parent = getSynthChild(assign, 1) and
(
i = 0 and
child =
SynthChild([
LocalVariableAccessRealKind(v).(SynthKind), InstanceVariableAccessKind(v),
ClassVariableAccessKind(v), GlobalVariableAccessKind(v)
]) and
l = getSomeLocation(ao.getLeftOperand())
or
i = 1 and
child = RealChild(ao.getRightOperand()) and
l = NoneLocation()
)
)
)
variableAssignOperationSynthesis(parent, i, child, l)
}
}
/** Gets an assignment operation where the LHS is method call `mc`. */
private AssignOperation assignOperationMethodCall(MethodCall mc) { result.getLeftOperand() = mc }
/** An assignment operation where the left-hand side is a method call. */
private class SetterAssignOperation extends AssignOperation {
private MethodCall mc;
pragma[nomagic]
SetterAssignOperation() { mc = this.getLeftOperand() }
MethodCall getMethodCall() { result = mc }
pragma[nomagic]
MethodCallKind getCallKind(boolean setter, int arity) {
result = MethodCallKind(mc.getMethodName(), setter, arity)
}
pragma[nomagic]
Expr getReceiver() { result = mc.getReceiver() }
pragma[nomagic]
Expr getArgument(int i) { result = mc.getArgument(i) }
pragma[nomagic]
int getNumberOfArguments() { result = mc.getNumberOfArguments() }
pragma[nomagic]
LocationOption getMethodCallLocation() { result = getSomeLocation(mc) }
}
pragma[nomagic]
private predicate methodCallAssignOperationSynthesis(
AstNode parent, int i, Child child, LocationOption l
) {
exists(SetterAssignOperation sao |
parent = sao and
i = -1 and
child = SynthChild(StmtSequenceKind()) and
l = NoneLocation()
or
exists(AstNode seq, AstNode receiver |
seq = TStmtSequenceSynth(sao, -1) and receiver = sao.getReceiver()
|
// `__synth__0 = foo`
assign(parent, i, child, TLocalVariableSynth(sao, 0), seq, 0, receiver) and
l = getSomeLocation(receiver)
or
// `__synth__1 = bar`
exists(Expr arg, int j | arg = sao.getArgument(j - 1) |
assign(parent, i, child, TLocalVariableSynth(sao, j), seq, j, arg) and
l = getSomeLocation(arg)
)
or
// `__synth__2 = __synth__0.[](__synth__1) + y`
exists(int opAssignIndex | opAssignIndex = sao.getNumberOfArguments() + 1 |
parent = seq and
i = opAssignIndex and
child = SynthChild(AssignExprKind()) and
l = SomeLocation(getAssignOperationLocation(sao))
or
exists(AstNode assign | assign = TAssignExprSynth(seq, opAssignIndex) |
parent = assign and
i = 0 and
child =
SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(sao, opAssignIndex))) and
l = SomeLocation(getAssignOperationLocation(sao))
or
parent = assign and
i = 1 and
child = SynthChild(getKind(sao)) and
l = SomeLocation(getAssignOperationLocation(sao))
or
// `__synth__0.[](__synth__1) + y`
exists(AstNode op | op = getSynthChild(assign, 1) |
parent = op and
i = 0 and
child = SynthChild(sao.getCallKind(false, sao.getNumberOfArguments())) and
l = sao.getMethodCallLocation()
or
parent = TMethodCallSynth(op, 0, _, _, _) and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(sao, i))) and
(
i = 0 and
l = getSomeLocation(receiver)
or
l = getSomeLocation(sao.getArgument(i - 1))
)
or
parent = op and
i = 1 and
child = RealChild(sao.getRightOperand()) and
l = NoneLocation()
)
)
or
// `__synth__0.[]=(__synth__1, __synth__2);`
parent = seq and
i = opAssignIndex + 1 and
child = SynthChild(sao.getCallKind(true, opAssignIndex)) and
l = sao.getMethodCallLocation()
or
exists(AstNode setter | setter = TMethodCallSynth(seq, opAssignIndex + 1, _, _, _) |
parent = setter and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(sao, i))) and
(
i = 0 and
l = getSomeLocation(receiver)
or
l = getSomeLocation(sao.getArgument(i - 1))
)
or
parent = setter and
i = opAssignIndex + 1 and
child =
SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(sao, opAssignIndex))) and
l = SomeLocation(getAssignOperationLocation(sao))
)
or
parent = seq and
i = opAssignIndex + 2 and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(sao, opAssignIndex))) and
l = SomeLocation(getAssignOperationLocation(sao))
)
)
)
}
/**
* ```rb
@@ -352,119 +541,181 @@ private module AssignOperationDesugar {
*/
private class MethodCallAssignOperationSynthesis extends Synthesis {
final override predicate child(AstNode parent, int i, Child child, LocationOption l) {
exists(AssignOperation ao, MethodCall mc | ao = assignOperationMethodCall(mc) |
parent = ao and
i = -1 and
child = SynthChild(StmtSequenceKind()) and
l = NoneLocation()
or
exists(AstNode seq, AstNode receiver |
seq = getSynthChild(ao, -1) and receiver = mc.getReceiver()
|
// `__synth__0 = foo`
assign(parent, i, child, TLocalVariableSynth(ao, 0), seq, 0, receiver) and
l = getSomeLocation(receiver)
or
// `__synth__1 = bar`
exists(Expr arg, int j | arg = mc.getArgument(j - 1) |
assign(parent, i, child, TLocalVariableSynth(ao, j), seq, j, arg) and
l = getSomeLocation(arg)
)
or
// `__synth__2 = __synth__0.[](__synth__1) + y`
exists(int opAssignIndex | opAssignIndex = mc.getNumberOfArguments() + 1 |
parent = seq and
i = opAssignIndex and
child = SynthChild(AssignExprKind()) and
l = SomeLocation(getAssignOperationLocation(ao))
or
exists(AstNode assign | assign = getSynthChild(seq, opAssignIndex) |
parent = assign and
i = 0 and
child =
SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(ao, opAssignIndex))) and
l = SomeLocation(getAssignOperationLocation(ao))
or
parent = assign and
i = 1 and
child = SynthChild(getKind(ao)) and
l = SomeLocation(getAssignOperationLocation(ao))
or
// `__synth__0.[](__synth__1) + y`
exists(AstNode op | op = getSynthChild(assign, 1) |
parent = op and
i = 0 and
child = SynthChild(getCallKind(mc, false, mc.getNumberOfArguments())) and
l = getSomeLocation(mc)
or
parent = getSynthChild(op, 0) and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(ao, i))) and
(
i = 0 and
l = getSomeLocation(receiver)
or
l = getSomeLocation(mc.getArgument(i - 1))
)
or
parent = op and
i = 1 and
child = RealChild(ao.getRightOperand()) and
l = NoneLocation()
)
)
or
// `__synth__0.[]=(__synth__1, __synth__2);`
parent = seq and
i = opAssignIndex + 1 and
child = SynthChild(getCallKind(mc, true, opAssignIndex)) and
l = getSomeLocation(mc)
or
exists(AstNode setter | setter = getSynthChild(seq, opAssignIndex + 1) |
parent = setter and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(ao, i))) and
(
i = 0 and
l = getSomeLocation(receiver)
or
l = getSomeLocation(mc.getArgument(i - 1))
)
or
parent = setter and
i = opAssignIndex + 1 and
child =
SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(ao, opAssignIndex))) and
l = SomeLocation(getAssignOperationLocation(ao))
)
or
parent = seq and
i = opAssignIndex + 2 and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(ao, opAssignIndex))) and
l = SomeLocation(getAssignOperationLocation(ao))
)
)
)
methodCallAssignOperationSynthesis(parent, i, child, l)
}
final override predicate localVariable(AstNode n, int i) {
exists(MethodCall mc | n = assignOperationMethodCall(mc) |
i in [0 .. mc.getNumberOfArguments() + 1]
)
n = any(SetterAssignOperation sao | i in [0 .. sao.getNumberOfArguments() + 1])
}
final override predicate methodCall(string name, boolean setter, int arity) {
exists(MethodCall mc | exists(assignOperationMethodCall(mc)) |
name = mc.getMethodName() and
exists(SetterAssignOperation sao | name = sao.getMethodCall().getMethodName() |
setter = false and
arity = mc.getNumberOfArguments()
arity = sao.getNumberOfArguments()
or
name = mc.getMethodName() and
setter = true and
arity = mc.getNumberOfArguments() + 1
arity = sao.getNumberOfArguments() + 1
)
}
final override predicate excludeFromControlFlowTree(AstNode n) {
exists(assignOperationMethodCall(n))
n = any(SetterAssignOperation sao).getMethodCall()
}
}
}
private module CompoundAssignDesugar {
/** An assignment where the left-hand side is a tuple pattern. */
private class TupleAssignExpr extends AssignExpr {
private TuplePattern tp;
pragma[nomagic]
TupleAssignExpr() { tp = this.getLeftOperand() }
TuplePattern getTuplePattern() { result = tp }
pragma[nomagic]
Pattern getElement(int i) { result = tp.getElement(i) }
pragma[nomagic]
int getNumberOfElements() {
toGenerated(tp) = any(TuplePatternImpl impl | result = count(impl.getChildNode(_)))
}
pragma[nomagic]
int getRestIndexOrNumberOfElements() {
result = tp.getRestIndex()
or
toGenerated(tp) = any(TuplePatternImpl impl | not exists(impl.getRestIndex())) and
result = this.getNumberOfElements()
}
pragma[nomagic]
SomeLocation getRightOperandLocation() { result = getSomeLocation(this.getRightOperand()) }
}
pragma[nomagic]
private predicate compoundAssignSynthesis(AstNode parent, int i, Child child, LocationOption l) {
exists(TupleAssignExpr tae |
parent = tae and
i = -1 and
child = SynthChild(StmtSequenceKind()) and
l = NoneLocation()
or
exists(AstNode seq | seq = TStmtSequenceSynth(tae, -1) |
parent = seq and
i = 0 and
child = SynthChild(AssignExprKind()) and
l = tae.getRightOperandLocation()
or
exists(AstNode assign | assign = TAssignExprSynth(seq, 0) |
parent = assign and
i = 0 and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(tae, 0))) and
l = tae.getRightOperandLocation()
or
parent = assign and
i = 1 and
child = SynthChild(SplatExprKind()) and
l = tae.getRightOperandLocation()
or
parent = TSplatExprSynth(assign, 1) and
i = 0 and
child = RealChild(tae.getRightOperand()) and
l = NoneLocation()
)
or
exists(Pattern p, int j, int restIndex |
p = tae.getElement(j) and
restIndex = tae.getRestIndexOrNumberOfElements()
|
parent = seq and
i = j + 1 and
child = SynthChild(AssignExprKind()) and
l = getSomeLocation(p)
or
exists(AstNode assign | assign = TAssignExprSynth(seq, j + 1) |
parent = assign and
i = 0 and
child = RealChild(p) and
l = NoneLocation()
or
parent = assign and
i = 1 and
child = SynthChild(MethodCallKind("[]", false, 1)) and
l = getSomeLocation(p)
or
l = getSomeLocation(p) and
(
parent = TMethodCallSynth(assign, 1, _, _, _) and
i = 0 and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(tae, 0)))
or
j < restIndex and
parent = TMethodCallSynth(assign, 1, _, _, _) and
i = 1 and
child = SynthChild(IntegerLiteralKind(j))
or
j = restIndex and
(
parent = TMethodCallSynth(assign, 1, _, _, _) and
i = 1 and
child = SynthChild(RangeLiteralKind(true))
or
exists(AstNode call |
call = TMethodCallSynth(assign, 1, _, _, _) and
parent = TRangeLiteralSynth(call, 1, _)
|
i = 0 and
child = SynthChild(IntegerLiteralKind(j))
or
i = 1 and
child = SynthChild(IntegerLiteralKind(restIndex - tae.getNumberOfElements()))
)
)
or
j > restIndex and
parent = TMethodCallSynth(assign, 1, _, _, _) and
i = 1 and
child = SynthChild(IntegerLiteralKind(j - tae.getNumberOfElements()))
)
)
)
)
)
}
/**
* ```rb
* x, *y, z = w
* ```
* desguars to
*
* ```rb
* __synth__0 = *w;
* x = __synth__0[0];
* y = __synth__0[1..-2];
* z = __synth__0[-1];
* ```
*/
private class CompoundAssignSynthesis extends Synthesis {
final override predicate child(AstNode parent, int i, Child child, LocationOption l) {
compoundAssignSynthesis(parent, i, child, l)
}
final override predicate localVariable(AstNode n, int i) {
n instanceof TupleAssignExpr and
i = 0
}
final override predicate methodCall(string name, boolean setter, int arity) {
name = "[]" and
setter = false and
arity = 1
}
final override predicate excludeFromControlFlowTree(AstNode n) {
n = any(TupleAssignExpr tae).getTuplePattern()
}
}
}

View File

@@ -434,7 +434,11 @@ class LocalVariableSynth extends LocalVariable, TLocalVariableSynth {
LocalVariableSynth() { this = TLocalVariableSynth(n, i) }
final override string getName() { result = "__synth__" + i }
final override string getName() {
exists(int level | level = desugarLevel(n) |
if level > 0 then result = "__synth__" + i + "__" + level else result = "__synth__" + i
)
}
final override Location getLocation() { result = n.getLocation() }

View File

@@ -287,7 +287,12 @@ module Trees {
}
private class AssignExprTree extends StandardPostOrderTree, AssignExpr {
AssignExprTree() { not this.getLeftOperand() instanceof MethodCall }
AssignExprTree() {
exists(Expr left | left = this.getLeftOperand() |
left instanceof VariableAccess or
left instanceof ConstantAccess
)
}
final override ControlFlowTree getChildNode(int i) {
result = this.getLeftOperand() and i = 0

View File

@@ -31,14 +31,90 @@ calls/calls.rb:
# 315| getAnOperand/getRightOperand: [IntegerLiteral] 10
# 315| getArgument: [IntegerLiteral] 0
# 315| getStmt: [LocalVariableAccess] __synth__0
# 316| [AssignExpr] ... = ...
# 316| getDesugared: [StmtSequence] ...
# 316| getStmt: [AssignExpr] ... = ...
# 316| getAnOperand/getLeftOperand: [MethodCall] call to foo
# 316| getDesugared: [StmtSequence] ...
# 316| getStmt: [SetterMethodCall] call to foo=
# 316| getReceiver: [Self] self
# 316| getArgument: [AssignExpr] ... = ...
# 316| getAnOperand/getRightOperand: [MethodCall] call to []
# 316| getArgument: [IntegerLiteral] 0
# 316| getReceiver: [LocalVariableAccess] __synth__0
# 316| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 316| getStmt: [LocalVariableAccess] __synth__0__1
# 316| getStmt: [AssignExpr] ... = ...
# 316| getDesugared: [StmtSequence] ...
# 316| getStmt: [SetterMethodCall] call to bar=
# 316| getReceiver: [Self] self
# 316| getArgument: [AssignExpr] ... = ...
# 316| getAnOperand/getRightOperand: [MethodCall] call to []
# 316| getArgument: [RangeLiteral] _ .. _
# 316| getBegin: [IntegerLiteral] 1
# 316| getEnd: [IntegerLiteral] -2
# 316| getReceiver: [LocalVariableAccess] __synth__0
# 316| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 316| getStmt: [LocalVariableAccess] __synth__0__1
# 316| getAnOperand/getLeftOperand: [MethodCall] call to bar
# 316| getStmt: [AssignExpr] ... = ...
# 316| getDesugared: [StmtSequence] ...
# 316| getStmt: [SetterMethodCall] call to []=
# 316| getReceiver: [MethodCall] call to foo
# 316| getReceiver: [Self] self
# 316| getArgument: [AssignExpr] ... = ...
# 316| getAnOperand/getRightOperand: [MethodCall] call to []
# 316| getArgument: [IntegerLiteral] -1
# 316| getReceiver: [LocalVariableAccess] __synth__0
# 316| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 316| getArgument: [IntegerLiteral] 4
# 316| getStmt: [LocalVariableAccess] __synth__0__1
# 316| getAnOperand/getLeftOperand: [ElementReference] ...[...]
# 316| getStmt: [AssignExpr] ... = ...
# 316| getAnOperand/getRightOperand: [SplatExpr] * ...
# 316| getAnOperand/getOperand: [ArrayLiteral] [...]
# 316| getElement: [IntegerLiteral] 1
# 316| getElement: [IntegerLiteral] 2
# 316| getElement: [IntegerLiteral] 3
# 316| getElement: [IntegerLiteral] 4
# 316| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 317| [AssignExpr] ... = ...
# 317| getDesugared: [StmtSequence] ...
# 317| getStmt: [AssignExpr] ... = ...
# 317| getAnOperand/getLeftOperand: [LocalVariableAccess] a
# 317| getAnOperand/getRightOperand: [MethodCall] call to []
# 317| getArgument: [IntegerLiteral] 0
# 317| getReceiver: [LocalVariableAccess] __synth__0
# 317| getStmt: [AssignExpr] ... = ...
# 317| getDesugared: [StmtSequence] ...
# 317| getStmt: [SetterMethodCall] call to []=
# 317| getReceiver: [MethodCall] call to foo
# 317| getReceiver: [Self] self
# 317| getArgument: [AssignExpr] ... = ...
# 317| getAnOperand/getRightOperand: [MethodCall] call to []
# 317| getArgument: [RangeLiteral] _ .. _
# 317| getBegin: [IntegerLiteral] 1
# 317| getEnd: [IntegerLiteral] -1
# 317| getReceiver: [LocalVariableAccess] __synth__0
# 317| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1
# 317| getArgument: [IntegerLiteral] 5
# 317| getStmt: [LocalVariableAccess] __synth__0__1
# 317| getAnOperand/getLeftOperand: [ElementReference] ...[...]
# 317| getStmt: [AssignExpr] ... = ...
# 317| getAnOperand/getRightOperand: [SplatExpr] * ...
# 317| getAnOperand/getOperand: [ArrayLiteral] [...]
# 317| getElement: [IntegerLiteral] 1
# 317| getElement: [IntegerLiteral] 2
# 317| getElement: [IntegerLiteral] 3
# 317| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 318| [AssignAddExpr] ... += ...
# 318| getDesugared: [StmtSequence] ...
# 318| getStmt: [SetterMethodCall] call to count=
# 318| getReceiver: [LocalVariableAccess] __synth__0
# 318| getArgument: [LocalVariableAccess] __synth__1
# 318| getStmt: [AssignExpr] ... = ...
# 318| getAnOperand/getRightOperand: [Self] self
# 318| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 318| getStmt: [SetterMethodCall] call to count=
# 318| getReceiver: [LocalVariableAccess] __synth__0
# 318| getArgument: [LocalVariableAccess] __synth__1
# 318| getStmt: [AssignExpr] ... = ...
# 318| getAnOperand/getRightOperand: [AddExpr] ... + ...
# 318| getAnOperand/getLeftOperand: [MethodCall] call to count
@@ -48,14 +124,14 @@ calls/calls.rb:
# 318| getStmt: [LocalVariableAccess] __synth__1
# 319| [AssignAddExpr] ... += ...
# 319| getDesugared: [StmtSequence] ...
# 319| getStmt: [SetterMethodCall] call to []=
# 319| getReceiver: [LocalVariableAccess] __synth__0
# 319| getArgument: [LocalVariableAccess] __synth__1
# 319| getArgument: [LocalVariableAccess] __synth__2
# 319| getStmt: [AssignExpr] ... = ...
# 319| getAnOperand/getRightOperand: [MethodCall] call to foo
# 319| getReceiver: [Self] self
# 319| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 319| getStmt: [SetterMethodCall] call to []=
# 319| getReceiver: [LocalVariableAccess] __synth__0
# 319| getArgument: [LocalVariableAccess] __synth__1
# 319| getArgument: [LocalVariableAccess] __synth__2
# 319| getStmt: [AssignExpr] ... = ...
# 319| getAnOperand/getRightOperand: [IntegerLiteral] 0
# 319| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__1
@@ -69,6 +145,11 @@ calls/calls.rb:
# 319| getStmt: [LocalVariableAccess] __synth__2
# 320| [AssignMulExpr] ... *= ...
# 320| getDesugared: [StmtSequence] ...
# 320| getStmt: [AssignExpr] ... = ...
# 320| getAnOperand/getRightOperand: [MethodCall] call to bar
# 320| getReceiver: [MethodCall] call to foo
# 320| getReceiver: [Self] self
# 320| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 320| getStmt: [SetterMethodCall] call to []=
# 320| getReceiver: [LocalVariableAccess] __synth__0
# 320| getArgument: [LocalVariableAccess] __synth__1
@@ -76,11 +157,6 @@ calls/calls.rb:
# 320| getArgument: [LocalVariableAccess] __synth__3
# 320| getArgument: [LocalVariableAccess] __synth__4
# 320| getStmt: [AssignExpr] ... = ...
# 320| getAnOperand/getRightOperand: [MethodCall] call to bar
# 320| getReceiver: [MethodCall] call to foo
# 320| getReceiver: [Self] self
# 320| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 320| getStmt: [AssignExpr] ... = ...
# 320| getAnOperand/getRightOperand: [IntegerLiteral] 0
# 320| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__1
# 320| getStmt: [AssignExpr] ... = ...

View File

@@ -4,6 +4,8 @@ blockArguments
splatExpr
| calls.rb:270:5:270:8 | * ... | calls.rb:270:6:270:8 | call to bar |
| calls.rb:271:5:271:11 | * ... | calls.rb:271:6:271:11 | call to bar |
| calls.rb:316:31:316:42 | * ... | calls.rb:316:31:316:42 | [...] |
| calls.rb:317:14:317:22 | * ... | calls.rb:317:14:317:22 | [...] |
hashSplatExpr
| calls.rb:274:5:274:9 | ** ... | calls.rb:274:7:274:9 | call to bar |
| calls.rb:275:5:275:12 | ** ... | calls.rb:275:7:275:12 | call to bar |

View File

@@ -35,8 +35,19 @@ callsWithArguments
| calls.rb:315:1:315:6 | ...[...] | [] | 0 | calls.rb:315:5:315:5 | 0 |
| calls.rb:315:1:315:6 | call to []= | []= | 0 | calls.rb:315:5:315:5 | 0 |
| calls.rb:315:1:315:6 | call to []= | []= | 1 | calls.rb:315:1:315:6 | ... = ... |
| calls.rb:316:1:316:8 | call to [] | [] | 0 | calls.rb:316:1:316:8 | 0 |
| calls.rb:316:1:316:8 | call to foo= | foo= | 0 | calls.rb:316:1:316:8 | ... = ... |
| calls.rb:316:12:316:19 | call to [] | [] | 0 | calls.rb:316:12:316:19 | _ .. _ |
| calls.rb:316:12:316:19 | call to bar= | bar= | 0 | calls.rb:316:12:316:19 | ... = ... |
| calls.rb:316:22:316:27 | ...[...] | [] | 0 | calls.rb:316:26:316:26 | 4 |
| calls.rb:316:22:316:27 | call to [] | [] | 0 | calls.rb:316:22:316:27 | -1 |
| calls.rb:316:22:316:27 | call to []= | []= | 0 | calls.rb:316:26:316:26 | 4 |
| calls.rb:316:22:316:27 | call to []= | []= | 1 | calls.rb:316:22:316:27 | ... = ... |
| calls.rb:317:1:317:1 | call to [] | [] | 0 | calls.rb:317:1:317:1 | 0 |
| calls.rb:317:5:317:10 | ...[...] | [] | 0 | calls.rb:317:9:317:9 | 5 |
| calls.rb:317:5:317:10 | call to [] | [] | 0 | calls.rb:317:5:317:10 | _ .. _ |
| calls.rb:317:5:317:10 | call to []= | []= | 0 | calls.rb:317:9:317:9 | 5 |
| calls.rb:317:5:317:10 | call to []= | []= | 1 | calls.rb:317:5:317:10 | ... = ... |
| calls.rb:318:1:318:10 | call to count= | count= | 1 | calls.rb:318:12:318:13 | __synth__1 |
| calls.rb:319:1:319:6 | ...[...] | [] | 0 | calls.rb:319:5:319:5 | 0 |
| calls.rb:319:1:319:6 | call to [] | [] | 0 | calls.rb:319:5:319:5 | __synth__1 |
@@ -225,12 +236,21 @@ callsWithReceiver
| calls.rb:315:1:315:3 | call to foo | calls.rb:315:1:315:3 | self |
| calls.rb:315:1:315:6 | ...[...] | calls.rb:315:1:315:3 | call to foo |
| calls.rb:315:1:315:6 | call to []= | calls.rb:315:1:315:3 | call to foo |
| calls.rb:316:1:316:8 | call to [] | calls.rb:316:1:316:8 | __synth__0 |
| calls.rb:316:1:316:8 | call to foo | calls.rb:316:1:316:4 | self |
| calls.rb:316:1:316:8 | call to foo= | calls.rb:316:1:316:4 | self |
| calls.rb:316:12:316:19 | call to [] | calls.rb:316:12:316:19 | __synth__0 |
| calls.rb:316:12:316:19 | call to bar | calls.rb:316:12:316:15 | self |
| calls.rb:316:12:316:19 | call to bar= | calls.rb:316:12:316:15 | self |
| calls.rb:316:22:316:24 | call to foo | calls.rb:316:22:316:24 | self |
| calls.rb:316:22:316:27 | ...[...] | calls.rb:316:22:316:24 | call to foo |
| calls.rb:316:22:316:27 | call to [] | calls.rb:316:22:316:27 | __synth__0 |
| calls.rb:316:22:316:27 | call to []= | calls.rb:316:22:316:24 | call to foo |
| calls.rb:317:1:317:1 | call to [] | calls.rb:317:1:317:1 | __synth__0 |
| calls.rb:317:5:317:7 | call to foo | calls.rb:317:5:317:7 | self |
| calls.rb:317:5:317:10 | ...[...] | calls.rb:317:5:317:7 | call to foo |
| calls.rb:317:5:317:10 | call to [] | calls.rb:317:5:317:10 | __synth__0 |
| calls.rb:317:5:317:10 | call to []= | calls.rb:317:5:317:7 | call to foo |
| calls.rb:318:1:318:10 | call to count | calls.rb:318:1:318:4 | __synth__0 |
| calls.rb:318:1:318:10 | call to count | calls.rb:318:1:318:4 | self |
| calls.rb:318:1:318:10 | call to count= | calls.rb:318:1:318:4 | __synth__0 |
@@ -287,6 +307,10 @@ superCallsWithBlock
setterCalls
| calls.rb:314:1:314:8 | call to foo= |
| calls.rb:315:1:315:6 | call to []= |
| calls.rb:316:1:316:8 | call to foo= |
| calls.rb:316:12:316:19 | call to bar= |
| calls.rb:316:22:316:27 | call to []= |
| calls.rb:317:5:317:10 | call to []= |
| calls.rb:318:1:318:10 | call to count= |
| calls.rb:319:1:319:6 | call to []= |
| calls.rb:320:1:320:32 | call to []= |

View File

@@ -870,7 +870,7 @@ cfg.rb:
#-----| -> ... ? ... : ...
# 61| ... = ...
#-----| -> x
#-----| -> __synth__0
# 61| C
#-----| -> "constant"
@@ -878,27 +878,87 @@ cfg.rb:
# 61| "constant"
#-----| -> ... = ...
# 62| ... = ...
# 62| ...
#-----| -> pattern
# 62| (..., ...)
#-----| -> 1
# 62| ...
#-----| -> ...
# 62| x
#-----| -> __synth__0
# 62| ... = ...
#-----| -> __synth__0__1
# 62| call to []
#-----| -> ... = ...
# 62| 0
#-----| -> call to []
# 62| __synth__0
#-----| -> 0
# 62| call to []
#-----| -> * ...
# 62| 1
#-----| -> call to []
# 62| __synth__0
#-----| -> 1
# 62| ... = ...
#-----| -> y
# 62| (..., ...)
#-----| -> (..., ...)
# 62| * ...
#-----| -> ... = ...
# 62| __synth__0__1
#-----| -> __synth__0
# 62| y
#-----| -> __synth__0__1
# 62| ... = ...
#-----| -> z
# 62| call to []
#-----| -> ... = ...
# 62| 0
#-----| -> call to []
# 62| __synth__0__1
#-----| -> 0
# 62| z
#-----| -> (..., ...)
#-----| -> __synth__0__1
# 62| ... = ...
#-----| -> ...
# 62| call to []
#-----| -> ... = ...
# 62| 1
#-----| -> call to []
# 62| __synth__0__1
#-----| -> 1
# 62| [...]
#-----| -> * ...
# 62| ... = ...
#-----| -> x
# 62| * ...
#-----| -> ... = ...
# 62| __synth__0
#-----| -> 1
# 62| 1
#-----| -> 2
@@ -1514,8 +1574,8 @@ cfg.rb:
#-----| -> ... rescue ...
# 136| ... / ...
#-----| -> init
#-----| raise -> self
#-----| -> __synth__0
# 136| 1
#-----| -> 0
@@ -1527,7 +1587,7 @@ cfg.rb:
#-----| -> ... / ...
# 136| call to puts
#-----| -> init
#-----| -> __synth__0
# 136| self
#-----| -> "div by zero"
@@ -1535,26 +1595,62 @@ cfg.rb:
# 136| "div by zero"
#-----| -> call to puts
# 138| ... = ...
# 138| ...
#-----| -> M
# 138| (..., ...)
#-----| -> 1
# 138| init
#-----| -> __synth__0
# 138| ... = ...
#-----| -> last
# 138| call to []
#-----| -> ... = ...
# 138| _ .. _
#-----| -> call to []
# 138| __synth__0
#-----| -> 0
# 138| 0
#-----| -> -2
# 138| -2
#-----| -> _ .. _
# 138| last
#-----| -> (..., ...)
#-----| -> __synth__0
# 138| ... = ...
#-----| -> ...
# 138| call to []
#-----| -> ... = ...
# 138| -1
#-----| -> call to []
# 138| __synth__0
#-----| -> -1
# 138| 1
#-----| -> 2
# 138| ... = ...
#-----| -> init
# 138| * ...
#-----| -> ... = ...
# 138| __synth__0
#-----| -> 1
# 138| 2
#-----| -> 3
# 138| 3
#-----| -> ... = ...
#-----| -> * ...
# 140| M
#-----| -> Constant
@@ -2214,18 +2310,18 @@ desugar.rb:
# 14| ...
#-----| -> exit m4 (normal)
# 14| call to count=
#-----| -> __synth__1
# 14| ... = ...
#-----| -> __synth__1
# 14| __synth__0
# 14| call to count=
#-----| -> __synth__1
# 14| __synth__0
#-----| -> x
# 14| __synth__0
#-----| -> __synth__1
# 14| call to count
#-----| -> 1
@@ -2242,10 +2338,10 @@ desugar.rb:
#-----| -> ... = ...
# 14| __synth__1
#-----| -> call to count=
#-----| -> __synth__0
# 14| __synth__1
#-----| -> __synth__0
#-----| -> call to count=
# 14| 1
#-----| -> ... + ...
@@ -2254,7 +2350,7 @@ desugar.rb:
#-----| -> x
# 17| m5
#-----| -> @x
#-----| -> m6
# 17| exit m5
@@ -2276,18 +2372,18 @@ desugar.rb:
# 18| ...
#-----| -> exit m5 (normal)
# 18| call to []=
#-----| -> __synth__4
# 18| ... = ...
#-----| -> __synth__1
# 18| __synth__0
#-----| -> __synth__1
# 18| call to []=
#-----| -> __synth__4
# 18| __synth__0
#-----| -> x
# 18| __synth__0
#-----| -> __synth__1
# 18| call to []
#-----| -> 1
@@ -2301,10 +2397,10 @@ desugar.rb:
#-----| -> __synth__2
# 18| __synth__1
#-----| -> __synth__2
#-----| -> 0
# 18| __synth__1
#-----| -> 0
#-----| -> __synth__2
# 18| __synth__1
#-----| -> __synth__2
@@ -2319,10 +2415,10 @@ desugar.rb:
#-----| -> __synth__3
# 18| __synth__2
#-----| -> __synth__3
#-----| -> y
# 18| __synth__2
#-----| -> y
#-----| -> __synth__3
# 18| __synth__2
#-----| -> __synth__3
@@ -2340,10 +2436,10 @@ desugar.rb:
#-----| -> __synth__4
# 18| __synth__3
#-----| -> __synth__4
#-----| -> x
# 18| __synth__3
#-----| -> x
#-----| -> __synth__4
# 18| __synth__3
#-----| -> call to []
@@ -2361,87 +2457,295 @@ desugar.rb:
#-----| -> ... = ...
# 18| __synth__4
#-----| -> call to []=
#-----| -> __synth__0
# 18| __synth__4
#-----| -> __synth__0
#-----| -> call to []=
# 18| 1
#-----| -> ... + ...
# 21| X
#-----| -> $global_var
# 21| enter m6
#-----| -> __synth__0
# 21| m6
#-----| -> m7
# 21| exit m6
# 21| exit m6 (normal)
#-----| -> exit m6
# 22| x
#-----| -> __synth__0
# 22| ...
#-----| -> exit m6 (normal)
# 22| ... = ...
#-----| -> @x
#-----| -> y
# 22| @x
# 22| call to []
#-----| -> ... = ...
# 22| 0
#-----| -> call to []
# 22| ...
#-----| -> ...
# 22| __synth__0
#-----| -> 0
# 22| y
#-----| -> __synth__0
# 22| ... = ...
#-----| -> self
# 22| call to []
#-----| -> ... = ...
# 22| _ .. _
#-----| -> call to []
# 22| __synth__0
#-----| -> 1
# 22| 1
#-----| -> -2
# 22| -2
#-----| -> _ .. _
# 22| call to z
#-----| -> __synth__0__1
# 22| self
#-----| -> call to z
# 22| call to []
#-----| -> ... = ...
# 23| @x
#-----| -> @x
# 22| -1
#-----| -> call to []
# 23| ... = ...
#-----| -> @@y
# 22| __synth__0
#-----| -> -1
# 23| @x
# 22| call to bar=
#-----| -> __synth__0__1
# 22| __synth__0__1
#-----| -> ...
# 22| ... = ...
#-----| -> call to bar=
# 22| __synth__0__1
#-----| -> __synth__0
# 22| [...]
#-----| -> * ...
# 22| ... = ...
#-----| -> x
# 22| * ...
#-----| -> ... = ...
# 22| __synth__0
#-----| -> 1
# 22| 1
#-----| -> 2
# 23| ... + ...
#-----| -> ... = ...
# 23| 2
#-----| -> ... + ...
# 25| ... = ...
#-----| -> @@y
# 25| @@y
# 22| 2
#-----| -> 3
# 25| 3
#-----| -> ... = ...
# 26| @@y
#-----| -> @@y
# 26| ... = ...
#-----| -> X
# 26| @@y
# 22| 3
#-----| -> 4
# 26| ... / ...
# 22| 4
#-----| -> [...]
# 25| enter m7
#-----| -> __synth__0
# 25| m7
#-----| -> @x
# 25| exit m7
# 25| exit m7 (normal)
#-----| -> exit m7
# 26| x
#-----| -> __synth__0
# 26| ...
#-----| -> exit m7 (normal)
# 26| ... = ...
#-----| -> __synth__0__1
# 26| call to []
#-----| -> ... = ...
# 26| 4
#-----| -> ... / ...
# 26| 0
#-----| -> call to []
# 29| ... = ...
#-----| -> $global_var
# 26| ...
#-----| -> ...
# 29| $global_var
#-----| -> 5
# 26| __synth__0
#-----| -> 0
# 29| 5
# 26| call to []
#-----| -> * ...
# 26| 1
#-----| -> call to []
# 26| __synth__0
#-----| -> 1
# 26| ... = ...
#-----| -> y
# 26| * ...
#-----| -> ... = ...
# 30| $global_var
# 26| __synth__0__1
#-----| -> __synth__0
# 26| y
#-----| -> __synth__0__1
# 26| ... = ...
#-----| -> z
# 26| call to []
#-----| -> ... = ...
# 26| 0
#-----| -> call to []
# 26| __synth__0__1
#-----| -> 0
# 26| z
#-----| -> __synth__0__1
# 26| ... = ...
#-----| -> ...
# 26| call to []
#-----| -> ... = ...
# 26| 1
#-----| -> call to []
# 26| __synth__0__1
#-----| -> 1
# 26| [...]
#-----| -> * ...
# 26| ... = ...
#-----| -> x
# 26| * ...
#-----| -> ... = ...
# 26| __synth__0
#-----| -> 1
# 26| 1
#-----| -> 2
# 26| [...]
#-----| -> [...]
# 26| 2
#-----| -> 3
# 26| 3
#-----| -> [...]
# 29| X
#-----| -> $global_var
# 30| ... = ...
#-----| -> exit desugar.rb (normal)
#-----| -> @x
# 30| $global_var
#-----| -> 6
# 30| @x
#-----| -> 1
# 30| ... * ...
# 30| 1
#-----| -> ... = ...
# 30| 6
# 31| @x
#-----| -> @x
# 31| ... = ...
#-----| -> @@y
# 31| @x
#-----| -> 2
# 31| ... + ...
#-----| -> ... = ...
# 31| 2
#-----| -> ... + ...
# 33| ... = ...
#-----| -> @@y
# 33| @@y
#-----| -> 3
# 33| 3
#-----| -> ... = ...
# 34| @@y
#-----| -> @@y
# 34| ... = ...
#-----| -> X
# 34| @@y
#-----| -> 4
# 34| ... / ...
#-----| -> ... = ...
# 34| 4
#-----| -> ... / ...
# 37| ... = ...
#-----| -> $global_var
# 37| $global_var
#-----| -> 5
# 37| 5
#-----| -> ... = ...
# 38| $global_var
#-----| -> $global_var
# 38| ... = ...
#-----| -> exit desugar.rb (normal)
# 38| $global_var
#-----| -> 6
# 38| ... * ...
#-----| -> ... = ...
# 38| 6
#-----| -> ... * ...
exit.rb:

View File

@@ -18,6 +18,14 @@ def m5 x, y
x.foo[0, y.bar, x.baz + 3] += 1
end
def m6
x, *y, z.bar = [1, 2, 3, 4]
end
def m7
x, (y, z) = [1, [2, 3]]
end
class X
@x = 1
@x += 2

View File

@@ -43,10 +43,12 @@ definition
| scopes.rb:7:1:7:5 | ... = ... | scopes.rb:7:1:7:1 | a |
| scopes.rb:9:9:18:3 | <captured> | scopes.rb:7:1:7:1 | a |
| scopes.rb:11:4:11:9 | ... = ... | scopes.rb:7:1:7:1 | a |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:7:1:7:1 | a |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:7:13:7 | b |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:11:13:11 | c |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:14:13:14 | d |
| scopes.rb:13:4:13:4 | ... = ... | scopes.rb:7:1:7:1 | a |
| scopes.rb:13:7:13:7 | ... = ... | scopes.rb:13:7:13:7 | b |
| scopes.rb:13:10:13:15 | ... = ... | scopes.rb:13:10:13:15 | __synth__0__1 |
| scopes.rb:13:11:13:11 | ... = ... | scopes.rb:13:11:13:11 | c |
| scopes.rb:13:14:13:14 | ... = ... | scopes.rb:13:14:13:14 | d |
| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 |
| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x |
| scopes.rb:42:2:42:9 | ... = ... | scopes.rb:42:2:42:4 | var |
| scopes.rb:46:5:46:13 | ... = ... | scopes.rb:46:5:46:8 | var2 |
@@ -128,10 +130,15 @@ read
| scopes.rb:9:9:18:3 | <captured> | scopes.rb:7:1:7:1 | a | scopes.rb:10:9:10:9 | a |
| scopes.rb:9:9:18:3 | <captured> | scopes.rb:7:1:7:1 | a | scopes.rb:11:4:11:4 | a |
| scopes.rb:11:4:11:9 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:12:9:12:9 | a |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:14:9:14:9 | a |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:7:13:7 | b | scopes.rb:15:9:15:9 | b |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:11:13:11 | c | scopes.rb:16:9:16:9 | c |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:14:13:14 | d | scopes.rb:17:9:17:9 | d |
| scopes.rb:13:4:13:4 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:14:9:14:9 | a |
| scopes.rb:13:7:13:7 | ... = ... | scopes.rb:13:7:13:7 | b | scopes.rb:15:9:15:9 | b |
| scopes.rb:13:10:13:15 | ... = ... | scopes.rb:13:10:13:15 | __synth__0__1 | scopes.rb:13:11:13:11 | __synth__0__1 |
| scopes.rb:13:10:13:15 | ... = ... | scopes.rb:13:10:13:15 | __synth__0__1 | scopes.rb:13:14:13:14 | __synth__0__1 |
| scopes.rb:13:11:13:11 | ... = ... | scopes.rb:13:11:13:11 | c | scopes.rb:16:9:16:9 | c |
| scopes.rb:13:14:13:14 | ... = ... | scopes.rb:13:14:13:14 | d | scopes.rb:17:9:17:9 | d |
| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 | scopes.rb:13:4:13:4 | __synth__0 |
| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 | scopes.rb:13:7:13:7 | __synth__0 |
| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 | scopes.rb:13:10:13:15 | __synth__0 |
| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:28:8:28:8 | x |
| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:31:10:31:10 | x |
| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:34:7:34:7 | x |
@@ -209,10 +216,12 @@ firstRead
| scopes.rb:7:1:7:5 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:8:6:8:6 | a |
| scopes.rb:9:9:18:3 | <captured> | scopes.rb:7:1:7:1 | a | scopes.rb:10:9:10:9 | a |
| scopes.rb:11:4:11:9 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:12:9:12:9 | a |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:14:9:14:9 | a |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:7:13:7 | b | scopes.rb:15:9:15:9 | b |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:11:13:11 | c | scopes.rb:16:9:16:9 | c |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:14:13:14 | d | scopes.rb:17:9:17:9 | d |
| scopes.rb:13:4:13:4 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:14:9:14:9 | a |
| scopes.rb:13:7:13:7 | ... = ... | scopes.rb:13:7:13:7 | b | scopes.rb:15:9:15:9 | b |
| scopes.rb:13:10:13:15 | ... = ... | scopes.rb:13:10:13:15 | __synth__0__1 | scopes.rb:13:11:13:11 | __synth__0__1 |
| scopes.rb:13:11:13:11 | ... = ... | scopes.rb:13:11:13:11 | c | scopes.rb:16:9:16:9 | c |
| scopes.rb:13:14:13:14 | ... = ... | scopes.rb:13:14:13:14 | d | scopes.rb:17:9:17:9 | d |
| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 | scopes.rb:13:4:13:4 | __synth__0 |
| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:28:8:28:8 | x |
| scopes.rb:42:2:42:9 | ... = ... | scopes.rb:42:2:42:4 | var | scopes.rb:44:5:44:7 | var |
| scopes.rb:46:5:46:13 | ... = ... | scopes.rb:46:5:46:8 | var2 | scopes.rb:47:5:47:8 | var2 |
@@ -280,10 +289,12 @@ lastRead
| scopes.rb:7:1:7:5 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:8:6:8:6 | a |
| scopes.rb:9:9:18:3 | <captured> | scopes.rb:7:1:7:1 | a | scopes.rb:11:4:11:4 | a |
| scopes.rb:11:4:11:9 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:12:9:12:9 | a |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:14:9:14:9 | a |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:7:13:7 | b | scopes.rb:15:9:15:9 | b |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:11:13:11 | c | scopes.rb:16:9:16:9 | c |
| scopes.rb:13:4:13:32 | ... = ... | scopes.rb:13:14:13:14 | d | scopes.rb:17:9:17:9 | d |
| scopes.rb:13:4:13:4 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:14:9:14:9 | a |
| scopes.rb:13:7:13:7 | ... = ... | scopes.rb:13:7:13:7 | b | scopes.rb:15:9:15:9 | b |
| scopes.rb:13:10:13:15 | ... = ... | scopes.rb:13:10:13:15 | __synth__0__1 | scopes.rb:13:14:13:14 | __synth__0__1 |
| scopes.rb:13:11:13:11 | ... = ... | scopes.rb:13:11:13:11 | c | scopes.rb:16:9:16:9 | c |
| scopes.rb:13:14:13:14 | ... = ... | scopes.rb:13:14:13:14 | d | scopes.rb:17:9:17:9 | d |
| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 | scopes.rb:13:10:13:15 | __synth__0 |
| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:37:5:37:5 | x |
| scopes.rb:42:2:42:9 | ... = ... | scopes.rb:42:2:42:4 | var | scopes.rb:44:5:44:7 | var |
| scopes.rb:46:5:46:13 | ... = ... | scopes.rb:46:5:46:8 | var2 | scopes.rb:47:5:47:8 | var2 |
@@ -317,6 +328,9 @@ adjacentReads
| parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:8:6:8:11 | pizzas | parameters.rb:11:14:11:19 | pizzas |
| parameters.rb:25:15:25:18 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:40:25:43 | name | parameters.rb:26:8:26:11 | name |
| scopes.rb:9:9:18:3 | <captured> | scopes.rb:7:1:7:1 | a | scopes.rb:10:9:10:9 | a | scopes.rb:11:4:11:4 | a |
| scopes.rb:13:10:13:15 | ... = ... | scopes.rb:13:10:13:15 | __synth__0__1 | scopes.rb:13:11:13:11 | __synth__0__1 | scopes.rb:13:14:13:14 | __synth__0__1 |
| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 | scopes.rb:13:4:13:4 | __synth__0 | scopes.rb:13:7:13:7 | __synth__0 |
| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 | scopes.rb:13:7:13:7 | __synth__0 | scopes.rb:13:10:13:15 | __synth__0 |
| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:28:8:28:8 | x | scopes.rb:31:10:31:10 | x |
| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:31:10:31:10 | x | scopes.rb:34:7:34:7 | x |
| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:34:7:34:7 | x | scopes.rb:34:14:34:14 | x |

View File

@@ -215,10 +215,16 @@ explicitWrite
| scopes.rb:7:1:7:1 | a | scopes.rb:7:1:7:5 | ... = ... |
| scopes.rb:11:4:11:4 | a | scopes.rb:11:4:11:9 | ... += ... |
| scopes.rb:11:4:11:4 | a | scopes.rb:11:4:11:9 | ... = ... |
| scopes.rb:13:4:13:4 | a | scopes.rb:13:4:13:4 | ... = ... |
| scopes.rb:13:4:13:4 | a | scopes.rb:13:4:13:32 | ... = ... |
| scopes.rb:13:7:13:7 | b | scopes.rb:13:4:13:32 | ... = ... |
| scopes.rb:13:7:13:7 | b | scopes.rb:13:7:13:7 | ... = ... |
| scopes.rb:13:10:13:15 | __synth__0__1 | scopes.rb:13:10:13:15 | ... = ... |
| scopes.rb:13:11:13:11 | c | scopes.rb:13:4:13:32 | ... = ... |
| scopes.rb:13:11:13:11 | c | scopes.rb:13:11:13:11 | ... = ... |
| scopes.rb:13:14:13:14 | d | scopes.rb:13:4:13:32 | ... = ... |
| scopes.rb:13:14:13:14 | d | scopes.rb:13:14:13:14 | ... = ... |
| scopes.rb:13:19:13:32 | __synth__0 | scopes.rb:13:19:13:32 | ... = ... |
| scopes.rb:21:1:21:7 | $global | scopes.rb:21:1:21:12 | ... = ... |
| scopes.rb:24:1:24:6 | script | scopes.rb:24:1:24:11 | ... = ... |
| scopes.rb:27:1:27:1 | x | scopes.rb:27:1:27:5 | ... = ... |
@@ -334,6 +340,11 @@ readAccess
| scopes.rb:10:9:10:9 | a |
| scopes.rb:11:4:11:4 | a |
| scopes.rb:12:9:12:9 | a |
| scopes.rb:13:4:13:4 | __synth__0 |
| scopes.rb:13:7:13:7 | __synth__0 |
| scopes.rb:13:10:13:15 | __synth__0 |
| scopes.rb:13:11:13:11 | __synth__0__1 |
| scopes.rb:13:14:13:14 | __synth__0__1 |
| scopes.rb:14:9:14:9 | a |
| scopes.rb:15:9:15:9 | b |
| scopes.rb:16:9:16:9 | c |

View File

@@ -54,7 +54,9 @@
| scopes.rb:4:4:4:4 | a |
| scopes.rb:7:1:7:1 | a |
| scopes.rb:9:14:9:14 | x |
| scopes.rb:13:4:13:32 | __synth__0 |
| scopes.rb:13:7:13:7 | b |
| scopes.rb:13:10:13:15 | __synth__0__1 |
| scopes.rb:13:11:13:11 | c |
| scopes.rb:13:14:13:14 | d |
| scopes.rb:24:1:24:6 | script |