1010
1111@(define codeblock-include (make-codeblock-include #'h ))
1212
13- @(for-each (λ (f) (ev `(require (file ,(path->string (build-path notes "knock " f))))))
14- '("interp.rkt " "compile.rkt " "ast.rkt " "syntax.rkt " "asm/interp.rkt " "asm/printer.rkt " ))
15-
1613@title[#:tag "Graphviz " ]{Using Graphviz/dot to visualize our AST}
1714
1815@table-of-contents[]
@@ -23,16 +20,15 @@ Abstract Syntax Trees (ASTs) are a useful abstraction when dealing with
2320programming languages as an object for analysis or manipulation (e.g.
2421compilation). At the same time , these structures can quickly become
2522too large reason about just by looking at it. For example, in Knock,
26- our AST for @racket[ (if (zero? x) (add1 (add1 x)) (sub1 x))] looks
23+ our AST for @tt{ (if (zero? x) (add1 (add1 x)) (sub1 x))} looks
2724like the following:
2825
2926@#reader scribble/comment-reader
3027(racketblock
3128 (if-e
3229 (prim-e 'zero? (list (var-e 'x )))
3330 (prim-e 'add1 (list (prim-e 'add1 (list (int-e 1 )))))
34- (prim-e 'sub1 (list (var-e 'x ))))
35- )
31+ (prim-e 'sub1 (list (var-e 'x )))))
3632
3733This has all the information necessary for manipulating our program (and more),
3834it's a bit unwieldy to look at. Particularly when debugging, it can
@@ -46,11 +42,11 @@ the following AST:
4642@#reader scribble/comment-reader
4743(racketblock
4844 (if-e
49- (prim-e 'zero? (list (var-e 'x )
45+ (prim-e 'zero? (list (var-e 'x )))
5046 (let-e
51- (list (binding 'g387 (prim-e 'add1 (list (int-e 1 ))))
52- (prim-e 'add1 (list (var-e 'g387 ))
53- (prim-e 'sub1 (list (var-e 'x )))
47+ (list (binding 'g387 (prim-e 'add1 (list (int-e 1 )))))
48+ (prim-e 'add1 (list (var-e 'g387 )))
49+ (prim-e 'sub1 (list (var-e 'x ))))))
5450
5551Was the program transformation done correctly? If you study the AST
5652carefully, you can determine that it was. However, it would be easier
@@ -89,28 +85,28 @@ for visualizing graphs.
8985Graphviz has many components, but we will focus on @tt{dot}, which is
9086the tool for laying out directed graphs. The full manual for @tt{dot}
9187can be found on the graphviz website:
92- @link["https://www.graphviz.org/pdf/dotguide.pdf " ]{https://www.graphviz.org/pdf/dotguide.pdf }.
88+ @link["https://www.graphviz.org/pdf/dotguide.pdf " ]{The Dot Guide }.
9389
9490Instructions for downloading Graphviz (and therefore @tt{dot}) can be found on
9591their website as well:
96- @link["https://www.graphviz.org/download/ " ]{https://www.graphviz.org/download/ }
92+ @link["https://www.graphviz.org/download/ " ]{Download Graphviz }
9793
9894The syntax for @tt{dot} files is fairly straightforward, you first declare the
9995type of graph, and give it a name. For our purposes the type will always be
10096@tt{digraph} (i.e. directed-graph), and the name can be whatever you choose
10197(though it will likely not matter much). For example:
10298
103- @verbatim|
99+ @verbatim|{
104100digraph CMSC430 {
105101 ...
106102}
107- |
103+ } |
108104
109105The ellipses are where you describe the graph you'd like to visualize. The
110106designers of Graphviz provide a grammar describing the language accepted by
111107their tools (I wish all system designers provided a grammar!). This can be
112108found on the Graphviz website:
113- @link["https://graphviz.org/doc/info/lang.html " ]{https://graphviz.org/doc/info/lang.html}
109+ @link["https://graphviz.org/doc/info/lang.html " ]{The DOT language}.
114110
115111Most of the time you will not need to consult the grammar, as most of the
116112simple rules are straightforward for those that have programmed in C or Java.
@@ -132,13 +128,13 @@ course), you can basically just use the following three types of statements:
132128Node statements are just an ASCII string (representing a Node ID) and an
133129optional list of attributes for that node. For example:
134130
135- @verbatim|
131+ @verbatim|{
136132digraph CMSC430 {
137133 lexer;
138134 parser [shape=box];
139135 code_gen [color=red];
140136}
141- |
137+ } |
142138
143139Using the @tt{dot} tool on a file with the above as its contents produces the
144140following diagram:
@@ -147,13 +143,13 @@ following diagram:
147143
148144Edge statements connect nodes in our graph, for example:
149145
150- @verbatim|
146+ @verbatim|{
151147digraph CMSC430 {
152148 lexer -> parser -> code_gen;
153149 parser [shape=box];
154150 code_gen [color=red];
155151}
156- |
152+ } |
157153
158154This produces the following diagram:
159155
@@ -163,13 +159,13 @@ You may wonder if the order matters here. While the @emph{horizontal} order
163159matters when specifying the edges in an edge statement, the @emph{vertical}
164160order does not matter in this case. The following produces the same diagram:
165161
166- @verbatim|
162+ @verbatim|{
167163digraph CMSC430 {
168164 parser [shape=box];
169165 code_gen [color=red];
170166 lexer -> parser -> code_gen;
171167}
172- |
168+ } |
173169
174170Notice that @tt{lexer} does not have its own `declaration' this is because it
175171is unnecessary unless you want to attach attributes to a node (as we do
@@ -179,13 +175,13 @@ Edge statements also support an optional list of attributes, the following
179175produces a similar diagram except that both edges are shaded ``deeppink2'' (for
180176the full list of supported colors, see the official documentation).
181177
182- @verbatim|
178+ @verbatim|{
183179digraph CMSC430 {
184180 lexer -> parser -> code_gen [color=deeppink2];
185181 parser [shape=box];
186182 code_gen [color=red];
187183}
188- |
184+ } |
189185
190186Attribute nodes describe a set of attributes that apply to all subsequent
191187statements (which means that vertical order @emph{does} matter here!). Unless
@@ -196,7 +192,7 @@ Here we added three attribute statements. Take a minute to study the example
196192below and see how each attribute statement affects the output.
197193
198194
199- @verbatim|
195+ @verbatim|{
200196digraph CMSC430 {
201197 edge [color=blue];
202198 lexer -> parser
@@ -207,7 +203,7 @@ digraph CMSC430 {
207203 code_gen [color=red];
208204 optimizer -> code_gen;
209205}
210- |
206+ } |
211207
212208@image{img/edges3.png}
213209
@@ -224,7 +220,7 @@ an @tt{if} node).
224220Here is an example of a @tt{dot} description make using our library on the program
225221@racket[(if (zero? x) 1 2 )]:
226222
227- @verbatim|
223+ @verbatim|{
228224digraph prog {
229225 g850 [ label=" x " ];
230226 g849 [ color=red,label=" (zero? ...) " ];
@@ -236,7 +232,7 @@ digraph prog {
236232 g848 -> g851 ;
237233 g848 -> g852 ;
238234}
239- |
235+ } |
240236
241237Not super nice to read, but we had a program write it for us!
242238
@@ -246,3 +242,5 @@ The complete library (three files):
246242@codeblock-include["knock/dot.rkt " ]
247243@codeblock-include["knock/render-ast.rkt " ]
248244@codeblock-include["knock/pretty-printer.rkt " ]
245+
246+
0 commit comments