6ac0704a583b47cb2e76e25ae82fab972434b6f5
1 /************************************************************************
2 ************************************************************************
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.
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.
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 ************************************************************************/
24 /*****************************************************************************
25 ******************************************************************************
29 ******************************************************************************
30 *****************************************************************************/
34 * \author Yann Orlarey
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.
50 Tree BOXTYPEPROP
= tree(symbol("boxTypeProp"));
51 static bool infereBoxType (Tree box
, int* inum
, int* onum
);
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
63 bool getBoxType (Tree box
, int* inum
, int* onum
)
66 if (getProperty(box
, BOXTYPEPROP
, t
)) {
71 *inum
= hd(t
)->node().getInt();
72 *onum
= tl(t
)->node().getInt();
78 if (infereBoxType(box
, inum
, onum
)) {
79 setProperty(box
, BOXTYPEPROP
, cons(tree(*inum
), tree(*onum
)));
82 setProperty(box
, BOXTYPEPROP
, nil
);
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
101 static bool infereBoxType (Tree t
, int* inum
, int* onum
)
104 //Tree abstr, genv, vis, lenv;
106 xtended
* p
= (xtended
*) getUserData(t
);
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; }
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; }
117 else if (isBoxPatternVar(t
,a
)) { return false; }
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; }
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; }
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
); }
139 else if (isBoxVBargraph(t
)) { *inum
= 1; *onum
= 1; }
140 else if (isBoxHBargraph(t
)) { *inum
= 1; *onum
= 1; }
142 else if (isBoxSeq(t
, a
, b
)) {
145 if (!getBoxType(a
, &u
, &v
)) return false;
146 if (!getBoxType(b
, &x
, &y
)) return false;
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
;
154 *inum
= u
; *onum
= y
;
157 } else if (isBoxPar(t
, a
, b
)) {
160 if (!getBoxType(a
, &u
, &v
)) return false;
161 if (!getBoxType(b
, &x
, &y
)) return false;
163 *inum
= u
+x
; *onum
= v
+y
;
165 } else if (isBoxSplit(t
, a
, b
)) {
168 if (!getBoxType(a
, &u
, &v
)) return false;
169 if (!getBoxType(b
, &x
, &y
)) return false;
172 cerr
<< "Connection error in : " << boxpp(t
) << endl
173 << "The first expression : " << boxpp(a
) << " has no outputs" << endl
;
178 cerr
<< "Connection error in : " << boxpp(t
) << endl
179 << "The second expression : " << boxpp(b
) << " has no inputs" << endl
;
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
;
191 *inum
= u
; *onum
= y
;
193 } else if (isBoxMerge(t
, a
, b
)) {
196 if (!getBoxType(a
, &u
, &v
)) return false;
197 if (!getBoxType(b
, &x
, &y
)) return false;
200 cerr
<< "Connection error in : " << boxpp(t
) << endl
201 << "The first expression : " << boxpp(a
) << " has no outputs" << endl
;
206 cerr
<< "Connection error in : " << boxpp(t
) << endl
207 << "The second expression : " << boxpp(b
) << " has no inputs" << endl
;
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
;
219 *inum
= u
; *onum
= y
;
221 } else if (isBoxRec(t
, a
, b
)) {
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
;
236 *inum
= max(0,u
-y
); *onum
= v
;
238 } else if (isBoxEnvironment(t
)) {
239 cerr
<< "Connection error : an environment is not a block-diagram : " << boxpp(t
) << endl
;
242 cerr
<< "boxType() internal error : unrecognized box expression " << boxpp(t
) << endl
;