6ac0704a583b47cb2e76e25ae82fab972434b6f5
[Faustine.git] / interpretor / preprocessor / faust-0.9.47mr3 / compiler / boxes / boxtype.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 /*****************************************************************************
25 ******************************************************************************
26
27 Box Type System
28
29 ******************************************************************************
30 *****************************************************************************/
31
32
33 /**\file boxtype.cpp
34 * \author Yann Orlarey
35 * \version 1.0
36 * \date 2003
37 * \brief A simple type system for block diagram expressions.
38 * The type of a block diagram is defined by a number of inputs and outputs.
39 */
40
41
42 #include <stdio.h>
43 #include <string.h>
44 #include "boxes.hh"
45 #include "ppbox.hh"
46 #include "prim2.hh"
47 #include "xtended.hh"
48
49
50 Tree BOXTYPEPROP = tree(symbol("boxTypeProp"));
51 static bool infereBoxType (Tree box, int* inum, int* onum);
52
53
54
55 /**
56 * Return the type (number of inputs and outputs) of a box or false if undefined
57 * \param box the box we want to know the type
58 * \param inum the place to return the number of inputs
59 * \param onum the place to return the number of outputs
60 * \return true if type is defined, false if undefined
61 */
62
63 bool getBoxType (Tree box, int* inum, int* onum)
64 {
65 Tree t;
66 if (getProperty(box, BOXTYPEPROP, t)) {
67
68 if (isNil(t)) {
69 return false;
70 } else {
71 *inum = hd(t)->node().getInt();
72 *onum = tl(t)->node().getInt();
73 return true;
74 }
75
76 } else {
77
78 if (infereBoxType(box, inum, onum)) {
79 setProperty(box, BOXTYPEPROP, cons(tree(*inum), tree(*onum)));
80 return true;
81 } else {
82 setProperty(box, BOXTYPEPROP, nil);
83 return false;
84 }
85 }
86 }
87
88
89
90 /**
91 * Infere the type (number of inputs and outputs) of a box.
92 * The box expression is assumed to be in 'propagation normal form'
93 * that is to have been evaluated and residual abstractions to have been
94 * converted to symbolic boxes (using a2sb()).
95 * \param box the box we want to know the type
96 * \param inum the place to return the number of inputs
97 * \param onum the place to return the number of outputs
98 * \return true if the box expression has a type
99 */
100
101 static bool infereBoxType (Tree t, int* inum, int* onum)
102 {
103 Tree a, b, ff, l, s;
104 //Tree abstr, genv, vis, lenv;
105
106 xtended* p = (xtended*) getUserData(t);
107
108 if (p) { *inum = p->arity(); *onum = 1; }
109 else if (isBoxInt(t)) { *inum = 0; *onum = 1; }
110 else if (isBoxReal(t)) { *inum = 0; *onum = 1; }
111 else if (isBoxWire(t)) { *inum = 1; *onum = 1; }
112 else if (isBoxCut(t)) { *inum = 1; *onum = 0; }
113
114 else if (isBoxSlot(t)) { *inum = 0; *onum = 1; }
115 else if (isBoxSymbolic(t,s,b)) { if (!getBoxType(b, inum, onum)) return false; *inum += 1; }
116
117 else if (isBoxPatternVar(t,a)) { return false; }
118
119 else if (isBoxPrim0(t)) { *inum = 0; *onum = 1; }
120 else if (isBoxPrim1(t)) { *inum = 1; *onum = 1; }
121 else if (isBoxPrim2(t)) { *inum = 2; *onum = 1; }
122 else if (isBoxPrim3(t)) { *inum = 3; *onum = 1; }
123 else if (isBoxPrim4(t)) { *inum = 4; *onum = 1; }
124 else if (isBoxPrim5(t)) { *inum = 5; *onum = 1; }
125
126 else if (isBoxFFun(t,ff)) { *inum = ffarity(ff); *onum = 1; }
127 else if (isBoxFConst(t)) { *inum = 0; *onum = 1; }
128 else if (isBoxFVar(t)) { *inum = 0; *onum = 1; }
129
130 else if (isBoxButton(t)) { *inum = 0; *onum = 1; }
131 else if (isBoxCheckbox(t)) { *inum = 0; *onum = 1; }
132 else if (isBoxVSlider(t)) { *inum = 0; *onum = 1; }
133 else if (isBoxHSlider(t)) { *inum = 0; *onum = 1; }
134 else if (isBoxNumEntry(t)) { *inum = 0; *onum = 1; }
135 else if (isBoxVGroup(t,l,a)){ return getBoxType(a, inum, onum); }
136 else if (isBoxHGroup(t,l,a)){ return getBoxType(a, inum, onum); }
137 else if (isBoxTGroup(t,l,a)){ return getBoxType(a, inum, onum); }
138
139 else if (isBoxVBargraph(t)) { *inum = 1; *onum = 1; }
140 else if (isBoxHBargraph(t)) { *inum = 1; *onum = 1; }
141
142 else if (isBoxSeq(t, a, b)) {
143
144 int u,v,x,y;
145 if (!getBoxType(a, &u, &v)) return false;
146 if (!getBoxType(b, &x, &y)) return false;
147
148 if (v != x) {
149 cerr << "Error in sequential composition (A:B)" << endl
150 << "The number of outputs (" << v << ") of A = " << boxpp(a) << endl
151 << "must be equal to the number of inputs (" << x << ") of B : " << boxpp(b) << endl;
152 exit(1);
153 } else {
154 *inum = u; *onum = y;
155 }
156
157 } else if (isBoxPar(t, a, b)) {
158
159 int u,v,x,y;
160 if (!getBoxType(a, &u, &v)) return false;
161 if (!getBoxType(b, &x, &y)) return false;
162
163 *inum = u+x; *onum = v+y;
164
165 } else if (isBoxSplit(t, a, b)) {
166
167 int u,v,x,y;
168 if (!getBoxType(a, &u, &v)) return false;
169 if (!getBoxType(b, &x, &y)) return false;
170
171 if (v == 0) {
172 cerr << "Connection error in : " << boxpp(t) << endl
173 << "The first expression : " << boxpp(a) << " has no outputs" << endl;
174 exit(1);
175 }
176
177 if (x == 0) {
178 cerr << "Connection error in : " << boxpp(t) << endl
179 << "The second expression : " << boxpp(b) << " has no inputs" << endl;
180 exit(1);
181 }
182
183 if (x % v != 0) {
184 cerr << "Connection error in : " << boxpp(t) << endl
185 << "The number of outputs " << v
186 << " of the first expression should be a divisor of the number of inputs " << x
187 << " of the second expression" << endl;
188 exit(1);
189 }
190
191 *inum = u; *onum = y;
192
193 } else if (isBoxMerge(t, a, b)) {
194
195 int u,v,x,y;
196 if (!getBoxType(a, &u, &v)) return false;
197 if (!getBoxType(b, &x, &y)) return false;
198
199 if (v == 0) {
200 cerr << "Connection error in : " << boxpp(t) << endl
201 << "The first expression : " << boxpp(a) << " has no outputs" << endl;
202 exit(1);
203 }
204
205 if (x == 0) {
206 cerr << "Connection error in : " << boxpp(t) << endl
207 << "The second expression : " << boxpp(b) << " has no inputs" << endl;
208 exit(1);
209 }
210
211 if (v % x != 0) {
212 cerr << "Connection error in : " << boxpp(t) << endl
213 << "The number of outputs " << v
214 << " of the first expression should be a multiple of the number of inputs " << x
215 << " of the second expression" << endl;
216 exit(1);
217 }
218
219 *inum = u; *onum = y;
220
221 } else if (isBoxRec(t, a, b)) {
222
223 int u,v,x,y;
224 if (!getBoxType(a, &u, &v)) return false;
225 if (!getBoxType(b, &x, &y)) return false;
226 if ( (x > v) | (y > u) ) {
227 cerr << "Connection error in : " << boxpp(t) << endl;
228 if (x > v) cerr << "The number of outputs " << v
229 << " of the first expression should be greater or equal \n to the number of inputs " << x
230 << " of the second expression" << endl;
231 if (y > u) cerr << "The number of inputs " << u
232 << " of the first expression should be greater or equal \n to the number of outputs " << y
233 << " of the second expression" << endl;
234 exit(1);
235 }
236 *inum = max(0,u-y); *onum = v;
237
238 } else if (isBoxEnvironment(t)) {
239 cerr << "Connection error : an environment is not a block-diagram : " << boxpp(t) << endl;
240 exit(1);
241 } else {
242 cerr << "boxType() internal error : unrecognized box expression " << boxpp(t) << endl;
243 exit(1);
244 }
245 return true;
246 }
247
248
249