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 /************************************************************************
23  ************************************************************************
24     Signals Order Rules
25     Copyright (C) 2003-2018 GRAME, Centre National de Creation Musicale
26     ---------------------------------------------------------------------
27     A small typing system that computes the "order" of a signal :
28         0 = numerical constant
29         1 = non-numerical constants (FConst)
30         2 = User Interface
31         3 = Audio
32     This order will be used to put expressions in normal form.
33 
34     Contrary to the full type system, it doesn't require environments
35     or special treatments for recursions
36  ************************************************************************
37  ************************************************************************/
38 
39 #include "sigorderrules.hh"
40 #include <stdio.h>
41 #include "exception.hh"
42 #include "global.hh"
43 #include "prim2.hh"
44 #include "sigprint.hh"
45 #include "sigtype.hh"
46 #include "tlib.hh"
47 #include "xtended.hh"
48 
49 static int infereSigOrder(Tree sig);
50 
51 /**
52  * Retrieve the order annotation (between 0 and 3) of a signal.
53  * (compute the order the first time). Orders have the following meanings
54  *	0 : numbers
55  *	1 : constants
56  *	2 : user interface values
57  *	3 : audio values
58  * @param sig the signal we want to know the order
59  * @return the order number
60  */
getSigOrder(Tree sig)61 int getSigOrder(Tree sig)
62 {
63     Tree tt;
64     if (getProperty(sig, gGlobal->ORDERPROP, tt)) {
65         return tree2int(tt);
66     } else {
67         int order = infereSigOrder(sig);
68         setProperty(sig, gGlobal->ORDERPROP, tree(order));
69         return order;
70     }
71 }
72 
73 // shortcut for order inference algorithm
74 #define O getSigOrder
75 
76 /**
77  * Infere the order of a term according to its components
78  * @param sig the signal to analyze
79  * @return the order of sig
80  */
infereSigOrder(Tree sig)81 static int infereSigOrder(Tree sig)
82 {
83     int    i;
84     double r;
85     Tree   sel, s1, s2, s3, s4, ff, id, ls, l, x, y, z, var, body, type, name, file, sf;
86 
87     xtended* xt = (xtended*)getUserData(sig);
88     // primitive elements
89     if (xt) {
90         vector<int> args;
91         for (int i1 = 0; i1 < sig->arity(); i1++) {
92             args.push_back(O(sig->branch(i1)));
93         }
94         return xt->infereSigOrder(args);
95     }
96 
97     else if (isSigInt(sig, &i))
98         return 0;
99 
100     else if (isSigReal(sig, &r))
101         return 0;
102 
103     else if (isSigWaveform(sig))
104         return 3;
105 
106     else if (isSigInput(sig, &i))
107         return 3;
108 
109     else if (isSigOutput(sig, &i, s1))
110         return 3;
111 
112     else if (isSigDelay1(sig, s1))
113         return 3;
114 
115     else if (isSigPrefix(sig, s1, s2))
116         return 3;
117 
118     else if (isSigDelay(sig, s1, s2))
119         return 3;
120 
121     else if (isSigBinOp(sig, &i, s1, s2))
122         return max(O(s1), O(s2));
123 
124     else if (isSigIntCast(sig, s1))
125         return O(s1);
126 
127     else if (isSigFloatCast(sig, s1))
128         return O(s1);
129 
130     else if (isSigFFun(sig, ff, ls) && isNil(ls))
131         return 1;
132 
133     else if (isSigFFun(sig, ff, ls))
134         return max(1, O(ls));
135 
136     else if (isSigFConst(sig, type, name, file))
137         return 1;
138 
139     else if (isSigFVar(sig, type, name, file))
140         return 2;
141 
142     else if (isSigButton(sig))
143         return 2;
144 
145     else if (isSigCheckbox(sig))
146         return 2;
147 
148     else if (isSigVSlider(sig))
149         return 2;
150 
151     else if (isSigHSlider(sig))
152         return 2;
153 
154     else if (isSigNumEntry(sig))
155         return 2;
156 
157     else if (isSigHBargraph(sig, l, x, y, s1))
158         return max(2, O(s1));  // at least a user interface
159 
160     else if (isSigVBargraph(sig, l, x, y, s1))
161         return max(2, O(s1));  // at least a user interface
162 
163     else if (isSigEnable(sig, s1, s2))
164         return max(O(s1), O(s2));  // O(s1);
165 
166     else if (isSigControl(sig, s1, s2))
167         return max(O(s1), O(s2));  // O(s1);
168 
169     else if (isSigSoundfile(sig, l))
170         throw faustexception("ERROR inferring signal order : isSigSoundfile\n");  // not supposed to happen.;
171 
172     else if (isSigSoundfileLength(sig, sf, x))
173         return 2;
174 
175     else if (isSigSoundfileRate(sig, sf, x))
176         return 2;
177 
178     else if (isSigSoundfileBuffer(sig, sf, x, y, z))
179         return 3;
180 
181     else if (isSigAttach(sig, s1, s2))
182         return max(1, O(s1));  // at least a constant
183 
184     else if (isRec(sig, var, body))
185         throw faustexception("ERROR inferring signal order : isRec\n");  // return 3;  // not supposed to happen.
186 
187     else if (isRef(sig, var))
188         throw faustexception("ERROR inferring signal order : isRef\n");  // return 3;  // not supposed to happen.
189 
190     else if (isProj(sig, &i, s1))
191         return 3;
192 
193     else if (isSigTable(sig, id, s1, s2))
194         return 3;
195 
196     else if (isSigWRTbl(sig, id, s1, s2, s3))
197         return 3;
198 
199     else if (isSigRDTbl(sig, s1, s2))
200         return 3;
201 
202     else if (isSigDocConstantTbl(sig, s1, s2))
203         return 3;
204 
205     else if (isSigDocWriteTbl(sig, s1, s2, s3, s4))
206         return 3;
207 
208     else if (isSigDocAccessTbl(sig, s1, s2))
209         return 3;
210 
211     else if (isSigGen(sig, s1))
212         return 3;
213 
214     else if (isSigSelect2(sig, sel, s1, s2))
215         return 3;
216 
217     else if (isList(sig)) {
218         int r1 = 0;
219         while (isList(sig)) {
220             int x1 = O(hd(sig));
221             if (x1 > r1) r1 = x1;
222             sig = tl(sig);
223         }
224         return r1;
225     }
226 
227     // unrecognized signal here
228     throw faustexception("ERROR inferring signal order : unrecognized signal\n");
229 }
230