Completing Faustine by adding following primitives : float, power, &, |, xor, >=...
[Faustine.git] / interpretor / preprocessor / faust-0.9.47mr3 / compiler / propagate / propagate.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 "propagate.hh"
25 #include "prim2.hh"
26 #include <assert.h>
27 #include "ppbox.hh"
28 #include "xtended.hh"
29 #include "labels.hh"
30 #include "Text.hh"
31 #include "ppsig.hh"
32 #include "names.hh"
33
34 //extern bool gPrintDocSwitch;
35 //static siglist realPropagate (Tree slotenv, Tree path, Tree box, const siglist& lsig);
36
37
38 ////////////////////////////////////////////////////////////////////////
39 /**
40 * propagate : box listOfSignal-> listOfSignal'
41 *
42 * Propage une liste de signaux de l'entrée vers la sortie d'une boite
43 * La boite a été annotée aec son type
44 */
45 ///////////////////////////////////////////////////////////////////////
46
47
48 //! mix une liste de signaux sur n bus
49 siglist mix(const siglist& lsig, int nbus)
50 {
51 int nlines = lsig.size();
52
53 siglist dst(nbus);
54
55 for (int b=0; b<nbus; b++) {
56 Tree t = (b<nlines) ? lsig[b] : sigInt(0);
57 for (int i=b+nbus; i<nlines; i+=nbus) {
58 t = sigAdd(t, lsig[i]);
59 }
60 dst[b] = t;
61 }
62 return dst;
63 }
64
65 //! split une liste de signaux sur n bus
66 siglist split(const siglist& inputs, int nbus)
67 {
68 int nlines = inputs.size();
69
70 siglist outputs(nbus);
71
72 for (int b=0; b<nbus; b++) {
73 outputs[b] = inputs[b % nlines];
74 }
75 return outputs;
76 }
77
78 //! Fabrique une liste de n projections d'un groupe récursif
79 siglist makeSigProjList (Tree t, int n)
80 {
81 siglist l(n);
82 for (int i = 0; i < n; i++) l[i] = sigDelay0(sigProj(i, t));
83 return l;
84 }
85
86 //! Fabrique une liste de n mem projections d'un groupe récursif
87 siglist makeMemSigProjList (Tree t, int n)
88 {
89 siglist l(n);
90 for (int i = 0; i < n; i++) l[i] = sigDelay1(sigProj(i, t));
91 return l;
92 }
93
94
95 //! Fabrique une liste de n entrées
96 siglist makeSigInputList (int n)
97 {
98 siglist l(n);
99 for (int i = 0; i < n; i++) l[i] = sigInput(i);
100 return l;
101 }
102
103 inline siglist makeList(Tree t)
104 {
105 siglist l(1);
106 l[0] = t;
107 return l;
108 }
109
110 siglist listRange(const siglist& l, int i, int j)
111 {
112 siglist r(j-i);
113 for (int x = i; x < j; x++) r[x-i] = l[x];
114 return r;
115 }
116
117 siglist listConcat(const siglist& a, const siglist& b)
118 {
119 int n1 = a.size();
120 int n2 = b.size();
121 siglist r(n1+n2);
122
123 for (int x=0; x<n1; x++) r[x] = a[x];
124 for (int x=0; x<n2; x++) r[x+n1] = b[x];
125 return r;
126 }
127
128 /**
129 * Convert an stl list of signals into a tree list of signals
130 */
131 Tree listConvert(const siglist& a)
132 {
133 int n = a.size();
134 Tree t=nil;
135 while (n--) t = cons(a[n],t);
136 return t;
137 }
138
139 // siglist listConvertBack(Tree l)
140 // {
141 // siglist r;
142 // while (!isNil(l)) { r.push_back(hd(l)); l = tl(l); }
143 // return r;
144 // }
145
146 siglist listLift(const siglist& l)
147 {
148 int n = l.size();
149 siglist r(n);
150
151 for(int i = 0; i<n; i++) r[i] = lift(l[i]);
152 return r;
153 }
154
155 static int gDummyInput = 10000;
156
157 /**
158 * Propagate computes the outputs signals of a block-diagram according to a list of input signals.
159 *
160 *\param slotenv input signals associated with symbolic slots
161 *\param path stack of user interface groups : (type,label)*
162 *\param box block-diagram where we propagate the signals
163 *\param lsig list of signals to be propagated into box
164 *\return list of resulting signals
165 */
166 /*
167 // for debugging purposes
168
169 siglist realpropagate (Tree slotenv, Tree path, Tree box, const siglist& lsig);
170
171 siglist propagate (Tree slotenv, Tree path, Tree box, const siglist& lsig)
172 {
173 cerr << "propagate in " << boxpp(box) << endl;
174 for (int i=0; i<lsig.size(); i++) { cerr << " -> signal " << i << " : " << *(lsig[i]) << endl; }
175 cerr << endl;
176 return realpropagate (slotenv, path, box, lsig);
177 }
178 */
179
180 /**
181 * Old try for names propagation.
182 */
183 //siglist propagate (Tree slotenv, Tree path, Tree box, const siglist& lsig)
184 //{
185 // siglist S = realPropagate(slotenv, path, box, lsig);
186 //
187 // if (gPrintDocSwitch) {
188 // Tree id;
189 // if (lsig.size()==0 && getDefNameProperty(box, id)) {
190 // string nickname = defName2NickName(tree2str(id));
191 // //setSigListNickName(S, nickname);
192 // }
193 // }
194 //
195 // return S;
196 //}
197
198 //siglist realPropagate (Tree slotenv, Tree path, Tree box, const siglist& lsig)
199 siglist propagate (Tree slotenv, Tree path, Tree box, const siglist& lsig)
200 {
201 int i;
202 double r;
203 prim0 p0;
204 prim1 p1;
205 prim2 p2;
206 prim3 p3;
207 prim4 p4;
208 prim5 p5;
209
210 Tree t1, t2, ff, label, cur, min, max, step, type, name, file, slot, body;
211
212
213 xtended* xt = (xtended*)getUserData(box);
214
215 // Extended Primitives
216
217 if (xt) {
218 assert(lsig.size() == xt->arity());
219 return makeList(xt->computeSigOutput(lsig));
220 }
221
222 // Numbers and Constants
223
224 else if (isBoxInt(box, &i)) {
225 assert(lsig.size()==0);
226 return makeList(sigInt(i));
227 }
228 else if (isBoxReal(box, &r)) {
229 assert(lsig.size()==0);
230 return makeList(sigReal(r));
231 }
232
233 else if (isBoxFConst(box, type, name, file)) {
234 assert(lsig.size()==0);
235 return makeList(sigFConst(type, name, file));
236 }
237
238 else if (isBoxFVar(box, type, name, file)) {
239 assert(lsig.size()==0);
240 return makeList(sigFVar(type, name, file));
241 }
242
243 // Wire and Cut
244
245 else if (isBoxCut(box)) {
246 assert(lsig.size()==1);
247 return siglist();
248 }
249
250 else if (isBoxWire(box)) {
251 assert(lsig.size()==1);
252 return lsig;
253 }
254
255 // Slots and Symbolic Boxes
256
257 else if (isBoxSlot(box)) {
258 Tree sig;
259 assert(lsig.size()==0);
260 if (!searchEnv(box,sig,slotenv)) {
261 // test YO simplification des diagrames
262 //fprintf(stderr, "propagate : internal error (slot undefined)\n");
263 //exit(1);
264 sig = sigInput(++gDummyInput);
265 }
266 return makeList(sig);
267 }
268
269 else if (isBoxSymbolic(box, slot, body)) {
270 assert(lsig.size()>0);
271 return propagate(pushEnv(slot,lsig[0],slotenv), path, body, listRange(lsig, 1, lsig.size()));
272 }
273
274 // Primitives
275
276 else if (isBoxPrim0(box, &p0)) {
277 assert(lsig.size()==0);
278 return makeList( p0() );
279 }
280
281 else if (isBoxPrim1(box, &p1)) {
282 assert(lsig.size()==1);
283 return makeList( p1(lsig[0]) );
284 }
285
286 else if (isBoxPrim2(box, &p2)) {
287 // printf("prim2 recoit : "); print(lsig); printf("\n");
288 assert(lsig.size()==2);
289 return makeList( p2(lsig[0],lsig[1]) );
290 }
291
292 else if (isBoxPrim3(box, &p3)) {
293 assert(lsig.size()==3);
294 return makeList( p3(lsig[0],lsig[1],lsig[2]) );
295 }
296
297 else if (isBoxPrim4(box, &p4)) {
298 assert(lsig.size()==4);
299 return makeList( p4(lsig[0],lsig[1],lsig[2],lsig[3]) );
300 }
301
302 else if (isBoxPrim5(box, &p5)) {
303 assert(lsig.size()==5);
304 return makeList( p5(lsig[0],lsig[1],lsig[2],lsig[3],lsig[4]) );
305 }
306
307 else if (isBoxFFun(box, ff)) {
308 //cerr << "propagate en boxFFun of arity " << ffarity(ff) << endl;
309 assert(int(lsig.size())==ffarity(ff));
310 return makeList(sigFFun(ff, listConvert(lsig)));
311 }
312
313 // User Interface Widgets
314
315 else if (isBoxButton(box, label)) {
316 assert(lsig.size()==0);
317 return makeList(sigButton(normalizePath(cons(label, path))));
318 }
319
320 else if (isBoxCheckbox(box, label)) {
321 assert(lsig.size()==0);
322 return makeList(sigCheckbox(normalizePath(cons(label, path))));
323 }
324
325 else if (isBoxVSlider(box, label, cur, min, max, step)) {
326 assert(lsig.size()==0);
327 return makeList(sigVSlider(normalizePath(cons(label, path)), cur, min, max, step));
328 }
329
330 else if (isBoxHSlider(box, label, cur, min, max, step)) {
331 assert(lsig.size()==0);
332 return makeList(sigHSlider(normalizePath(cons(label, path)), cur, min, max, step));
333 }
334
335 else if (isBoxNumEntry(box, label, cur, min, max, step)) {
336 assert(lsig.size()==0);
337 return makeList(sigNumEntry(normalizePath(cons(label, path)), cur, min, max, step));
338 }
339
340 else if (isBoxVBargraph(box, label, min, max)) {
341 assert(lsig.size()==1);
342 return makeList(sigVBargraph(normalizePath(cons(label, path)), min, max, lsig[0]));
343 }
344
345 else if (isBoxHBargraph(box, label, min, max)) {
346 assert(lsig.size()==1);
347 return makeList(sigHBargraph(normalizePath(cons(label, path)), min, max, lsig[0]));
348 }
349
350 // User Interface Groups
351
352 else if (isBoxVGroup(box, label, t1)) {
353 return propagate(slotenv,cons(cons(tree(0),label), path), t1, lsig);
354 }
355
356 else if (isBoxHGroup(box, label, t1)) {
357 return propagate(slotenv, cons(cons(tree(1),label), path), t1, lsig);
358 }
359
360 else if (isBoxTGroup(box, label, t1)) {
361 return propagate(slotenv, cons(cons(tree(2),label), path), t1, lsig);
362 }
363
364 // Block Diagram Composition Algebra
365
366 else if (isBoxSeq(box, t1, t2)) {
367 int in1, out1, in2, out2;
368 getBoxType(t1, &in1, &out1);
369 getBoxType(t2, &in2, &out2);
370
371 assert(out1==in2);
372
373 if (out1 == in2) {
374 return propagate(slotenv, path, t2, propagate(slotenv, path,t1,lsig));
375 } else if (out1 > in2) {
376 siglist lr = propagate(slotenv, path, t1,lsig);
377 return listConcat(propagate(slotenv, path, t2, listRange(lr, 0, in2)), listRange(lr, in2, out1));
378 } else {
379 return propagate(slotenv, path, t2, listConcat( propagate(slotenv, path, t1, listRange(lsig,0,in1)), listRange(lsig,in1,in1+in2-out1) ) );
380 }
381 }
382
383 else if (isBoxPar(box, t1, t2)) {
384 int in1, out1, in2, out2;
385 getBoxType(t1, &in1, &out1);
386 getBoxType(t2, &in2, &out2);
387
388 return listConcat( propagate(slotenv, path, t1, listRange(lsig, 0, in1)),
389 propagate(slotenv, path, t2, listRange(lsig, in1, in1+in2)) );
390 }
391
392 else if (isBoxSplit(box, t1, t2)) {
393 int in1, out1, in2, out2;
394 getBoxType(t1, &in1, &out1);
395 getBoxType(t2, &in2, &out2);
396
397 siglist l1 = propagate(slotenv, path, t1, lsig);
398 siglist l2 = split(l1, in2);
399 return propagate(slotenv, path, t2, l2);
400 }
401
402 else if (isBoxMerge(box, t1, t2)) {
403 int in1, out1, in2, out2;
404 getBoxType(t1, &in1, &out1);
405 getBoxType(t2, &in2, &out2);
406
407 siglist l1 = propagate(slotenv, path, t1, lsig);
408 siglist l2 = mix(l1, in2);
409 return propagate(slotenv, path, t2, l2);
410 }
411 /*
412 else if (isBoxRec(box, t1, t2)) {
413 int in1, out1, in2, out2;
414 getBoxType(t1, &in1, &out1);
415 getBoxType(t2, &in2, &out2);
416
417 siglist l0 = makeSigProjList(ref(1), in2);
418 siglist l1 = propagate(slotenv, path, t2, l0);
419 siglist l2 = propagate(slotenv, path, t1, listConcat(l1,listLift(lsig)));
420 Tree g = rec(listConvert(l2));
421 return makeSigProjList(g, out1);
422 }
423 */
424 else if (isBoxRec(box, t1, t2)) {
425 // Bug Corrected
426 int in1, out1, in2, out2;
427 getBoxType(t1, &in1, &out1);
428 getBoxType(t2, &in2, &out2);
429
430 Tree slotenv2 = lift(slotenv); // the environment must also be lifted
431
432 siglist l0 = makeMemSigProjList(ref(1), in2);
433 siglist l1 = propagate(slotenv2, path, t2, l0);
434 siglist l2 = propagate(slotenv2, path, t1, listConcat(l1,listLift(lsig)));
435 Tree g = rec(listConvert(l2));
436 return makeSigProjList(g, out1);
437 }
438
439 cout << "ERROR in file " << __FILE__ << ':' << __LINE__ << ", unrecognised box expression : " << boxpp(box) << endl;
440 exit(1);
441 return siglist();
442 }
443
444
445 Tree boxPropagateSig (Tree path, Tree box, const siglist& lsig)
446 {
447 return listConvert(propagate(nil, path, box, lsig));
448 }
449