Skip to content

Commit 867bd54

Browse files
committed
Add a tab in the inspector to visualize a CFG
1 parent 952bc03 commit 867bd54

2 files changed

Lines changed: 187 additions & 0 deletions

File tree

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
Extension { #name : 'FASTAbstractBasicBlock' }
2+
3+
{ #category : '*FAST-Python-Tools' }
4+
FASTAbstractBasicBlock >> inspectionVisualization: aBuilder [
5+
6+
<inspectorPresentationOrder: 3 title: 'Visu'>
7+
^ (aBuilder instantiate: SpRoassalInspectorPresenter)
8+
canvas: (FASTCFGVisualizationBuilder on: self);
9+
yourself
10+
]
11+
12+
{ #category : '*FAST-Python-Tools' }
13+
FASTAbstractBasicBlock >> inspectionVisualizationContext: aContext [
14+
15+
aContext active: self isStart
16+
]
17+
18+
{ #category : '*FAST-Python-Tools' }
19+
FASTAbstractBasicBlock >> withAllFollowingBlocks [
20+
21+
^ self withDeep: #nextBlocks collect: #yourself
22+
]
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
Class {
2+
#name : 'FASTCFGVisualizationBuilder',
3+
#superclass : 'Object',
4+
#instVars : [
5+
'canvas'
6+
],
7+
#category : 'FAST-Python-Tools-CFG/DataFlow',
8+
#package : 'FAST-Python-Tools',
9+
#tag : 'CFG/DataFlow'
10+
}
11+
12+
{ #category : 'instance creation' }
13+
FASTCFGVisualizationBuilder class >> on: aStartBlock [
14+
15+
^ self new openOn: aStartBlock
16+
]
17+
18+
{ #category : 'instance creation' }
19+
FASTCFGVisualizationBuilder >> attachLineText: lineShape [
20+
21+
lineShape model key nextBlockForValues do: [ :valueNextBlock |
22+
| label |
23+
valueNextBlock value = lineShape model value ifTrue: [
24+
label := RSLabel new text: valueNextBlock key asString.
25+
RSLocation new
26+
center;
27+
stick: label on: lineShape.
28+
canvas add: label ] ]
29+
]
30+
31+
{ #category : 'hooks' }
32+
FASTCFGVisualizationBuilder >> basicBlockShape: aBasicBlock [
33+
34+
| shape |
35+
shape := aBasicBlock isStart
36+
ifTrue: [
37+
aBasicBlock isFinal
38+
ifTrue: [ self startAndFinalBlockShape ]
39+
ifFalse: [ self startBlockShape ] ]
40+
ifFalse: [
41+
aBasicBlock isFinal
42+
ifTrue: [ self finalBlockShape ]
43+
ifFalse: [ self normalBlockShape ] ].
44+
aBasicBlock isConditional ifTrue: [ shape color: self conditionalBlockColor ].
45+
^ shape
46+
]
47+
48+
{ #category : 'instance creation' }
49+
FASTCFGVisualizationBuilder >> buildLegend [
50+
51+
| legend |
52+
legend := RSLegend new.
53+
legend container: canvas.
54+
legend onDemand.
55+
legend title: 'Legend'.
56+
legend text: 'Start block' withShape: self startBlockShape.
57+
legend text: 'Final block' withShape: self finalBlockShape.
58+
legend text: 'start & final block' withShape: self startAndFinalBlockShape.
59+
legend text: 'Normal block' withShape: self normalBlockShape.
60+
legend text: 'Conditional block' withShape: (self normalBlockShape color: self conditionalBlockColor).
61+
legend build
62+
]
63+
64+
{ #category : 'instance creation' }
65+
FASTCFGVisualizationBuilder >> buildLines: shapes [
66+
67+
| marker bldr |
68+
marker := RSArrowedLine new defaultHead.
69+
70+
bldr := RSLineBuilder arrowedLine.
71+
bldr
72+
verticalBezier ; "Bezier lines"
73+
markerEnd: marker ; "Bezier lines"
74+
withBorderAttachPoint;
75+
shapes: shapes;
76+
canvas: canvas;
77+
connectToAll: [ :block | block nextBlocks ].
78+
79+
bldr shape markerMid: (RSLabel new text: 'true').
80+
81+
canvas lines do: [ :lineModel |
82+
lineModel model key isConditional
83+
ifTrue: [ self attachLineText: lineModel ] ]
84+
]
85+
86+
{ #category : 'hooks' }
87+
FASTCFGVisualizationBuilder >> conditionalBlockColor [
88+
89+
^ Color blue
90+
]
91+
92+
{ #category : 'hooks' }
93+
FASTCFGVisualizationBuilder >> finalBlockShape [
94+
95+
^ RSEllipse new
96+
radius: 10;
97+
color: Color transparent;
98+
border: (RSBorder new
99+
width: 4;
100+
color: Color black;
101+
yourself);
102+
yourself
103+
]
104+
105+
{ #category : 'hooks' }
106+
FASTCFGVisualizationBuilder >> normalBlockShape [
107+
108+
^ RSBox new
109+
size: 20;
110+
yourself
111+
]
112+
113+
{ #category : 'instance creation' }
114+
FASTCFGVisualizationBuilder >> openOn: aCFGNode [
115+
116+
| shapes |
117+
canvas := RSCanvas new.
118+
shapes := aCFGNode withAllFollowingBlocks collect: [ :bb | self shapeFor: bb ].
119+
120+
self buildLines: shapes.
121+
122+
canvas addAll: shapes.
123+
[ RSTreeLayout on: shapes ] valueWithin: 5 seconds onTimeout: [ self inform: 'Tree layout computation takes too long. Aborted' ].
124+
125+
self buildLegend.
126+
127+
canvas @ RSCanvasController new noLegend.
128+
129+
^ canvas
130+
]
131+
132+
{ #category : 'hooks' }
133+
FASTCFGVisualizationBuilder >> shapeFor: aBasicBlock [
134+
135+
| shape |
136+
shape := self basicBlockShape: aBasicBlock.
137+
138+
shape model: aBasicBlock.
139+
shape @ (RSPopup text: [ :block | block sourceCode ]).
140+
shape @ RSDraggable.
141+
142+
^ shape
143+
]
144+
145+
{ #category : 'hooks' }
146+
FASTCFGVisualizationBuilder >> startAndFinalBlockShape [
147+
148+
^ RSComposite new
149+
add: self finalBlockShape;
150+
add: (RSEllipse new
151+
radius: 5;
152+
color: Color black;
153+
yourself);
154+
adjustToChildren;
155+
yourself
156+
]
157+
158+
{ #category : 'hooks' }
159+
FASTCFGVisualizationBuilder >> startBlockShape [
160+
161+
^ RSEllipse new
162+
radius: 10;
163+
color: Color black;
164+
yourself
165+
]

0 commit comments

Comments
 (0)