Merge branch 'master' of https://scm.cri.ensmp.fr/git/Faustine
[Faustine.git] / interpreter / preprocessor / faust-0.9.47mr3 / compiler / draw / sigToGraph.cpp
1 /************************************************************************
2 ************************************************************************
3 FAUST compiler
4 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ************************************************************************
20 ************************************************************************/
21
22
23
24 #include <stdio.h>
25
26 #include <set>
27 #include <vector>
28 #include <iostream>
29 #include <sstream>
30 #include <string>
31
32 #include "signals.hh"
33 #include "sigtype.hh"
34 #include "sigtyperules.hh"
35 #include "xtended.hh"
36
37 #include "sigToGraph.hh"
38 #include "sigraterules.hh"
39 #include "Text.hh"
40
41 using namespace std;
42
43 static void recdraw(Tree sig, set<Tree>& drawn, ofstream& fout, RateInferrer* R );
44 static string commonattr(Type t);
45 static string nodeattr(Type t);
46 static string edgeattr(Type t, int rate);
47 static string sigLabel(Tree sig);
48
49
50 /**
51 * Draw a list of signals as a directed graph using graphviz's dot language
52 */
53 void sigToGraph (Tree L, ofstream& fout, RateInferrer* R)
54 {
55 set<Tree> alreadyDrawn;
56
57 fout << "strict digraph loopgraph {\n"
58 << " rankdir=LR; node [fontsize=10];"
59 << endl;
60 int out = 0;
61 while (isList(L)) {
62 recdraw(hd(L), alreadyDrawn, fout, R);
63
64 fout << "OUTPUT_" << out << "[color=\"red2\" style=\"filled\" fillcolor=\"pink\"];" << endl;
65 fout << 'S' << hd(L) << " -> " << "OUTPUT_" << out++ << "[" << edgeattr(getCertifiedSigType(hd(L)), R->rate(hd(L))) << "];" << endl;
66 L = tl(L);
67 }
68
69 fout << "}" << endl;
70 }
71
72
73 /******************************* IMPLEMENTATION ***********************************/
74
75
76 /**
77 * Draw recursively a signal
78 */
79 static void recdraw(Tree sig, set<Tree>& drawn, ofstream& fout, RateInferrer* R )
80 {
81 //cerr << ++TABBER << "ENTER REC DRAW OF " << sig << "$" << *sig << endl;
82 vector<Tree> subsig;
83 int n;
84
85 if (drawn.count(sig) == 0) {
86 // the signal has never been drawn
87 drawn.insert(sig); // remember it
88 if (isList(sig)) {
89 // it's a list of signals : we draw each signal of the list
90 do {
91 recdraw(hd(sig), drawn, fout, R);
92 sig = tl(sig);
93 } while (isList(sig));
94 } else {
95 // it is a regular signal
96 // first draw the node
97 fout << 'S' << sig << "[label=\"" << sigLabel(sig) << "\""
98 << nodeattr(getCertifiedSigType(sig)) << "];"
99 << endl;
100
101 // then draw the subsignals if any
102 n = getSubSignals(sig, subsig);
103 if (n > 0) {
104 Tree id, body;
105 // check special recursion case, recreate a vector of subsignals instead of the
106 // list provided by getSubSignal
107 if (n==1 && isList(subsig[0])) {
108 assert(isRec(sig,id,body));
109
110 Tree L = subsig[0];
111 subsig.clear();
112 n = 0;
113 do {
114 subsig.push_back(hd(L));
115 L = tl(L);
116 n += 1;
117 } while (isList(L));
118 }
119
120 // draw each subsignal
121 for (int i=0; i<n; i++) {
122 recdraw(subsig[i], drawn, fout, R);
123 if (isRec(subsig[i],id,body)) {
124 // special case when source is a recursive group, we don't want a rate
125 fout << 'S' << subsig[i] << " -> " << 'S' << sig
126 << "[style=dashed];"
127 << endl;
128 } else {
129 // special case when source is a recursive group, we don't want a rate
130 fout << 'S' << subsig[i] << " -> " << 'S' << sig
131 << "[" << edgeattr(getCertifiedSigType(subsig[i]), R->rate(subsig[i])) << "];"
132 << endl;
133 }
134 }
135 }
136 }
137 }
138 //cerr << --TABBER << "EXIT REC DRAW OF " << sig << endl;
139 }
140
141
142 /**
143 * Convert a signal type into attributes common to edges and nodes
144 */
145 static string commonattr(Type t)
146 {
147 string s;
148
149 // nature
150 if (t->nature()==kInt) {
151 s += " color=\"blue\"";
152 } else {
153 s += " color=\"red\"";
154 }
155
156 // vectorability
157 if (t->vectorability()==kVect && t->variability()==kSamp) {
158 s += " style=\"bold\"";
159 }
160
161 return s;
162 }
163 /**
164 * Convert a signal type into edge attributes
165 */
166 static string edgeattr(Type t, int rate)
167 {
168 string s;
169 vector<int> d;
170 Type b = t->dimensions(d);
171
172 s = commonattr(t);
173
174 // add rate information as label at the head of the arrow
175 s += " label=\"";
176 for (int i=0; i<d.size(); i++) {
177 s += subst("[$0]", T(d[i]));
178 }
179 s += subst("x$0\" fontsize=8", T(rate));
180
181 return s;
182 }
183
184
185 /**
186 * Convert a signal type into node attributes
187 */
188 static string nodeattr(Type t)
189 {
190 string s = commonattr(t);
191
192 // variability
193 if (t->variability()==kKonst) {
194 s += " shape=\"box\"";
195 } else if (t->variability()==kBlock) {
196 s += " shape=\"hexagon\"";
197 } else if (t->variability()==kSamp) {
198 s += " shape=\"ellipse\"";
199 }
200
201 return s;
202 }
203
204
205 /**
206 * translate signal binary operations into strings
207 */
208 static const char* binopname[]= {
209 "+", "-", "*", "/", "%",
210 "<<", ">>",
211 ">", "<", ">=", "<=", "==", "!=",
212 "&", "|", "^"
213 };
214
215
216 /**
217 * return the label of a signal as a string
218 */
219 static string sigLabel(Tree sig)
220 {
221 int i;
222 double r;
223 Tree x, y, z, c, type, name, file, ff, largs, id, le, sel, var, label;
224
225 xtended* p = (xtended*) getUserData(sig);
226
227 stringstream fout;
228
229 if (p) { fout << p->name(); }
230 else if ( isSigInt(sig, &i) ) { fout << i; }
231 else if ( isSigReal(sig, &r) ) { fout << r; }
232 else if ( isSigInput(sig, &i) ) { fout << "INPUT_" << i; }
233 else if ( isSigOutput(sig, &i, x) ) { fout << "OUTPUT_" << i; }
234
235 else if ( isSigDelay1(sig, x) ) { fout << "mem"; }
236 else if ( isSigFixDelay(sig, x, y) ) { fout << "@"; }
237 else if ( isSigPrefix(sig, x, y) ) { fout << "prefix"; }
238 else if ( isSigIota(sig, x) ) { fout << "iota"; }
239 else if ( isSigBinOp(sig, &i, x, y) ) { fout << binopname[i]; }
240 else if ( isSigFFun(sig, ff, largs) ) { fout << "ffunction:" << *ff; }
241 else if ( isSigFConst(sig, type, name, file) ) { fout << *name; }
242 else if ( isSigFVar(sig, type, name, file) ) { fout << *name; }
243
244 else if ( isSigTable(sig, id, x, y) ) { fout << "table:" << id; }
245 else if ( isSigWRTbl(sig, id, x, y, z) ) { fout << "write:" << id; }
246 else if ( isSigRDTbl(sig, x, y) ) { fout << "read"; }
247
248
249
250 else if ( isSigSelect2(sig, sel, x, y) ) { fout << "select2"; }
251 else if ( isSigSelect3(sig, sel, x, y, z) ) { fout << "select3"; }
252
253 else if ( isSigGen(sig, x) ) { fout << "generator"; }
254
255 else if ( isProj(sig, &i, x) ) { fout << "Proj" << i; }
256 else if ( isRec(sig, var, le) ) { fout << "REC " << *var; }
257
258 else if ( isSigIntCast(sig, x) ) { fout << "int"; }
259 else if ( isSigFloatCast(sig, x) ) { fout << "float"; }
260 #if 0
261 else if ( isSigButton(sig, label) ) { fout << "button \"" << *label << '"'; }
262 else if ( isSigCheckbox(sig, label) ) { fout << "checkbox \"" << *label << '"'; }
263 else if ( isSigVSlider(sig, label,c,x,y,z) ) { fout << "vslider \"" << *label << '"'; }
264 else if ( isSigHSlider(sig, label,c,x,y,z) ) { fout << "hslider \"" << *label << '"'; }
265 else if ( isSigNumEntry(sig, label,c,x,y,z) ) { fout << "nentry \"" << *label << '"'; }
266
267 else if ( isSigVBargraph(sig, label,x,y,z) ) { fout << "vbargraph \"" << *label << '"'; }
268 else if ( isSigHBargraph(sig, label,x,y,z) ) { fout << "hbargraph \"" << *label << '"'; }
269 #else
270 else if ( isSigButton(sig, label) ) { fout << "button"; }
271 else if ( isSigCheckbox(sig, label) ) { fout << "checkbox"; }
272 else if ( isSigVSlider(sig, label,c,x,y,z) ) { fout << "vslider"; }
273 else if ( isSigHSlider(sig, label,c,x,y,z) ) { fout << "hslider"; }
274 else if ( isSigNumEntry(sig, label,c,x,y,z) ) { fout << "nentry"; }
275
276 else if ( isSigVBargraph(sig, label,x,y,z) ) { fout << "vbargraph"; }
277 else if ( isSigHBargraph(sig, label,x,y,z) ) { fout << "hbargraph"; }
278 #endif
279 else if ( isSigAttach(sig, x, y) ) { fout << "attach"; }
280
281 else if ( isSigVectorize(sig, x, y) ) { fout << "vectorize"; }
282 else if ( isSigSerialize(sig, x) ) { fout << "serialize"; }
283 else if ( isSigConcat(sig, x, y) ) { fout << "#"; }
284 else if ( isSigVectorAt(sig, x, y) ) { fout << "[]"; }
285
286 else if ( isSigUpSample(sig, x, y) ) { fout << "up"; }
287 else if ( isSigDownSample(sig, x, y) ) { fout << "down"; }
288
289 else {
290 cerr << "ERROR in sigLabel(), unrecognized signal : " << *sig << endl;
291 exit(1);
292 }
293
294 return fout.str();
295 }