Merge pull request #10918 from asgerf/rb/constant-compound-assignment

Ruby: handle compound constant-assignment
This commit is contained in:
Asger F
2022-10-24 14:07:28 +02:00
committed by GitHub
16 changed files with 568 additions and 11 deletions

View File

@@ -252,6 +252,20 @@ private class ConstantReadAccessSynth extends ConstantAccess, TConstantReadAcces
final override predicate hasGlobalScope() { value.matches("::%") }
}
private class ConstantWriteAccessSynth extends ConstantAccess, TConstantWriteAccessSynth {
private string value;
ConstantWriteAccessSynth() { this = TConstantWriteAccessSynth(_, _, value) }
final override string getName() {
if this.hasGlobalScope() then result = value.suffix(2) else result = value
}
final override Expr getScopeExpr() { synthChild(this, 0, result) }
final override predicate hasGlobalScope() { value.matches("::%") }
}
/**
* A use (read) of a constant.
*
@@ -323,7 +337,9 @@ class ConstantReadAccess extends ConstantAccess {
*/
class ConstantWriteAccess extends ConstantAccess {
ConstantWriteAccess() {
explicitAssignmentNode(toGenerated(this), _) or this instanceof TNamespace
explicitAssignmentNode(toGenerated(this), _) or
this instanceof TNamespace or
this instanceof TConstantWriteAccessSynth
}
override string getAPrimaryQlClass() { result = "ConstantWriteAccess" }

View File

@@ -61,7 +61,7 @@ class ArgumentList extends Expr, TArgumentList {
private class LhsExpr_ =
TVariableAccess or TTokenConstantAccess or TScopeResolutionConstantAccess or TMethodCall or
TDestructuredLhsExpr;
TDestructuredLhsExpr or TConstantWriteAccessSynth;
/**
* A "left-hand-side" (LHS) expression. An `LhsExpr` can occur on the left-hand side of

View File

@@ -116,6 +116,9 @@ private module Cached {
TConstantReadAccessSynth(Ast::AstNode parent, int i, string value) {
mkSynthChild(ConstantReadAccessKind(value), parent, i)
} or
TConstantWriteAccessSynth(Ast::AstNode parent, int i, string value) {
mkSynthChild(ConstantWriteAccessKind(value), parent, i)
} or
TDefinedExpr(Ruby::Unary g) { g instanceof @ruby_unary_definedquestion } or
TDelimitedSymbolLiteral(Ruby::DelimitedSymbol g) or
TDestructuredLeftAssignment(Ruby::DestructuredLeftAssignment g) {
@@ -373,12 +376,13 @@ private module Cached {
class TAstNodeSynth =
TAddExprSynth or TAssignExprSynth or TBitwiseAndExprSynth or TBitwiseOrExprSynth or
TBitwiseXorExprSynth or TBraceBlockSynth or TClassVariableAccessSynth or
TConstantReadAccessSynth or TDivExprSynth or TExponentExprSynth or
TGlobalVariableAccessSynth or TIfSynth or TInstanceVariableAccessSynth or
TIntegerLiteralSynth or TLShiftExprSynth or TLocalVariableAccessSynth or
TLogicalAndExprSynth or TLogicalOrExprSynth or TMethodCallSynth or TModuloExprSynth or
TMulExprSynth or TNilLiteralSynth or TRShiftExprSynth or TRangeLiteralSynth or TSelfSynth or
TSimpleParameterSynth or TSplatExprSynth or TStmtSequenceSynth or TSubExprSynth;
TConstantReadAccessSynth or TConstantWriteAccessSynth or TDivExprSynth or
TExponentExprSynth or TGlobalVariableAccessSynth or TIfSynth or
TInstanceVariableAccessSynth or TIntegerLiteralSynth or TLShiftExprSynth or
TLocalVariableAccessSynth or TLogicalAndExprSynth or TLogicalOrExprSynth or
TMethodCallSynth or TModuloExprSynth or TMulExprSynth or TNilLiteralSynth or
TRShiftExprSynth or TRangeLiteralSynth or TSelfSynth or TSimpleParameterSynth or
TSplatExprSynth or TStmtSequenceSynth or TSubExprSynth;
/**
* Gets the underlying TreeSitter entity for a given AST node. This does not
@@ -565,6 +569,8 @@ private module Cached {
or
result = TConstantReadAccessSynth(parent, i, _)
or
result = TConstantWriteAccessSynth(parent, i, _)
or
result = TDivExprSynth(parent, i)
or
result = TExponentExprSynth(parent, i)
@@ -672,7 +678,8 @@ class TMethodCall =
class TSuperCall = TTokenSuperCall or TRegularSuperCall;
class TConstantAccess =
TTokenConstantAccess or TScopeResolutionConstantAccess or TNamespace or TConstantReadAccessSynth;
TTokenConstantAccess or TScopeResolutionConstantAccess or TNamespace or
TConstantReadAccessSynth or TConstantWriteAccessSynth;
class TControlExpr = TConditionalExpr or TCaseExpr or TCaseMatch or TLoop;

View File

@@ -42,7 +42,8 @@ newtype SynthKind =
StmtSequenceKind() or
SelfKind(SelfVariable v) or
SubExprKind() or
ConstantReadAccessKind(string value) { any(Synthesis s).constantReadAccess(value) }
ConstantReadAccessKind(string value) { any(Synthesis s).constantReadAccess(value) } or
ConstantWriteAccessKind(string value) { any(Synthesis s).constantWriteAccess(value) }
/**
* An AST child.
@@ -107,6 +108,11 @@ class Synthesis extends TSynthesis {
*/
predicate constantReadAccess(string name) { none() }
/**
* Holds if a constant write access of `name` is needed.
*/
predicate constantWriteAccess(string name) { none() }
/**
* Holds if `n` should be excluded from `ControlFlowTree` in the CFG construction.
*/
@@ -493,6 +499,231 @@ private module AssignOperationDesugar {
}
}
/**
* An assignment operation where the left-hand side is a constant
* without scope expression, such as`FOO` or `::Foo`.
*/
private class ConstantAssignOperation extends AssignOperation {
string name;
pragma[nomagic]
ConstantAssignOperation() {
name =
any(Ruby::Constant constant | TTokenConstantAccess(constant) = this.getLeftOperand())
.getValue()
or
name =
"::" +
any(Ruby::Constant constant |
TScopeResolutionConstantAccess(any(Ruby::ScopeResolution g | not exists(g.getScope())),
constant) = this.getLeftOperand()
).getValue()
}
final string getName() { result = name }
}
pragma[nomagic]
private predicate constantAssignOperationSynthesis(AstNode parent, int i, Child child) {
exists(ConstantAssignOperation cao |
parent = cao and
i = -1 and
child = SynthChild(AssignExprKind())
or
exists(AstNode assign | assign = TAssignExprSynth(cao, -1) |
parent = assign and
i = 0 and
child = childRef(cao.getLeftOperand())
or
parent = assign and
i = 1 and
child = SynthChild(getKind(cao))
or
parent = getSynthChild(assign, 1) and
(
i = 0 and
child = SynthChild(ConstantReadAccessKind(cao.getName()))
or
i = 1 and
child = childRef(cao.getRightOperand())
)
)
)
}
/**
* ```rb
* FOO += y
* ```
*
* desugars to
*
* ```rb
* FOO = FOO + y
* ```
*/
private class ConstantAssignOperationSynthesis extends Synthesis {
final override predicate child(AstNode parent, int i, Child child) {
constantAssignOperationSynthesis(parent, i, child)
}
final override predicate constantReadAccess(string name) {
name = any(ConstantAssignOperation o).getName()
}
final override predicate location(AstNode n, Location l) {
exists(ConstantAssignOperation cao, BinaryOperation bo |
bo = cao.getDesugared().(AssignExpr).getRightOperand()
|
n = bo and
l = getAssignOperationLocation(cao)
or
n = bo.getLeftOperand() and
hasLocation(cao.getLeftOperand(), l)
)
}
}
/**
* An assignment operation where the left-hand side is a constant
* with scope expression, such as `expr::FOO`.
*/
private class ScopeResolutionAssignOperation extends AssignOperation {
string name;
Expr scope;
pragma[nomagic]
ScopeResolutionAssignOperation() {
exists(Ruby::Constant constant, Ruby::ScopeResolution g |
TScopeResolutionConstantAccess(g, constant) = this.getLeftOperand() and
name = constant.getValue() and
toGenerated(scope) = g.getScope()
)
}
final string getName() { result = name }
final Expr getScopeExpr() { result = scope }
}
pragma[nomagic]
private predicate scopeResolutionAssignOperationSynthesis(AstNode parent, int i, Child child) {
exists(ScopeResolutionAssignOperation cao |
parent = cao and
i = -1 and
child = SynthChild(StmtSequenceKind())
or
exists(AstNode stmts | stmts = TStmtSequenceSynth(cao, -1) |
parent = stmts and
i = 0 and
child = SynthChild(AssignExprKind())
or
exists(AstNode assign | assign = TAssignExprSynth(stmts, 0) |
parent = assign and
i = 0 and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(cao, 0)))
or
parent = assign and
i = 1 and
child = childRef(cao.getScopeExpr())
)
or
parent = stmts and
i = 1 and
child = SynthChild(AssignExprKind())
or
exists(AstNode assign | assign = TAssignExprSynth(stmts, 1) |
parent = assign and
i = 0 and
child = SynthChild(ConstantWriteAccessKind(cao.getName()))
or
exists(AstNode cwa | cwa = TConstantWriteAccessSynth(assign, 0, cao.getName()) |
parent = cwa and
i = 0 and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(cao, 0)))
)
or
parent = assign and
i = 1 and
child = SynthChild(getKind(cao))
or
exists(AstNode op | op = getSynthChild(assign, 1) |
parent = op and
i = 0 and
child = SynthChild(ConstantReadAccessKind(cao.getName()))
or
exists(AstNode cra | cra = TConstantReadAccessSynth(op, 0, cao.getName()) |
parent = cra and
i = 0 and
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(cao, 0)))
)
or
parent = op and
i = 1 and
child = childRef(cao.getRightOperand())
)
)
)
)
}
/**
* ```rb
* expr::FOO += y
* ```
*
* desugars to
*
* ```rb
* __synth__0 = expr
* __synth__0::FOO = _synth__0::FOO + y
* ```
*/
private class ScopeResolutionAssignOperationSynthesis extends Synthesis {
final override predicate child(AstNode parent, int i, Child child) {
scopeResolutionAssignOperationSynthesis(parent, i, child)
}
final override predicate constantReadAccess(string name) {
name = any(ScopeResolutionAssignOperation o).getName()
}
final override predicate localVariable(AstNode n, int i) {
n instanceof ScopeResolutionAssignOperation and
i = 0
}
final override predicate constantWriteAccess(string name) { this.constantReadAccess(name) }
final override predicate location(AstNode n, Location l) {
exists(ScopeResolutionAssignOperation cao, StmtSequence stmts | stmts = cao.getDesugared() |
n = stmts.getStmt(0) and
hasLocation(cao.getScopeExpr(), l)
or
exists(AssignExpr assign | assign = stmts.getStmt(1) |
n = assign and hasLocation(cao, l)
or
n = assign.getLeftOperand() and
hasLocation(cao.getLeftOperand(), l)
or
n = assign.getLeftOperand().(ConstantAccess).getScopeExpr() and
hasLocation(cao.getScopeExpr(), l)
or
exists(BinaryOperation bo | bo = assign.getRightOperand() |
n = bo and
l = getAssignOperationLocation(cao)
or
n = bo.getLeftOperand() and
hasLocation(cao.getLeftOperand(), l)
or
n = bo.getLeftOperand().(ConstantAccess).getScopeExpr() and
hasLocation(cao.getScopeExpr(), l)
)
)
)
}
}
/** An assignment operation where the left-hand side is a method call. */
private class SetterAssignOperation extends AssignOperation {
private MethodCall mc;

View File

@@ -890,7 +890,12 @@ module Trees {
private class ConstantAccessTree extends PostOrderTree, ConstantAccess {
ConstantAccessTree() {
not this instanceof ClassDeclaration and
not this instanceof ModuleDeclaration
not this instanceof ModuleDeclaration and
// constant accesses with scope expression in compound assignments are desugared
not (
this = any(AssignOperation op).getLeftOperand() and
exists(this.getScopeExpr())
)
}
final override predicate propagatesAbnormal(AstNode child) { child = this.getScopeExpr() }

View File

@@ -2833,6 +2833,29 @@ operations/operations.rb:
# 96| getStmt: [AssignMulExpr] ... *= ...
# 96| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var
# 96| getAnOperand/getRightOperand: [IntegerLiteral] 6
# 98| getStmt: [AssignExpr] ... = ...
# 98| getAnOperand/getLeftOperand: [ConstantAssignment] CONSTANT1
# 98| getAnOperand/getRightOperand: [IntegerLiteral] 5
# 99| getStmt: [AssignAddExpr] ... += ...
# 99| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT2
# 99| getAnOperand/getRightOperand: [IntegerLiteral] 6
# 100| getStmt: [AssignLogicalOrExpr] ... ||= ...
# 100| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT3
# 100| getAnOperand/getRightOperand: [IntegerLiteral] 7
# 101| getStmt: [AssignLogicalOrExpr] ... ||= ...
# 101| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] MemberConstant
# 101| getScopeExpr: [ConstantReadAccess] Foo
# 101| getAnOperand/getRightOperand: [IntegerLiteral] 8
# 102| getStmt: [AssignLogicalOrExpr] ... ||= ...
# 102| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] OtherConstant
# 102| getScopeExpr: [MethodCall] call to bar
# 102| getReceiver: [MethodCall] call to foo
# 102| getReceiver: [SelfVariableAccess] self
# 102| getArgument: [IntegerLiteral] 1
# 102| getAnOperand/getRightOperand: [IntegerLiteral] 7
# 103| getStmt: [AssignLogicalOrExpr] ... ||= ...
# 103| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT4
# 103| getAnOperand/getRightOperand: [IntegerLiteral] 7
params/params.rb:
# 1| [Toplevel] params.rb
# 4| getStmt: [Method] identifier_method_params

View File

@@ -865,6 +865,51 @@ operations/operations.rb:
# 96| getAnOperand/getRightOperand: [MulExpr] ... * ...
# 96| getAnOperand/getLeftOperand/getReceiver: [GlobalVariableAccess] $global_var
# 96| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 6
# 99| [AssignAddExpr] ... += ...
# 99| getDesugared: [AssignExpr] ... = ...
# 99| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT2
# 99| getAnOperand/getRightOperand: [AddExpr] ... + ...
# 99| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] CONSTANT2
# 99| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 6
# 100| [AssignLogicalOrExpr] ... ||= ...
# 100| getDesugared: [AssignExpr] ... = ...
# 100| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT3
# 100| getAnOperand/getRightOperand: [LogicalOrExpr] ... || ...
# 100| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] CONSTANT3
# 100| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 7
# 101| [AssignLogicalOrExpr] ... ||= ...
# 101| getDesugared: [StmtSequence] ...
# 101| getStmt: [AssignExpr] ... = ...
# 101| getAnOperand/getRightOperand: [ConstantReadAccess] Foo
# 101| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 101| getStmt: [AssignExpr] ... = ...
# 101| getAnOperand/getLeftOperand: [ConstantAssignment] MemberConstant
# 101| getScopeExpr: [LocalVariableAccess] __synth__0
# 101| getAnOperand/getRightOperand: [LogicalOrExpr] ... || ...
# 101| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] MemberConstant
# 101| getScopeExpr: [LocalVariableAccess] __synth__0
# 101| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 8
# 102| [AssignLogicalOrExpr] ... ||= ...
# 102| getDesugared: [StmtSequence] ...
# 102| getStmt: [AssignExpr] ... = ...
# 102| getAnOperand/getRightOperand: [MethodCall] call to bar
# 102| getReceiver: [MethodCall] call to foo
# 102| getReceiver: [SelfVariableAccess] self
# 102| getArgument: [IntegerLiteral] 1
# 102| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0
# 102| getStmt: [AssignExpr] ... = ...
# 102| getAnOperand/getLeftOperand: [ConstantAssignment] OtherConstant
# 102| getScopeExpr: [LocalVariableAccess] __synth__0
# 102| getAnOperand/getRightOperand: [LogicalOrExpr] ... || ...
# 102| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] OtherConstant
# 102| getScopeExpr: [LocalVariableAccess] __synth__0
# 102| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 7
# 103| [AssignLogicalOrExpr] ... ||= ...
# 103| getDesugared: [AssignExpr] ... = ...
# 103| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT4
# 103| getAnOperand/getRightOperand: [LogicalOrExpr] ... || ...
# 103| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] CONSTANT4
# 103| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 7
params/params.rb:
# 8| [HashLiteral] {...}
# 8| getDesugared: [MethodCall] call to []

View File

@@ -5537,6 +5537,46 @@ operations/operations.rb:
# 96| 0: [GlobalVariable] $global_var
# 96| 1: [ReservedWord] *=
# 96| 2: [Integer] 6
# 98| 66: [Assignment] Assignment
# 98| 0: [Constant] CONSTANT1
# 98| 1: [ReservedWord] =
# 98| 2: [Integer] 5
# 99| 67: [OperatorAssignment] OperatorAssignment
# 99| 0: [Constant] CONSTANT2
# 99| 1: [ReservedWord] +=
# 99| 2: [Integer] 6
# 100| 68: [OperatorAssignment] OperatorAssignment
# 100| 0: [Constant] CONSTANT3
# 100| 1: [ReservedWord] ||=
# 100| 2: [Integer] 7
# 101| 69: [OperatorAssignment] OperatorAssignment
# 101| 0: [ScopeResolution] ScopeResolution
# 101| 0: [Constant] Foo
# 101| 1: [ReservedWord] ::
# 101| 2: [Constant] MemberConstant
# 101| 1: [ReservedWord] ||=
# 101| 2: [Integer] 8
# 102| 70: [OperatorAssignment] OperatorAssignment
# 102| 0: [ScopeResolution] ScopeResolution
# 102| 0: [Call] Call
# 102| 0: [Call] Call
# 102| 0: [Identifier] foo
# 102| 1: [ArgumentList] ArgumentList
# 102| 0: [ReservedWord] (
# 102| 1: [Integer] 1
# 102| 2: [ReservedWord] )
# 102| 1: [ReservedWord] .
# 102| 2: [Identifier] bar
# 102| 1: [ReservedWord] ::
# 102| 2: [Constant] OtherConstant
# 102| 1: [ReservedWord] ||=
# 102| 2: [Integer] 7
# 103| 71: [OperatorAssignment] OperatorAssignment
# 103| 0: [ScopeResolution] ScopeResolution
# 103| 0: [ReservedWord] ::
# 103| 1: [Constant] CONSTANT4
# 103| 1: [ReservedWord] ||=
# 103| 2: [Integer] 7
# 1| [Comment] # Start with assignments to all the identifiers used below, so that they are
# 2| [Comment] # interpreted as variables.
# 22| [Comment] # Unary operations

View File

@@ -888,6 +888,13 @@ exprValue
| operations/operations.rb:92:10:92:10 | 4 | 4 | int |
| operations/operations.rb:95:15:95:15 | 5 | 5 | int |
| operations/operations.rb:96:16:96:16 | 6 | 6 | int |
| operations/operations.rb:98:13:98:13 | 5 | 5 | int |
| operations/operations.rb:99:14:99:14 | 6 | 6 | int |
| operations/operations.rb:100:15:100:15 | 7 | 7 | int |
| operations/operations.rb:101:25:101:25 | 8 | 8 | int |
| operations/operations.rb:102:5:102:5 | 1 | 1 | int |
| operations/operations.rb:102:31:102:31 | 7 | 7 | int |
| operations/operations.rb:103:17:103:17 | 7 | 7 | int |
| params/params.rb:41:46:41:46 | 7 | 7 | int |
| params/params.rb:47:19:47:21 | :bar | :bar | symbol |
| params/params.rb:47:24:47:24 | 2 | 2 | int |
@@ -1764,6 +1771,13 @@ exprCfgNodeValue
| operations/operations.rb:92:10:92:10 | 4 | 4 | int |
| operations/operations.rb:95:15:95:15 | 5 | 5 | int |
| operations/operations.rb:96:16:96:16 | 6 | 6 | int |
| operations/operations.rb:98:13:98:13 | 5 | 5 | int |
| operations/operations.rb:99:14:99:14 | 6 | 6 | int |
| operations/operations.rb:100:15:100:15 | 7 | 7 | int |
| operations/operations.rb:101:25:101:25 | 8 | 8 | int |
| operations/operations.rb:102:5:102:5 | 1 | 1 | int |
| operations/operations.rb:102:31:102:31 | 7 | 7 | int |
| operations/operations.rb:103:17:103:17 | 7 | 7 | int |
| params/params.rb:41:46:41:46 | 7 | 7 | int |
| params/params.rb:47:19:47:21 | :bar | :bar | symbol |
| params/params.rb:47:24:47:24 | 2 | 2 | int |

View File

@@ -52,6 +52,19 @@ assignments
| operations.rb:95:1:95:15 | ... = ... | = | operations.rb:95:1:95:11 | $global_var | operations.rb:95:15:95:15 | 5 | AssignExpr |
| operations.rb:96:1:96:16 | ... *= ... | *= | operations.rb:96:1:96:11 | $global_var | operations.rb:96:16:96:16 | 6 | AssignMulExpr |
| operations.rb:96:1:96:16 | ... = ... | = | operations.rb:96:1:96:11 | $global_var | operations.rb:96:13:96:14 | ... * ... | AssignExpr |
| operations.rb:98:1:98:13 | ... = ... | = | operations.rb:98:1:98:9 | CONSTANT1 | operations.rb:98:13:98:13 | 5 | AssignExpr |
| operations.rb:99:1:99:14 | ... += ... | += | operations.rb:99:1:99:9 | CONSTANT2 | operations.rb:99:14:99:14 | 6 | AssignAddExpr |
| operations.rb:99:1:99:14 | ... = ... | = | operations.rb:99:1:99:9 | CONSTANT2 | operations.rb:99:11:99:12 | ... + ... | AssignExpr |
| operations.rb:100:1:100:15 | ... = ... | = | operations.rb:100:1:100:9 | CONSTANT3 | operations.rb:100:11:100:13 | ... \|\| ... | AssignExpr |
| operations.rb:100:1:100:15 | ... \|\|= ... | \|\|= | operations.rb:100:1:100:9 | CONSTANT3 | operations.rb:100:15:100:15 | 7 | AssignLogicalOrExpr |
| operations.rb:101:1:101:3 | ... = ... | = | operations.rb:101:1:101:3 | __synth__0 | operations.rb:101:1:101:3 | Foo | AssignExpr |
| operations.rb:101:1:101:25 | ... = ... | = | operations.rb:101:1:101:19 | MemberConstant | operations.rb:101:21:101:23 | ... \|\| ... | AssignExpr |
| operations.rb:101:1:101:25 | ... \|\|= ... | \|\|= | operations.rb:101:1:101:19 | MemberConstant | operations.rb:101:25:101:25 | 8 | AssignLogicalOrExpr |
| operations.rb:102:1:102:10 | ... = ... | = | operations.rb:102:1:102:10 | __synth__0 | operations.rb:102:1:102:10 | call to bar | AssignExpr |
| operations.rb:102:1:102:31 | ... = ... | = | operations.rb:102:1:102:25 | OtherConstant | operations.rb:102:27:102:29 | ... \|\| ... | AssignExpr |
| operations.rb:102:1:102:31 | ... \|\|= ... | \|\|= | operations.rb:102:1:102:25 | OtherConstant | operations.rb:102:31:102:31 | 7 | AssignLogicalOrExpr |
| operations.rb:103:1:103:17 | ... = ... | = | operations.rb:103:1:103:11 | CONSTANT4 | operations.rb:103:13:103:15 | ... \|\| ... | AssignExpr |
| operations.rb:103:1:103:17 | ... \|\|= ... | \|\|= | operations.rb:103:1:103:11 | CONSTANT4 | operations.rb:103:17:103:17 | 7 | AssignLogicalOrExpr |
assignOperations
| operations.rb:69:1:69:8 | ... += ... | += | operations.rb:69:1:69:1 | x | operations.rb:69:6:69:8 | 128 | AssignAddExpr |
| operations.rb:70:1:70:7 | ... -= ... | -= | operations.rb:70:1:70:1 | y | operations.rb:70:6:70:7 | 32 | AssignSubExpr |
@@ -69,6 +82,11 @@ assignOperations
| operations.rb:89:3:89:9 | ... += ... | += | operations.rb:89:3:89:4 | @x | operations.rb:89:9:89:9 | 2 | AssignAddExpr |
| operations.rb:92:3:92:10 | ... /= ... | /= | operations.rb:92:3:92:5 | @@y | operations.rb:92:10:92:10 | 4 | AssignDivExpr |
| operations.rb:96:1:96:16 | ... *= ... | *= | operations.rb:96:1:96:11 | $global_var | operations.rb:96:16:96:16 | 6 | AssignMulExpr |
| operations.rb:99:1:99:14 | ... += ... | += | operations.rb:99:1:99:9 | CONSTANT2 | operations.rb:99:14:99:14 | 6 | AssignAddExpr |
| operations.rb:100:1:100:15 | ... \|\|= ... | \|\|= | operations.rb:100:1:100:9 | CONSTANT3 | operations.rb:100:15:100:15 | 7 | AssignLogicalOrExpr |
| operations.rb:101:1:101:25 | ... \|\|= ... | \|\|= | operations.rb:101:1:101:19 | MemberConstant | operations.rb:101:25:101:25 | 8 | AssignLogicalOrExpr |
| operations.rb:102:1:102:31 | ... \|\|= ... | \|\|= | operations.rb:102:1:102:25 | OtherConstant | operations.rb:102:31:102:31 | 7 | AssignLogicalOrExpr |
| operations.rb:103:1:103:17 | ... \|\|= ... | \|\|= | operations.rb:103:1:103:11 | CONSTANT4 | operations.rb:103:17:103:17 | 7 | AssignLogicalOrExpr |
assignArithmeticOperations
| operations.rb:69:1:69:8 | ... += ... | += | operations.rb:69:1:69:1 | x | operations.rb:69:6:69:8 | 128 | AssignAddExpr |
| operations.rb:70:1:70:7 | ... -= ... | -= | operations.rb:70:1:70:1 | y | operations.rb:70:6:70:7 | 32 | AssignSubExpr |
@@ -79,9 +97,14 @@ assignArithmeticOperations
| operations.rb:89:3:89:9 | ... += ... | += | operations.rb:89:3:89:4 | @x | operations.rb:89:9:89:9 | 2 | AssignAddExpr |
| operations.rb:92:3:92:10 | ... /= ... | /= | operations.rb:92:3:92:5 | @@y | operations.rb:92:10:92:10 | 4 | AssignDivExpr |
| operations.rb:96:1:96:16 | ... *= ... | *= | operations.rb:96:1:96:11 | $global_var | operations.rb:96:16:96:16 | 6 | AssignMulExpr |
| operations.rb:99:1:99:14 | ... += ... | += | operations.rb:99:1:99:9 | CONSTANT2 | operations.rb:99:14:99:14 | 6 | AssignAddExpr |
assignLogicalOperations
| operations.rb:77:2:77:8 | ... &&= ... | &&= | operations.rb:77:2:77:2 | x | operations.rb:77:8:77:8 | y | AssignLogicalAndExpr |
| operations.rb:78:2:78:8 | ... \|\|= ... | \|\|= | operations.rb:78:2:78:2 | a | operations.rb:78:8:78:8 | b | AssignLogicalOrExpr |
| operations.rb:100:1:100:15 | ... \|\|= ... | \|\|= | operations.rb:100:1:100:9 | CONSTANT3 | operations.rb:100:15:100:15 | 7 | AssignLogicalOrExpr |
| operations.rb:101:1:101:25 | ... \|\|= ... | \|\|= | operations.rb:101:1:101:19 | MemberConstant | operations.rb:101:25:101:25 | 8 | AssignLogicalOrExpr |
| operations.rb:102:1:102:31 | ... \|\|= ... | \|\|= | operations.rb:102:1:102:25 | OtherConstant | operations.rb:102:31:102:31 | 7 | AssignLogicalOrExpr |
| operations.rb:103:1:103:17 | ... \|\|= ... | \|\|= | operations.rb:103:1:103:11 | CONSTANT4 | operations.rb:103:17:103:17 | 7 | AssignLogicalOrExpr |
assignBitwiseOperations
| operations.rb:81:2:81:8 | ... <<= ... | <<= | operations.rb:81:2:81:2 | x | operations.rb:81:8:81:8 | 2 | AssignLShiftExpr |
| operations.rb:82:2:82:8 | ... >>= ... | >>= | operations.rb:82:2:82:2 | y | operations.rb:82:8:82:8 | 3 | AssignRShiftExpr |

View File

@@ -40,6 +40,11 @@ binaryOperations
| operations.rb:89:6:89:7 | ... + ... | + | operations.rb:89:3:89:4 | @x | operations.rb:89:9:89:9 | 2 | AddExpr |
| operations.rb:92:7:92:8 | ... / ... | / | operations.rb:92:3:92:5 | @@y | operations.rb:92:10:92:10 | 4 | DivExpr |
| operations.rb:96:13:96:14 | ... * ... | * | operations.rb:96:1:96:11 | $global_var | operations.rb:96:16:96:16 | 6 | MulExpr |
| operations.rb:99:11:99:12 | ... + ... | + | operations.rb:99:1:99:9 | CONSTANT2 | operations.rb:99:14:99:14 | 6 | AddExpr |
| operations.rb:100:11:100:13 | ... \|\| ... | \|\| | operations.rb:100:1:100:9 | CONSTANT3 | operations.rb:100:15:100:15 | 7 | LogicalOrExpr |
| operations.rb:101:21:101:23 | ... \|\| ... | \|\| | operations.rb:101:1:101:19 | MemberConstant | operations.rb:101:25:101:25 | 8 | LogicalOrExpr |
| operations.rb:102:27:102:29 | ... \|\| ... | \|\| | operations.rb:102:1:102:25 | OtherConstant | operations.rb:102:31:102:31 | 7 | LogicalOrExpr |
| operations.rb:103:13:103:15 | ... \|\| ... | \|\| | operations.rb:103:1:103:11 | CONSTANT4 | operations.rb:103:17:103:17 | 7 | LogicalOrExpr |
binaryArithmeticOperations
| operations.rb:32:1:32:7 | ... + ... | + | operations.rb:32:1:32:1 | w | operations.rb:32:5:32:7 | 234 | AddExpr |
| operations.rb:33:1:33:6 | ... - ... | - | operations.rb:33:1:33:1 | x | operations.rb:33:5:33:6 | 17 | SubExpr |
@@ -56,6 +61,7 @@ binaryArithmeticOperations
| operations.rb:89:6:89:7 | ... + ... | + | operations.rb:89:3:89:4 | @x | operations.rb:89:9:89:9 | 2 | AddExpr |
| operations.rb:92:7:92:8 | ... / ... | / | operations.rb:92:3:92:5 | @@y | operations.rb:92:10:92:10 | 4 | DivExpr |
| operations.rb:96:13:96:14 | ... * ... | * | operations.rb:96:1:96:11 | $global_var | operations.rb:96:16:96:16 | 6 | MulExpr |
| operations.rb:99:11:99:12 | ... + ... | + | operations.rb:99:1:99:9 | CONSTANT2 | operations.rb:99:14:99:14 | 6 | AddExpr |
binaryLogicalOperations
| operations.rb:40:1:40:10 | ... && ... | && | operations.rb:40:1:40:3 | foo | operations.rb:40:8:40:10 | bar | LogicalAndExpr |
| operations.rb:41:1:41:11 | ... and ... | and | operations.rb:41:1:41:3 | baz | operations.rb:41:9:41:11 | qux | LogicalAndExpr |
@@ -63,6 +69,10 @@ binaryLogicalOperations
| operations.rb:43:1:43:6 | ... \|\| ... | \|\| | operations.rb:43:1:43:1 | x | operations.rb:43:6:43:6 | y | LogicalOrExpr |
| operations.rb:77:4:77:6 | ... && ... | && | operations.rb:77:2:77:2 | x | operations.rb:77:8:77:8 | y | LogicalAndExpr |
| operations.rb:78:4:78:6 | ... \|\| ... | \|\| | operations.rb:78:2:78:2 | a | operations.rb:78:8:78:8 | b | LogicalOrExpr |
| operations.rb:100:11:100:13 | ... \|\| ... | \|\| | operations.rb:100:1:100:9 | CONSTANT3 | operations.rb:100:15:100:15 | 7 | LogicalOrExpr |
| operations.rb:101:21:101:23 | ... \|\| ... | \|\| | operations.rb:101:1:101:19 | MemberConstant | operations.rb:101:25:101:25 | 8 | LogicalOrExpr |
| operations.rb:102:27:102:29 | ... \|\| ... | \|\| | operations.rb:102:1:102:25 | OtherConstant | operations.rb:102:31:102:31 | 7 | LogicalOrExpr |
| operations.rb:103:13:103:15 | ... \|\| ... | \|\| | operations.rb:103:1:103:11 | CONSTANT4 | operations.rb:103:17:103:17 | 7 | LogicalOrExpr |
binaryBitwiseOperations
| operations.rb:46:1:46:6 | ... << ... | << | operations.rb:46:1:46:1 | x | operations.rb:46:6:46:6 | 3 | LShiftExpr |
| operations.rb:47:1:47:7 | ... >> ... | >> | operations.rb:47:1:47:1 | y | operations.rb:47:6:47:7 | 16 | RShiftExpr |

View File

@@ -194,3 +194,39 @@
| operations.rb:96:1:96:16 | ... = ... | = | operations.rb:96:13:96:14 | ... * ... | AssignExpr |
| operations.rb:96:13:96:14 | ... * ... | * | operations.rb:96:1:96:11 | $global_var | MulExpr |
| operations.rb:96:13:96:14 | ... * ... | * | operations.rb:96:16:96:16 | 6 | MulExpr |
| operations.rb:98:1:98:13 | ... = ... | = | operations.rb:98:1:98:9 | CONSTANT1 | AssignExpr |
| operations.rb:98:1:98:13 | ... = ... | = | operations.rb:98:13:98:13 | 5 | AssignExpr |
| operations.rb:99:1:99:14 | ... += ... | += | operations.rb:99:1:99:9 | CONSTANT2 | AssignAddExpr |
| operations.rb:99:1:99:14 | ... += ... | += | operations.rb:99:14:99:14 | 6 | AssignAddExpr |
| operations.rb:99:1:99:14 | ... = ... | = | operations.rb:99:1:99:9 | CONSTANT2 | AssignExpr |
| operations.rb:99:1:99:14 | ... = ... | = | operations.rb:99:11:99:12 | ... + ... | AssignExpr |
| operations.rb:99:11:99:12 | ... + ... | + | operations.rb:99:1:99:9 | CONSTANT2 | AddExpr |
| operations.rb:99:11:99:12 | ... + ... | + | operations.rb:99:14:99:14 | 6 | AddExpr |
| operations.rb:100:1:100:15 | ... = ... | = | operations.rb:100:1:100:9 | CONSTANT3 | AssignExpr |
| operations.rb:100:1:100:15 | ... = ... | = | operations.rb:100:11:100:13 | ... \|\| ... | AssignExpr |
| operations.rb:100:1:100:15 | ... \|\|= ... | \|\|= | operations.rb:100:1:100:9 | CONSTANT3 | AssignLogicalOrExpr |
| operations.rb:100:1:100:15 | ... \|\|= ... | \|\|= | operations.rb:100:15:100:15 | 7 | AssignLogicalOrExpr |
| operations.rb:100:11:100:13 | ... \|\| ... | \|\| | operations.rb:100:1:100:9 | CONSTANT3 | LogicalOrExpr |
| operations.rb:100:11:100:13 | ... \|\| ... | \|\| | operations.rb:100:15:100:15 | 7 | LogicalOrExpr |
| operations.rb:101:1:101:3 | ... = ... | = | operations.rb:101:1:101:3 | Foo | AssignExpr |
| operations.rb:101:1:101:3 | ... = ... | = | operations.rb:101:1:101:3 | __synth__0 | AssignExpr |
| operations.rb:101:1:101:25 | ... = ... | = | operations.rb:101:1:101:19 | MemberConstant | AssignExpr |
| operations.rb:101:1:101:25 | ... = ... | = | operations.rb:101:21:101:23 | ... \|\| ... | AssignExpr |
| operations.rb:101:1:101:25 | ... \|\|= ... | \|\|= | operations.rb:101:1:101:19 | MemberConstant | AssignLogicalOrExpr |
| operations.rb:101:1:101:25 | ... \|\|= ... | \|\|= | operations.rb:101:25:101:25 | 8 | AssignLogicalOrExpr |
| operations.rb:101:21:101:23 | ... \|\| ... | \|\| | operations.rb:101:1:101:19 | MemberConstant | LogicalOrExpr |
| operations.rb:101:21:101:23 | ... \|\| ... | \|\| | operations.rb:101:25:101:25 | 8 | LogicalOrExpr |
| operations.rb:102:1:102:10 | ... = ... | = | operations.rb:102:1:102:10 | __synth__0 | AssignExpr |
| operations.rb:102:1:102:10 | ... = ... | = | operations.rb:102:1:102:10 | call to bar | AssignExpr |
| operations.rb:102:1:102:31 | ... = ... | = | operations.rb:102:1:102:25 | OtherConstant | AssignExpr |
| operations.rb:102:1:102:31 | ... = ... | = | operations.rb:102:27:102:29 | ... \|\| ... | AssignExpr |
| operations.rb:102:1:102:31 | ... \|\|= ... | \|\|= | operations.rb:102:1:102:25 | OtherConstant | AssignLogicalOrExpr |
| operations.rb:102:1:102:31 | ... \|\|= ... | \|\|= | operations.rb:102:31:102:31 | 7 | AssignLogicalOrExpr |
| operations.rb:102:27:102:29 | ... \|\| ... | \|\| | operations.rb:102:1:102:25 | OtherConstant | LogicalOrExpr |
| operations.rb:102:27:102:29 | ... \|\| ... | \|\| | operations.rb:102:31:102:31 | 7 | LogicalOrExpr |
| operations.rb:103:1:103:17 | ... = ... | = | operations.rb:103:1:103:11 | CONSTANT4 | AssignExpr |
| operations.rb:103:1:103:17 | ... = ... | = | operations.rb:103:13:103:15 | ... \|\| ... | AssignExpr |
| operations.rb:103:1:103:17 | ... \|\|= ... | \|\|= | operations.rb:103:1:103:11 | CONSTANT4 | AssignLogicalOrExpr |
| operations.rb:103:1:103:17 | ... \|\|= ... | \|\|= | operations.rb:103:17:103:17 | 7 | AssignLogicalOrExpr |
| operations.rb:103:13:103:15 | ... \|\| ... | \|\| | operations.rb:103:1:103:11 | CONSTANT4 | LogicalOrExpr |
| operations.rb:103:13:103:15 | ... \|\| ... | \|\| | operations.rb:103:17:103:17 | 7 | LogicalOrExpr |

View File

@@ -94,3 +94,10 @@ end
$global_var = 5
$global_var *= 6
CONSTANT1 = 5
CONSTANT2 += 6
CONSTANT3 ||= 7
Foo::MemberConstant ||= 8
foo(1).bar::OtherConstant ||= 7
::CONSTANT4 ||= 7

View File

@@ -3762,6 +3762,81 @@ cfg.rb:
# 215| self
#-----| -> call to something_else
constant_compound_assign.rb:
# 1| Foo
#-----| -> foo_before
# 1| enter constant_compound_assign.rb
#-----| -> Foo
# 1| exit constant_compound_assign.rb
# 1| exit constant_compound_assign.rb (normal)
#-----| -> exit constant_compound_assign.rb
# 2| foo_before
#-----| -> FOO_CONSTANT
# 5| FOO_CONSTANT
#-----| -> FOO_CONSTANT
# 5| FOO_CONSTANT
#-----| true -> ... || ...
#-----| false -> 123
# 5| ... = ...
#-----| -> foo_after
# 5| ... || ...
#-----| -> ... = ...
# 5| 123
#-----| -> ... || ...
# 7| foo_after
#-----| -> top_before
# 11| top_before
#-----| -> TOP_CONSTANT
# 14| TOP_CONSTANT
#-----| -> TOP_CONSTANT
# 14| TOP_CONSTANT
#-----| true -> ... || ...
#-----| false -> 123
# 14| ... = ...
#-----| -> top_after
# 14| ... || ...
#-----| -> ... = ...
# 14| 123
#-----| -> ... || ...
# 16| top_after
#-----| -> TOP_CONSTANT2
# 19| TOP_CONSTANT2
#-----| -> TOP_CONSTANT2
# 19| TOP_CONSTANT2
#-----| true -> ... || ...
#-----| false -> 123
# 19| ... = ...
#-----| -> top_after2
# 19| ... || ...
#-----| -> ... = ...
# 19| 123
#-----| -> ... || ...
# 21| top_after2
#-----| -> exit constant_compound_assign.rb (normal)
desugar.rb:
# 1| enter m1
#-----| -> x

View File

@@ -212,6 +212,9 @@ positionalArguments
| cfg.rb:205:1:205:23 | call to bar | cfg.rb:205:10:205:10 | 1 |
| cfg.rb:205:1:205:23 | call to bar | cfg.rb:205:12:205:12 | 2 |
| cfg.rb:205:4:205:5 | call to == | cfg.rb:205:1:205:3 | __synth__0__1 |
| constant_compound_assign.rb:5:18:5:20 | ... \|\| ... | constant_compound_assign.rb:5:22:5:24 | 123 |
| constant_compound_assign.rb:14:14:14:16 | ... \|\| ... | constant_compound_assign.rb:14:18:14:20 | 123 |
| constant_compound_assign.rb:19:17:19:19 | ... \|\| ... | constant_compound_assign.rb:19:21:19:23 | 123 |
| desugar.rb:2:5:2:6 | ... + ... | desugar.rb:2:8:2:8 | 1 |
| desugar.rb:6:3:6:13 | call to count= | desugar.rb:6:17:6:17 | ... = ... |
| desugar.rb:10:3:10:10 | call to []= | desugar.rb:10:9:10:9 | 0 |

View File

@@ -0,0 +1,22 @@
module Foo
def foo_before
end
FOO_CONSTANT ||= 123
def foo_after
end
end
def top_before
end
TOP_CONSTANT ||= 123
def top_after
end
::TOP_CONSTANT2 ||= 123
def top_after2
end