jruby_visualizer 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ class Java::org::jruby::ir::IRScope
2
+ ##
3
+ # Return a key for storage into the ScopeRegistry.
4
+ def key
5
+ "#{get_name}[#{get_file_name}:#{get_line_number}]".to_sym
6
+ end
7
+
8
+ ##
9
+ # return the CFG and if it is not created yet construct it as
10
+ # a side-effect
11
+ def cfg!
12
+ buildCFG unless get_cfg
13
+ get_cfg
14
+ end
15
+ end
@@ -0,0 +1,57 @@
1
+ =begin
2
+ JRuby Visualizer
3
+ Copyright (C) 2013 The JRuby Team
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ =end
17
+
18
+ #
19
+ # Retrieve a nicely formatted string from JRuby's IRScope
20
+ #
21
+ module IRPrettyPrinter
22
+
23
+ def self.pretty_ir(scope, indent='')
24
+ instrs = if scope.cfg
25
+ # read instrs from control flow graph
26
+ scope.cfg.sorted_basic_blocks.reduce([]) do |cfg_instrs, bb|
27
+ cfg_instrs += bb.instrs
28
+ end
29
+ else
30
+ # if no pass has been executed get them directly without cfg
31
+ scope.instrs
32
+ end
33
+ pretty_str = instrs.map do |instr|
34
+ f_str = "%s\s\s%s" % [indent, instr]
35
+ f_str
36
+ end
37
+ pretty_str = [indent + scope.to_s] + pretty_str
38
+ scope.lexical_scopes.each do |lex_scope|
39
+ pretty_str += pretty_ir(lex_scope, indent + "\s" * 4)
40
+ end
41
+ pretty_str
42
+ end
43
+
44
+ def self.print_ir(scope)
45
+ instrs = pretty_ir(scope)
46
+ instrs.each do |instr|
47
+ puts instr
48
+ end
49
+ end
50
+
51
+ def self.pretty_string(scope)
52
+ instrs = pretty_ir(scope)
53
+ instrs.join("\n")
54
+ end
55
+
56
+ end
57
+
@@ -0,0 +1,41 @@
1
+ =begin
2
+ JRuby Visualizer
3
+ Copyright (C) 2013 The JRuby Team
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ =end
17
+
18
+ require_relative 'core_ext/ir_scope'
19
+
20
+ #
21
+ # Registry for IRScopes, to access them by key without nesting of scopes
22
+ #
23
+ class IRScopeRegistry
24
+
25
+ attr_reader :scopes
26
+
27
+ def initialize(root_scope)
28
+ @scopes = {}
29
+ fill_registry(root_scope)
30
+ end
31
+
32
+ def fill_registry(ir_scope)
33
+ @scopes[ir_scope.key] = ir_scope
34
+ ir_scope.lexical_scopes.each { |lex_scope| fill_registry(lex_scope) }
35
+ end
36
+
37
+ def clear
38
+ @scopes = {}
39
+ end
40
+
41
+ end
@@ -0,0 +1,79 @@
1
+ =begin
2
+ JRuby Visualizer
3
+ Copyright (C) 2013 The JRuby Team
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ =end
17
+
18
+ require 'jrubyfx'
19
+ require 'diffy'
20
+ require_relative 'ir_pretty_printer'
21
+ require_relative 'jruby_visualizer'
22
+
23
+ resource_root :images, File.join(File.dirname(__FILE__), 'ui', 'img'), 'ui/img'
24
+ fxml_root File.join(File.dirname(__FILE__), 'ui')
25
+
26
+ #
27
+ # Visualizer for JRuby's Intermediate Representation (IR)
28
+ # displaying all IR Scopes with its lexical nesting
29
+ # and
30
+ # diffs on the IR, if it has changed (after executing a compiler pass)
31
+ #
32
+ class IRVisualizer < JRubyFX::Application
33
+
34
+ def start(stage)
35
+ compiler_data = JRubyVisualizer.compiler_data
36
+ with(stage, title: 'Intermediate Representation (IR) Visualizer') do
37
+ fxml(IRVisualizerController, initialize: [compiler_data])
38
+ icons.add(Image.new(resource_url(:images, 'jruby-icon-32.png').to_s))
39
+ show
40
+ end
41
+ end
42
+ end
43
+
44
+ #
45
+ # The controller loads the UI file and takes care of the diffs and
46
+ # updating the UI
47
+ #
48
+ class IRVisualizerController
49
+ include JRubyFX::Controller
50
+ fxml 'ir-view.fxml'
51
+
52
+ attr_reader :compiler_data
53
+
54
+ def initialize(compiler_data)
55
+ @compiler_data = compiler_data
56
+ pretty_ir_string = IRPrettyPrinter.pretty_string(@compiler_data.ir_scope)
57
+ @ir_view.text = @new_ir_string = @previous_ir_string = pretty_ir_string
58
+
59
+ @compiler_data.ir_scope_property.add_invalidation_listener do |new_scope_property|
60
+ @previous_ir_string = @new_ir_string
61
+ @new_ir_string = IRPrettyPrinter.pretty_string(new_scope_property.get)
62
+ diff_string = Diffy::Diff.new(@previous_ir_string, @new_ir_string).to_s
63
+ @ir_view.text =
64
+ if diff_string.empty?
65
+ @new_ir_string
66
+ else
67
+ diff_string
68
+ end
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ if __FILE__ == $PROGRAM_NAME
75
+ JRubyVisualizer.compiler_data = CompilerData.new(
76
+ "a = 1 + 4 + 7;\nc = nil;\nj = 1;\ni = 3 + j;\nputs i")
77
+ IRVisualizer.launch
78
+ end
79
+
@@ -0,0 +1,103 @@
1
+ =begin
2
+ JRuby Visualizer
3
+ Copyright (C) 2013 The JRuby Team
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ =end
17
+
18
+ require 'java'
19
+ require 'jruby'
20
+ require_relative 'visualizer_compiler_pass_listener'
21
+ require_relative 'visualizer_main_app'
22
+
23
+ #
24
+ # The Visualizer module enables to launch the visualizer components via
25
+ # an API call or ARGV
26
+ #
27
+ module JRubyVisualizer
28
+ @@main_app = nil
29
+ @@compiler_data = nil
30
+
31
+ def self.compiler_data
32
+ @@compiler_data
33
+ end
34
+
35
+ def self.compiler_data=(new_data)
36
+ @@compiler_data = new_data
37
+ end
38
+
39
+ def self.launched?
40
+ !!@@main_app
41
+ end
42
+
43
+ def self.launch
44
+ if launched?
45
+ return
46
+ end
47
+ unless @@compiler_data
48
+ raise 'Cannot launch Visualizer without a ComiplerData object'
49
+ end
50
+ VisualizerMainApp.launch
51
+ @@main_app = VisualizerMainApp
52
+ end
53
+
54
+ def self.inject_pass_listener
55
+ # create and add listener
56
+ vis_pass_listener = VisualizerCompilerPassListener.new
57
+ ir_manager = JRuby::runtime.ir_manager
58
+ ir_manager.add_listener(vis_pass_listener)
59
+
60
+ # activate visualization listener
61
+ JRuby::IR.visualize = true
62
+ end
63
+
64
+ def self.pass_listener?
65
+ JRuby::IR.visualize
66
+ end
67
+
68
+ def self.visualize(ruby_code)
69
+ unless pass_listener?
70
+ inject_pass_listener
71
+ end
72
+ @@compiler_data = CompilerData.new(ruby_code)
73
+ # launch App with Ruby code as input
74
+ launch
75
+ end
76
+
77
+ def self.visualize_with_argv
78
+ unless ARGV.length == 1
79
+ usage_message =
80
+ %#No ruby input for the JRuby Visualizer
81
+ Usage:
82
+ ./lib/jruby_visualizer.rb "def foo; 42; end; foo"
83
+ or
84
+ ./lib/jruby_visualizer.rb foo.rb#
85
+ raise usage_message
86
+ end
87
+ ruby_input = ARGV[0]
88
+ ruby_code =
89
+ if ruby_input.end_with?('.rb')
90
+ File.read(ruby_input)
91
+ else
92
+ ruby_input
93
+ end
94
+ visualize(ruby_code)
95
+ end
96
+
97
+ end
98
+
99
+ if __FILE__ == $PROGRAM_NAME
100
+ vis = JRubyVisualizer
101
+ vis.visualize('def foo; 42; end; foo')
102
+ end
103
+
@@ -0,0 +1,35 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+
3
+ <?import java.lang.*?>
4
+ <?import java.util.*?>
5
+ <?import javafx.scene.control.*?>
6
+ <?import javafx.scene.image.*?>
7
+ <?import javafx.scene.layout.*?>
8
+ <?import javafx.scene.paint.*?>
9
+ <?import javafx.scene.text.*?>
10
+
11
+ <VBox alignment="CENTER" prefHeight="300.0" prefWidth="500.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
12
+ <children>
13
+ <HBox alignment="CENTER" prefHeight="-1.0" prefWidth="-1.0">
14
+ <children>
15
+ <Label text="JRuby:" />
16
+ <Hyperlink fx:id="jruby_hyperlink" text="www.jruby.org">
17
+ <font>
18
+ <Font name="Monospaced Regular" size="13.0" />
19
+ </font>
20
+ </Hyperlink>
21
+ </children>
22
+ </HBox>
23
+ <ImageView fx:id="jruby_logo" fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true">
24
+ <image>
25
+ <Image url="@img/jruby-logo.png" />
26
+ </image>
27
+ </ImageView>
28
+ <Hyperlink fx:id="visualizer_hyperlink" text="The JRuby Visualizer">
29
+ <font>
30
+ <Font name="System Bold" size="20.0" />
31
+ </font>
32
+ </Hyperlink>
33
+ <TextArea editable="false" prefWidth="200.0" text="visualizes JRuby's Compiler and Interpreter artifacts:&#10;- the Abstract Syntax Tree (AST)&#10;- the Intermediate Representation (IR)&#10;- the execution of compiler passes on IR&#10;- a visualization for the Control Flow Graphs (CFGs) on JRuby Scopes" wrapText="true" />
34
+ </children>
35
+ </VBox>
@@ -0,0 +1,42 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+
3
+ <?import java.lang.*?>
4
+ <?import java.util.*?>
5
+ <?import javafx.collections.*?>
6
+ <?import javafx.geometry.*?>
7
+ <?import javafx.scene.control.*?>
8
+ <?import javafx.scene.image.*?>
9
+ <?import javafx.scene.layout.*?>
10
+ <?import javafx.scene.paint.*?>
11
+
12
+ <BorderPane prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
13
+ <center>
14
+ <TabPane id="ir_scopes" fx:id="cfg_scopes_view" prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE" />
15
+ </center>
16
+ <padding>
17
+ <Insets />
18
+ </padding>
19
+ <top>
20
+ <HBox prefHeight="25.0" prefWidth="600.0" spacing="5.0" BorderPane.alignment="CENTER">
21
+ <children>
22
+ <Label text="Scope">
23
+ <HBox.margin>
24
+ <Insets bottom="5.0" left="5.0" top="8.0" />
25
+ </HBox.margin>
26
+ </Label>
27
+ <ComboBox fx:id="ir_scope_selector" onAction="#select_scope" prefWidth="201.0">
28
+ <items>
29
+ <FXCollections fx:factory="observableArrayList">
30
+ <String fx:value="Item 1" />
31
+ <String fx:value="Item 2" />
32
+ <String fx:value="Item 3" />
33
+ </FXCollections>
34
+ </items>
35
+ <HBox.margin>
36
+ <Insets bottom="5.0" right="5.0" top="5.0" />
37
+ </HBox.margin>
38
+ </ComboBox>
39
+ </children>
40
+ </HBox>
41
+ </top>
42
+ </BorderPane>
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+
3
+ <?import java.lang.*?>
4
+ <?import java.util.*?>
5
+ <?import javafx.scene.control.*?>
6
+ <?import javafx.scene.layout.*?>
7
+ <?import javafx.scene.paint.*?>
8
+
9
+ <BorderPane prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
10
+ <center>
11
+ <VBox prefHeight="-1.0" prefWidth="-1.0">
12
+ <children>
13
+ <Label text="IR Code:" />
14
+ <TextArea id="ir" fx:id="ir_view" editable="false" minHeight="-1.0" prefWidth="-1.0" style="-fx-font-family: monospaced" text="Script: file: -ScriptBody -[-:0]&#10; 0 %self = recv_self&#10; 1 %current_scope = scope&lt;-&gt;&#10; 2 %current_module = module&lt;-&gt;&#10; 3 line_num(0)&#10; 4 def_inst_meth(&quot;--unused--&quot;, foo, -)&#10; 5 return(nil)&#10; Method foo[-:0]&#10; 0 %self = recv_self&#10; 1 %current_scope = scope&lt;-&gt;&#10; 2 %current_module = module&lt;-&gt;&#10; 3 check_arity(0, 0, -1)&#10; 4 %block(0:0) = recv_closure&#10; 5 thread_poll&#10; 6 line_num(0)&#10; 7 %v_2 = &quot;bar&quot;&#10; 8 %v_3 = call(FUNCTIONAL, 'puts', %self, [%v_2])&#10; 9 return(%v_3)&#10;" wrapText="true" VBox.vgrow="ALWAYS" />
15
+ </children>
16
+ </VBox>
17
+ </center>
18
+ </BorderPane>
@@ -0,0 +1,81 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+
3
+ <?import java.lang.*?>
4
+ <?import java.util.*?>
5
+ <?import javafx.collections.*?>
6
+ <?import javafx.scene.control.*?>
7
+ <?import javafx.scene.layout.*?>
8
+ <?import javafx.scene.paint.*?>
9
+
10
+ <BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
11
+ <center>
12
+ <SplitPane dividerPositions="0.6783625730994152" focusTraversable="true" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0">
13
+ <items>
14
+ <SplitPane dividerPositions="0.5" focusTraversable="true" prefHeight="160.0" prefWidth="200.0">
15
+ <items>
16
+ <VBox prefHeight="200.0" prefWidth="100.0">
17
+ <children>
18
+ <Label text="Abstract Syntax Tree:" />
19
+ <TreeView fx:id="ast_view" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS" />
20
+ </children>
21
+ </VBox>
22
+ <VBox prefHeight="100.0" prefWidth="414.0">
23
+ <children>
24
+ <Label text="Ruby Source:" />
25
+ <TextArea id="ruby_source" fx:id="ruby_view" editable="false" prefHeight="258.0000999999975" prefWidth="330.0" style="-fx-font-family: monospaced" text="def foo&#10; puts &quot;bar&quot;&#10;end" wrapText="true" VBox.vgrow="ALWAYS" />
26
+ </children>
27
+ </VBox>
28
+ </items>
29
+ </SplitPane>
30
+ <VBox prefHeight="-1.0" prefWidth="-1.0">
31
+ <children>
32
+ <Label id="compile_information" text="Information" />
33
+ <ListView fx:id="compile_information" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS" />
34
+ </children>
35
+ </VBox>
36
+ </items>
37
+ </SplitPane>
38
+ </center>
39
+ <top>
40
+ <VBox prefHeight="-1.0" prefWidth="-1.0">
41
+ <children>
42
+ <MenuBar>
43
+ <menus>
44
+ <Menu mnemonicParsing="false" text="File">
45
+ <items>
46
+ <MenuItem mnemonicParsing="false" onAction="#close_app" text="Close" />
47
+ </items>
48
+ </Menu>
49
+ <Menu mnemonicParsing="false" text="View">
50
+ <items>
51
+ <MenuItem mnemonicParsing="false" onAction="#launch_ir_view" text="IR View" />
52
+ <MenuItem mnemonicParsing="false" onAction="#launch_cfg_view" text="Control Flow Graph" />
53
+ </items>
54
+ </Menu>
55
+ <Menu mnemonicParsing="false" text="Help">
56
+ <items>
57
+ <MenuItem mnemonicParsing="false" onAction="#launch_about" text="About" />
58
+ </items>
59
+ </Menu>
60
+ </menus>
61
+ </MenuBar>
62
+ <ToolBar>
63
+ <items>
64
+ <Label text="IRPasses:" />
65
+ <ComboBox fx:id="ir_passes_box" onAction="#select_ir_pass">
66
+ <items>
67
+ <FXCollections fx:factory="observableArrayList">
68
+ <String fx:value="Item 1" />
69
+ <String fx:value="Item 2" />
70
+ <String fx:value="Item 3" />
71
+ </FXCollections>
72
+ </items>
73
+ </ComboBox>
74
+ <Button mnemonicParsing="false" onAction="#step_ir_pass" text="Step" />
75
+ <Button mnemonicParsing="false" onAction="#reset_passes" text="Reset" />
76
+ </items>
77
+ </ToolBar>
78
+ </children>
79
+ </VBox>
80
+ </top>
81
+ </BorderPane>