FAUST compiler  0.9.9.6b8
propagate.cpp
Go to the documentation of this file.
00001 /************************************************************************
00002  ************************************************************************
00003     FAUST compiler
00004     Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
00005     ---------------------------------------------------------------------
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  ************************************************************************
00020  ************************************************************************/
00021  
00022  
00023  
00024 #include "propagate.hh"
00025 #include "prim2.hh"
00026 #include <assert.h>
00027 #include "ppbox.hh"
00028 #include "xtended.hh"
00029 #include "labels.hh"
00030 #include "Text.hh"
00031 #include "ppsig.hh"
00032 #include "names.hh"
00033 
00034 //extern bool gPrintDocSwitch;
00035 //static siglist realPropagate (Tree slotenv, Tree path, Tree box, const siglist&  lsig);
00036 
00037 
00039 
00045 
00046 
00047 
00049 siglist mix(const siglist& lsig, int nbus)
00050 {
00051     int nlines  = lsig.size();
00052     
00053     siglist dst(nbus);
00054     
00055     for (int b=0; b<nbus; b++) {
00056         Tree t = (b<nlines) ? lsig[b] : sigInt(0);
00057         for (int i=b+nbus; i<nlines; i+=nbus) {
00058             t = sigAdd(t, lsig[i]);
00059         }
00060         dst[b] = t;
00061     }
00062     return dst;
00063 }           
00064 
00066 siglist split(const siglist& inputs, int nbus)
00067 {
00068     int nlines  = inputs.size();
00069     
00070     siglist outputs(nbus);
00071     
00072     for (int b=0; b<nbus; b++) {
00073         outputs[b] = inputs[b % nlines];
00074     }
00075     return outputs;
00076 }           
00077 
00079 siglist makeSigProjList (Tree t, int n)
00080 {
00081     siglist l(n);
00082     for (int i = 0; i < n; i++) l[i] = sigDelay0(sigProj(i, t));
00083     return l;
00084 }
00085 
00087 siglist makeMemSigProjList (Tree t, int n)
00088 {
00089     siglist l(n);
00090     for (int i = 0; i < n; i++) l[i] = sigDelay1(sigProj(i, t));
00091     return l;
00092 }
00093 
00094 
00096 siglist makeSigInputList (int n)
00097 {
00098     siglist l(n);
00099     for (int i = 0; i < n; i++) l[i] = sigInput(i);
00100     return l;
00101 }
00102 
00103 inline siglist makeList(Tree t)
00104 {
00105     siglist l(1);
00106     l[0] = t;
00107     return l;
00108 }
00109 
00110 siglist listRange(const siglist& l, int i, int j)
00111 {
00112     siglist r(j-i);
00113     for (int x = i; x < j; x++) r[x-i] = l[x];
00114     return r;
00115 }
00116 
00117 siglist listConcat(const siglist& a, const siglist& b)
00118 {
00119     int n1 = a.size();
00120     int n2 = b.size();
00121     siglist r(n1+n2);
00122     
00123     for (int x=0; x<n1; x++) r[x] = a[x];
00124     for (int x=0; x<n2; x++) r[x+n1] = b[x];
00125     return r;
00126 }
00127 
00131 Tree listConvert(const siglist& a)
00132 {
00133     int     n = a.size();
00134     Tree    t=nil;
00135     while (n--) t = cons(a[n],t);
00136     return t;
00137 }
00138 
00139 // siglist listConvertBack(Tree l)
00140 // {
00141 //  siglist r;
00142 //  while (!isNil(l)) { r.push_back(hd(l)); l = tl(l); }
00143 //  return r;
00144 // }
00145 
00146 siglist listLift(const siglist& l)
00147 {
00148     int         n = l.size();
00149     siglist     r(n);
00150     
00151     for(int i = 0; i<n; i++) r[i] = lift(l[i]);
00152     return r;
00153 }
00154 
00155 static int  gDummyInput = 10000;
00156 
00166 /*
00167 // for debugging purposes
00168 
00169 siglist realpropagate (Tree slotenv, Tree path, Tree box, const siglist&  lsig);
00170 
00171 siglist propagate (Tree slotenv, Tree path, Tree box, const siglist&  lsig)
00172 {
00173     cerr << "propagate in " << boxpp(box) << endl; 
00174     for (int i=0; i<lsig.size(); i++) { cerr << " -> signal " << i << " : " << *(lsig[i]) << endl; }
00175     cerr << endl;
00176     return realpropagate (slotenv, path, box, lsig);
00177 }
00178 */
00179 
00183 //siglist propagate (Tree slotenv, Tree path, Tree box, const siglist&  lsig)
00184 //{
00185 //  siglist S = realPropagate(slotenv, path, box, lsig);
00186 //
00187 //  if (gPrintDocSwitch) {
00188 //      Tree    id;
00189 //      if (lsig.size()==0 && getDefNameProperty(box, id)) {
00190 //          string nickname = defName2NickName(tree2str(id));
00191 //          //setSigListNickName(S, nickname);
00192 //      }
00193 //  }
00194 //
00195 //  return S;
00196 //}
00197 
00198 //siglist realPropagate (Tree slotenv, Tree path, Tree box, const siglist&  lsig)
00199 siglist propagate (Tree slotenv, Tree path, Tree box, const siglist&  lsig)
00200 {
00201     int     i;
00202     double  r;
00203     prim0   p0;
00204     prim1   p1;
00205     prim2   p2;
00206     prim3   p3;
00207     prim4   p4;
00208     prim5   p5;
00209     
00210     Tree    t1, t2, ff, label, cur, min, max, step, type, name, file, slot, body;
00211     
00212     
00213     xtended* xt = (xtended*)getUserData(box);
00214     
00215     // Extended Primitives
00216     
00217     if (xt) {
00218         assert(lsig.size() == xt->arity());
00219         return makeList(xt->computeSigOutput(lsig));
00220     }
00221         
00222     // Numbers and Constants
00223     
00224     else if (isBoxInt(box, &i))     { 
00225         assert(lsig.size()==0); 
00226         return makeList(sigInt(i)); 
00227     }
00228     else if (isBoxReal(box, &r))    { 
00229         assert(lsig.size()==0); 
00230         return makeList(sigReal(r)); 
00231     }
00232     
00233     else if (isBoxFConst(box, type, name, file))    { 
00234         assert(lsig.size()==0); 
00235         return makeList(sigFConst(type, name, file)); 
00236     }
00237     
00238     else if (isBoxFVar(box, type, name, file))    { 
00239         assert(lsig.size()==0); 
00240         return makeList(sigFVar(type, name, file)); 
00241     }
00242     
00243     // Wire and Cut
00244     
00245     else if (isBoxCut(box))                 { 
00246         assert(lsig.size()==1); 
00247         return siglist(); 
00248     }
00249     
00250     else if (isBoxWire(box))                { 
00251         assert(lsig.size()==1); 
00252         return lsig;  
00253     }
00254     
00255     // Slots and Symbolic Boxes
00256     
00257     else if (isBoxSlot(box))                { 
00258         Tree sig;
00259         assert(lsig.size()==0); 
00260         if (!searchEnv(box,sig,slotenv)) {
00261             // test YO simplification des diagrames
00262             //fprintf(stderr, "propagate : internal error (slot undefined)\n");
00263             //exit(1);
00264             sig = sigInput(++gDummyInput);
00265         }
00266         return makeList(sig);
00267     }
00268     
00269     else if (isBoxSymbolic(box, slot, body))                { 
00270         assert(lsig.size()>0); 
00271         return propagate(pushEnv(slot,lsig[0],slotenv), path, body, listRange(lsig, 1, lsig.size()));
00272     }
00273     
00274     // Primitives
00275     
00276     else if (isBoxPrim0(box, &p0))          { 
00277         assert(lsig.size()==0); 
00278         return makeList( p0() );  
00279     }
00280     
00281     else if (isBoxPrim1(box, &p1))              { 
00282         assert(lsig.size()==1); 
00283         return makeList( p1(lsig[0]) );  
00284     }
00285     
00286     else if (isBoxPrim2(box, &p2))              { 
00287 //      printf("prim2 recoit : "); print(lsig); printf("\n");
00288         assert(lsig.size()==2); 
00289         return makeList( p2(lsig[0],lsig[1]) );  
00290     }
00291     
00292     else if (isBoxPrim3(box, &p3))              { 
00293         assert(lsig.size()==3); 
00294         return makeList( p3(lsig[0],lsig[1],lsig[2]) );  
00295     }
00296     
00297     else if (isBoxPrim4(box, &p4))              { 
00298         assert(lsig.size()==4); 
00299         return makeList( p4(lsig[0],lsig[1],lsig[2],lsig[3]) );  
00300     }
00301     
00302     else if (isBoxPrim5(box, &p5))              { 
00303         assert(lsig.size()==5); 
00304         return makeList( p5(lsig[0],lsig[1],lsig[2],lsig[3],lsig[4]) );  
00305     }
00306     
00307     else if (isBoxFFun(box, ff))                { 
00308         //cerr << "propagate en boxFFun of arity " << ffarity(ff) << endl;
00309         assert(int(lsig.size())==ffarity(ff)); 
00310         return makeList(sigFFun(ff, listConvert(lsig)));  
00311     }
00312     
00313     // User Interface Widgets
00314     
00315     else if (isBoxButton(box, label))   { 
00316         assert(lsig.size()==0); 
00317         return makeList(sigButton(normalizePath(cons(label, path)))); 
00318     }
00319     
00320     else if (isBoxCheckbox(box, label))     { 
00321         assert(lsig.size()==0); 
00322         return makeList(sigCheckbox(normalizePath(cons(label, path)))); 
00323     }
00324     
00325     else if (isBoxVSlider(box, label, cur, min, max, step))     { 
00326         assert(lsig.size()==0); 
00327         return makeList(sigVSlider(normalizePath(cons(label, path)), cur, min, max, step)); 
00328     }
00329     
00330     else if (isBoxHSlider(box, label, cur, min, max, step))     { 
00331         assert(lsig.size()==0); 
00332         return makeList(sigHSlider(normalizePath(cons(label, path)), cur, min, max, step)); 
00333     }
00334     
00335     else if (isBoxNumEntry(box, label, cur, min, max, step))    { 
00336         assert(lsig.size()==0); 
00337         return makeList(sigNumEntry(normalizePath(cons(label, path)), cur, min, max, step)); 
00338     }
00339     
00340     else if (isBoxVBargraph(box, label, min, max))  { 
00341         assert(lsig.size()==1); 
00342         return makeList(sigVBargraph(normalizePath(cons(label, path)), min, max, lsig[0])); 
00343     }
00344     
00345     else if (isBoxHBargraph(box, label, min, max))  { 
00346         assert(lsig.size()==1); 
00347         return makeList(sigHBargraph(normalizePath(cons(label, path)), min, max, lsig[0])); 
00348     }
00349     
00350     // User Interface Groups
00351     
00352     else if (isBoxVGroup(box, label, t1))   { 
00353         return propagate(slotenv,cons(cons(tree(0),label), path), t1, lsig); 
00354     }
00355     
00356     else if (isBoxHGroup(box, label, t1))   { 
00357         return propagate(slotenv, cons(cons(tree(1),label), path), t1, lsig); 
00358     }
00359     
00360     else if (isBoxTGroup(box, label, t1))   { 
00361         return propagate(slotenv, cons(cons(tree(2),label), path), t1, lsig); 
00362     }
00363     
00364     // Block Diagram Composition Algebra
00365     
00366     else if (isBoxSeq(box, t1, t2))     { 
00367         int in1, out1, in2, out2;
00368         getBoxType(t1, &in1, &out1);
00369         getBoxType(t2, &in2, &out2);
00370 
00371         assert(out1==in2);
00372 
00373         if (out1 == in2) {
00374             return propagate(slotenv, path, t2, propagate(slotenv, path,t1,lsig));
00375         } else if (out1 > in2) {
00376             siglist lr = propagate(slotenv, path, t1,lsig);
00377             return listConcat(propagate(slotenv, path, t2, listRange(lr, 0, in2)), listRange(lr, in2, out1));
00378         } else {
00379             return propagate(slotenv, path, t2, listConcat( propagate(slotenv, path, t1, listRange(lsig,0,in1)), listRange(lsig,in1,in1+in2-out1) ) );
00380         }
00381     }
00382     
00383     else if (isBoxPar(box, t1, t2))     { 
00384         int in1, out1, in2, out2;
00385         getBoxType(t1, &in1, &out1);
00386         getBoxType(t2, &in2, &out2);
00387             
00388         return listConcat(  propagate(slotenv, path, t1, listRange(lsig, 0,  in1)), 
00389                             propagate(slotenv, path, t2, listRange(lsig, in1, in1+in2)) );
00390     }
00391     
00392     else if (isBoxSplit(box, t1, t2))   { 
00393         int in1, out1, in2, out2;
00394         getBoxType(t1, &in1, &out1);
00395         getBoxType(t2, &in2, &out2);
00396         
00397         siglist l1 = propagate(slotenv, path, t1, lsig);
00398         siglist l2 = split(l1, in2);
00399         return propagate(slotenv, path, t2, l2);
00400     }
00401     
00402     else if (isBoxMerge(box, t1, t2))   { 
00403         int in1, out1, in2, out2;
00404         getBoxType(t1, &in1, &out1);
00405         getBoxType(t2, &in2, &out2);
00406         
00407         siglist l1 = propagate(slotenv, path, t1, lsig);
00408         siglist l2 = mix(l1, in2);
00409         return propagate(slotenv, path, t2, l2);
00410     }
00411 /*  
00412     else if (isBoxRec(box, t1, t2))     { 
00413         int in1, out1, in2, out2;
00414         getBoxType(t1, &in1, &out1);
00415         getBoxType(t2, &in2, &out2);
00416         
00417         siglist l0 = makeSigProjList(ref(1), in2);
00418         siglist l1 = propagate(slotenv, path, t2, l0);
00419         siglist l2 = propagate(slotenv, path, t1, listConcat(l1,listLift(lsig)));
00420         Tree g = rec(listConvert(l2));
00421         return makeSigProjList(g, out1);
00422     }
00423 */  
00424     else if (isBoxRec(box, t1, t2))     {
00425         // Bug Corrected
00426         int in1, out1, in2, out2;
00427         getBoxType(t1, &in1, &out1);
00428         getBoxType(t2, &in2, &out2);
00429 
00430         Tree slotenv2 = lift(slotenv); // the environment must also be lifted
00431 
00432         siglist l0 = makeMemSigProjList(ref(1), in2);
00433         siglist l1 = propagate(slotenv2, path, t2, l0);
00434         siglist l2 = propagate(slotenv2, path, t1, listConcat(l1,listLift(lsig)));
00435         Tree g = rec(listConvert(l2));
00436         return makeSigProjList(g, out1);
00437     }
00438 
00439     cout << "ERROR in file " << __FILE__ << ':' << __LINE__ << ", unrecognised box expression : " << boxpp(box) << endl;
00440     exit(1);
00441     return siglist();
00442 }
00443 
00444     
00445 Tree boxPropagateSig (Tree path, Tree box, const siglist& lsig)
00446 {
00447     return listConvert(propagate(nil, path, box, lsig));
00448 }
00449