1 /************************************************************************
2  ************************************************************************
3     FAUST compiler
4     Copyright (C) 2003-2018 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  * @file boxcomplexity.cpp
23  * Implement complexity computation for box diagrams.
24  */
25 
26 // Build graphical representation
27 
28 #include "boxcomplexity.hh"
29 #include <ostream>
30 #include "exception.hh"
31 #include "global.hh"
32 #include "xtended.hh"
33 
34 using namespace std;
35 
36 /**
37  * property Key used to store box complexity
38  */
39 
40 static int computeBoxComplexity(Tree box);
41 
42 /**
43  * Return the complexity property of a box expression tree.
44  * If no complexity property exist, it is created and computeBoxComplexity
45  * is called do to the job.
46  *
47  * @param box an evaluated box expression tree
48  * @return the complexity of box
49  *
50  * @see computeBoxComplexity
51  */
boxComplexity(Tree box)52 int boxComplexity(Tree box)
53 {
54     Tree prop = box->getProperty(gGlobal->BCOMPLEXITY);
55 
56     if (prop) {
57         return tree2int(prop);
58 
59     } else {
60         int v = computeBoxComplexity(box);
61         box->setProperty(gGlobal->BCOMPLEXITY, tree(v));
62         return v;
63     }
64 }
65 
66 /**
67  * internal shortcut to simplify computeBoxComplexity code
68  */
69 #define BC boxComplexity
70 
71 /**
72  * Compute the complexity of a box expression.
73  *
74  * Compute the complexity of a box expression tree according to the
75  * complexity of its subexpressions. Basically it counts the number
76  * of boxes to be drawn. The box-diagram expression is supposed
77  * to be evaluated. It will exit with an error if it is not the case.
78  *
79  * @param box an evaluated box expression tree
80  * @return the complexity of box
81  */
computeBoxComplexity(Tree box)82 int computeBoxComplexity(Tree box)
83 {
84     int    i;
85     double r;
86     prim0  p0;
87     prim1  p1;
88     prim2  p2;
89     prim3  p3;
90     prim4  p4;
91     prim5  p5;
92 
93     Tree t1, t2, t3, ff, label, cur, min, max, step, type, name, file, chan;
94 
95     xtended* xt = (xtended*)getUserData(box);
96 
97     // simple elements
98     if (xt)
99         return 1;
100     else if (isBoxInt(box, &i))
101         return 1;
102     else if (isBoxReal(box, &r))
103         return 1;
104 
105     else if (isBoxWaveform(box))
106         return 1;
107 
108     else if (isBoxCut(box))
109         return 0;
110     else if (isBoxWire(box))
111         return 0;
112 
113     else if (isBoxPrim0(box, &p0))
114         return 1;
115     else if (isBoxPrim1(box, &p1))
116         return 1;
117     else if (isBoxPrim2(box, &p2))
118         return 1;
119     else if (isBoxPrim3(box, &p3))
120         return 1;
121     else if (isBoxPrim4(box, &p4))
122         return 1;
123     else if (isBoxPrim5(box, &p5))
124         return 1;
125 
126     // foreign elements
127     else if (isBoxFFun(box, ff))
128         return 1;
129     else if (isBoxFConst(box, type, name, file))
130         return 1;
131     else if (isBoxFVar(box, type, name, file))
132         return 1;
133     // slots and symbolic boxes
134     else if (isBoxSlot(box, &i))
135         return 1;
136     else if (isBoxSymbolic(box, t1, t2))
137         return 1 + BC(t2);
138 
139     // block diagram binary operator
140     else if (isBoxSeq(box, t1, t2))
141         return BC(t1) + BC(t2);
142     else if (isBoxSplit(box, t1, t2))
143         return BC(t1) + BC(t2);
144     else if (isBoxMerge(box, t1, t2))
145         return BC(t1) + BC(t2);
146     else if (isBoxPar(box, t1, t2))
147         return BC(t1) + BC(t2);
148     else if (isBoxRec(box, t1, t2))
149         return BC(t1) + BC(t2);
150 
151     // user interface widgets
152     else if (isBoxButton(box, label))
153         return 1;
154     else if (isBoxCheckbox(box, label))
155         return 1;
156     else if (isBoxVSlider(box, label, cur, min, max, step))
157         return 1;
158     else if (isBoxHSlider(box, label, cur, min, max, step))
159         return 1;
160     else if (isBoxHBargraph(box, label, min, max))
161         return 1;
162     else if (isBoxVBargraph(box, label, min, max))
163         return 1;
164     else if (isBoxSoundfile(box, label, chan))
165         return 1;
166     else if (isBoxNumEntry(box, label, cur, min, max, step))
167         return 1;
168 
169     // user interface groups
170     else if (isBoxVGroup(box, label, t1))
171         return BC(t1);
172     else if (isBoxHGroup(box, label, t1))
173         return BC(t1);
174     else if (isBoxTGroup(box, label, t1))
175         return BC(t1);
176 
177     // environment
178     else if (isBoxEnvironment(box))
179         return 0;
180     else if (isBoxMetadata(box, t1, t2))
181         return BC(t1);
182 
183     else if (isBoxRoute(box, t1, t2, t3))
184         return 0;
185 
186     // to complete
187     else {
188         // fout << tree2str(box);
189         stringstream error;
190         error << "ERROR in boxComplexity : not an evaluated box [[ " << *box << " ]]\n";
191         throw faustexception(error.str());
192     }
193 
194     return -1;
195 }
196