jruby_visualizer 0.1

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.
@@ -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>