rdg 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +2 -2
- data/Gemfile +1 -1
- data/RELEASES.md +10 -0
- data/TODO.md +68 -0
- data/bin/ast +5 -4
- data/bin/cfg +5 -4
- data/lib/rdg/analysis/analyser.rb +30 -0
- data/lib/rdg/analysis/composite.rb +23 -0
- data/lib/rdg/analysis/context.rb +17 -0
- data/lib/rdg/analysis/equivalences.rb +25 -0
- data/lib/rdg/analysis/propagater.rb +51 -0
- data/lib/rdg/analysis/registry.rb +35 -0
- data/lib/rdg/cfg.rb +12 -41
- data/lib/rdg/control/begin.rb +6 -4
- data/lib/rdg/control/break.rb +19 -0
- data/lib/rdg/control/case.rb +25 -0
- data/lib/rdg/control/{while.rb → conditional_loop.rb} +8 -7
- data/lib/rdg/control/def.rb +21 -7
- data/lib/rdg/control/ensure.rb +30 -0
- data/lib/rdg/control/for.rb +29 -0
- data/lib/rdg/control/handler.rb +25 -0
- data/lib/rdg/control/if.rb +7 -6
- data/lib/rdg/control/jump.rb +33 -0
- data/lib/rdg/control/jump_to_start.rb +11 -0
- data/lib/rdg/control/next.rb +9 -0
- data/lib/rdg/control/none.rb +5 -3
- data/lib/rdg/control/redo.rb +9 -0
- data/lib/rdg/control/rescue.rb +31 -0
- data/lib/rdg/control/rescue_body.rb +29 -0
- data/lib/rdg/control/retry.rb +13 -0
- data/lib/rdg/control/return.rb +5 -6
- data/lib/rdg/control/when.rb +27 -0
- data/lib/rdg/graph/bidirected_adjacency_graph.rb +19 -0
- data/lib/rdg/graph/rgl/allow_duplicates.rb +45 -0
- data/lib/rdg/tree/ast.rb +15 -4
- data/lib/rdg/version.rb +1 -1
- data/rdg.gemspec +3 -2
- data/spec/integration/cfg/conditionals/case_spec.rb +66 -0
- data/spec/integration/cfg/{if_spec.rb → conditionals/if_spec.rb} +24 -9
- data/spec/integration/cfg/conditionals/unless_spec.rb +53 -0
- data/spec/integration/cfg/exceptions_spec.rb +131 -0
- data/spec/integration/cfg/loops/loop_control_spec.rb +90 -0
- data/spec/integration/cfg/loops/loop_spec.rb +70 -0
- data/spec/integration/cfg/sequence_spec.rb +7 -1
- data/spec/support/doubles/fake_ast.rb +15 -0
- data/spec/support/matchers/flow_between_matcher.rb +1 -1
- data/spec/unit/analysis/composite_spec.rb +47 -0
- data/spec/unit/analysis/equivalences_spec.rb +29 -0
- data/spec/unit/{control/analyser_spec.rb → analysis/propagater_spec.rb} +23 -12
- data/spec/unit/analysis/registry_spec.rb +61 -0
- data/spec/unit/control/begin_spec.rb +3 -6
- data/spec/unit/control/break_spec.rb +26 -0
- data/spec/unit/control/case_spec.rb +66 -0
- data/spec/unit/control/conditional_loop_spec.rb +22 -0
- data/spec/unit/control/ensure_spec.rb +33 -0
- data/spec/unit/control/for_spec.rb +26 -0
- data/spec/unit/control/handler_spec.rb +27 -0
- data/spec/unit/control/if_spec.rb +26 -18
- data/spec/unit/control/jump_spec.rb +43 -0
- data/spec/unit/control/jump_to_start_spec.rb +22 -0
- data/spec/unit/control/rescue_body_spec.rb +26 -0
- data/spec/unit/control/rescue_spec.rb +62 -0
- data/spec/unit/control/return_spec.rb +1 -10
- data/spec/unit/control/when_spec.rb +59 -0
- data/spec/unit/graph/bidirected_adjacency_graph_spec.rb +49 -0
- metadata +91 -18
- data/lib/rdg/control/analyser.rb +0 -44
- data/spec/integration/cfg/methods_spec.rb +0 -39
- data/spec/unit/control/def_spec.rb +0 -28
- data/spec/unit/control/while_spec.rb +0 -25
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative "jump"
|
2
|
+
|
3
|
+
module RDG
|
4
|
+
module Control
|
5
|
+
class Break < Jump
|
6
|
+
register_analyser :break
|
7
|
+
|
8
|
+
def new_successors
|
9
|
+
graph
|
10
|
+
.each_successor(test)
|
11
|
+
.reject { |s| s.ancestors.include?(block) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def test
|
15
|
+
equivalences.first(block.children.first)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "rdg/analysis/propagater"
|
2
|
+
|
3
|
+
module RDG
|
4
|
+
module Control
|
5
|
+
class Case < Analysis::Propagater
|
6
|
+
register_analyser :case
|
7
|
+
|
8
|
+
def prepare
|
9
|
+
@expression, *@consequences = nodes
|
10
|
+
end
|
11
|
+
|
12
|
+
def internal_flow_edges
|
13
|
+
nodes.each_cons(2).to_a
|
14
|
+
end
|
15
|
+
|
16
|
+
def start_node
|
17
|
+
@expression
|
18
|
+
end
|
19
|
+
|
20
|
+
def end_nodes
|
21
|
+
@consequences
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,10 +1,11 @@
|
|
1
|
-
|
1
|
+
require "rdg/analysis/propagater"
|
2
2
|
|
3
3
|
module RDG
|
4
4
|
module Control
|
5
|
-
class
|
6
|
-
|
7
|
-
|
5
|
+
class ConditionalLoop < Analysis::Propagater
|
6
|
+
register_analyser :while, :until
|
7
|
+
|
8
|
+
def prepare
|
8
9
|
@predicate, @body = children
|
9
10
|
end
|
10
11
|
|
@@ -12,12 +13,12 @@ module RDG
|
|
12
13
|
[[@predicate, @body], [@body, @predicate]]
|
13
14
|
end
|
14
15
|
|
15
|
-
def
|
16
|
-
|
16
|
+
def start_node
|
17
|
+
@predicate
|
17
18
|
end
|
18
19
|
|
19
20
|
def end_nodes
|
20
|
-
[@
|
21
|
+
[@predicate]
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|
data/lib/rdg/control/def.rb
CHANGED
@@ -1,14 +1,28 @@
|
|
1
|
+
require "rdg/analysis/propagater"
|
2
|
+
|
1
3
|
module RDG
|
2
4
|
module Control
|
3
|
-
class Def
|
4
|
-
def
|
5
|
-
|
6
|
-
|
5
|
+
class Def < Analysis::Propagater
|
6
|
+
register_analyser :def
|
7
|
+
|
8
|
+
def prepare
|
9
|
+
_name, _args, @body = children
|
10
|
+
end
|
11
|
+
|
12
|
+
def internal_flow_edges
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
|
16
|
+
def start_node
|
17
|
+
@body
|
18
|
+
end
|
19
|
+
|
20
|
+
def end_nodes
|
21
|
+
[@body]
|
7
22
|
end
|
8
23
|
|
9
|
-
def
|
10
|
-
@
|
11
|
-
@graph.add_edge(@name, @body)
|
24
|
+
def nodes
|
25
|
+
[@body]
|
12
26
|
end
|
13
27
|
end
|
14
28
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "rdg/analysis/propagater"
|
2
|
+
|
3
|
+
module RDG
|
4
|
+
module Control
|
5
|
+
class Ensure < Analysis::Propagater
|
6
|
+
register_analyser :ensure
|
7
|
+
|
8
|
+
def prepare
|
9
|
+
@body, @finaliser = nodes
|
10
|
+
end
|
11
|
+
|
12
|
+
def analyse
|
13
|
+
super
|
14
|
+
registry.prepend_for(@finaliser, Handler)
|
15
|
+
end
|
16
|
+
|
17
|
+
def internal_flow_edges
|
18
|
+
[[@body, @finaliser]]
|
19
|
+
end
|
20
|
+
|
21
|
+
def start_node
|
22
|
+
@body
|
23
|
+
end
|
24
|
+
|
25
|
+
def end_nodes
|
26
|
+
[@finaliser]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "rdg/analysis/propagater"
|
2
|
+
|
3
|
+
module RDG
|
4
|
+
module Control
|
5
|
+
class For < Analysis::Propagater
|
6
|
+
register_analyser :for
|
7
|
+
|
8
|
+
def prepare
|
9
|
+
_, @iterable, @body = children
|
10
|
+
end
|
11
|
+
|
12
|
+
def internal_flow_edges
|
13
|
+
[[@iterable, @body], [@body, @iterable]]
|
14
|
+
end
|
15
|
+
|
16
|
+
def start_node
|
17
|
+
@iterable
|
18
|
+
end
|
19
|
+
|
20
|
+
def end_nodes
|
21
|
+
[@iterable]
|
22
|
+
end
|
23
|
+
|
24
|
+
def nodes
|
25
|
+
[@iterable, @body]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "rdg/analysis/analyser"
|
2
|
+
|
3
|
+
module RDG
|
4
|
+
module Control
|
5
|
+
class Handler < Analysis::Analyser
|
6
|
+
def analyse
|
7
|
+
add_an_edge_from_every_main_node_to_the_handler
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def add_an_edge_from_every_main_node_to_the_handler
|
13
|
+
main.each { |m| graph.add_edge(m, @ast_node) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def main
|
17
|
+
equivalences.all(block.children.first)
|
18
|
+
end
|
19
|
+
|
20
|
+
def block
|
21
|
+
@ast_node.parent
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/rdg/control/if.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
|
1
|
+
require "rdg/analysis/propagater"
|
2
2
|
|
3
3
|
module RDG
|
4
4
|
module Control
|
5
|
-
class If <
|
6
|
-
|
7
|
-
|
5
|
+
class If < Analysis::Propagater
|
6
|
+
register_analyser :if
|
7
|
+
|
8
|
+
def prepare
|
8
9
|
@predicate, *@consequences = children.reject(&:empty?)
|
9
10
|
end
|
10
11
|
|
@@ -12,8 +13,8 @@ module RDG
|
|
12
13
|
@consequences.map { |consequence| [@predicate, consequence] }
|
13
14
|
end
|
14
15
|
|
15
|
-
def
|
16
|
-
|
16
|
+
def start_node
|
17
|
+
@predicate
|
17
18
|
end
|
18
19
|
|
19
20
|
def end_nodes
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "rdg/analysis/analyser"
|
2
|
+
|
3
|
+
module RDG
|
4
|
+
module Control
|
5
|
+
class Jump < Analysis::Analyser
|
6
|
+
def analyse
|
7
|
+
return unless block
|
8
|
+
remove_all_successors
|
9
|
+
add_new_successors
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def block_types
|
15
|
+
%i(while until for)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def remove_all_successors
|
21
|
+
graph.each_successor(@ast_node) { |s| graph.remove_edge(@ast_node, s) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_new_successors
|
25
|
+
new_successors.each { |s| graph.add_edge(@ast_node, s) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def block
|
29
|
+
@ast_node.ancestors.detect { |a| block_types.include?(a.type) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/rdg/control/none.rb
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
require "rdg/analysis/propagater"
|
2
|
+
require_relative "handler"
|
3
|
+
|
4
|
+
module RDG
|
5
|
+
module Control
|
6
|
+
class Rescue < Analysis::Propagater
|
7
|
+
register_analyser :rescue
|
8
|
+
|
9
|
+
def prepare
|
10
|
+
@main, *@handlers, @alternative = children
|
11
|
+
end
|
12
|
+
|
13
|
+
def analyse
|
14
|
+
super
|
15
|
+
@handlers.each { |h| registry.prepend_for(h, Handler) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def internal_flow_edges
|
19
|
+
@alternative.empty? ? [] : [[@main, @alternative]]
|
20
|
+
end
|
21
|
+
|
22
|
+
def start_node
|
23
|
+
@main
|
24
|
+
end
|
25
|
+
|
26
|
+
def end_nodes
|
27
|
+
@alternative.empty? ? nodes : @handlers.push(@alternative)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "rdg/analysis/propagater"
|
2
|
+
|
3
|
+
module RDG
|
4
|
+
module Control
|
5
|
+
class RescueBody < Analysis::Propagater
|
6
|
+
register_analyser :resbody
|
7
|
+
|
8
|
+
def prepare
|
9
|
+
_exception_types, _variable_name, *@statements = children
|
10
|
+
end
|
11
|
+
|
12
|
+
def internal_flow_edges
|
13
|
+
@statements.each_cons(2).to_a
|
14
|
+
end
|
15
|
+
|
16
|
+
def start_node
|
17
|
+
@statements.first
|
18
|
+
end
|
19
|
+
|
20
|
+
def end_nodes
|
21
|
+
@statements.last(1)
|
22
|
+
end
|
23
|
+
|
24
|
+
def nodes
|
25
|
+
@statements
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/rdg/control/return.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
|
+
require "rdg/analysis/analyser"
|
2
|
+
|
1
3
|
module RDG
|
2
4
|
module Control
|
3
|
-
class Return
|
4
|
-
|
5
|
-
@graph, @ast_node, @state = graph, ast_node, state
|
6
|
-
end
|
5
|
+
class Return < Analysis::Analyser
|
6
|
+
register_analyser :return
|
7
7
|
|
8
8
|
def analyse
|
9
|
-
|
10
|
-
@graph.each_successor(@ast_node) { |s| @graph.remove_edge(@ast_node, s) }
|
9
|
+
graph.each_successor(@ast_node) { |s| graph.remove_edge(@ast_node, s) }
|
11
10
|
end
|
12
11
|
end
|
13
12
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "rdg/analysis/propagater"
|
2
|
+
|
3
|
+
module RDG
|
4
|
+
module Control
|
5
|
+
class When < Analysis::Propagater
|
6
|
+
register_analyser :when
|
7
|
+
|
8
|
+
def prepare
|
9
|
+
@test, @action = children
|
10
|
+
end
|
11
|
+
|
12
|
+
def internal_flow_edges
|
13
|
+
[[@test, @action]]
|
14
|
+
end
|
15
|
+
|
16
|
+
def start_node
|
17
|
+
@test
|
18
|
+
end
|
19
|
+
|
20
|
+
def propogate_outgoing_flow
|
21
|
+
successors = graph.each_successor(@ast_node).to_a
|
22
|
+
graph.add_edge(@test, successors.first)
|
23
|
+
graph.add_edge(@action, successors.last)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "rgl/adjacency"
|
2
|
+
require "rgl/dot"
|
3
|
+
require_relative "rgl/allow_duplicates"
|
4
|
+
|
5
|
+
module RDG
|
6
|
+
module Graph
|
7
|
+
class BidirectedAdjacencyGraph < ::RGL::DirectedAdjacencyGraph
|
8
|
+
include RGL::AllowDuplicates
|
9
|
+
|
10
|
+
def each_predecessor(vertex, &block)
|
11
|
+
each_vertex.select { |v| each_adjacent(v).include?(vertex) }.each(&block)
|
12
|
+
end
|
13
|
+
|
14
|
+
def each_successor(vertex, &block)
|
15
|
+
each_adjacent(vertex, &block) if has_vertex?(vertex)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|