FAUST compiler  0.9.9.6b8
simplify.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 <stdio.h>
00025 #include <assert.h>
00026 #include "list.hh"
00027 #include "signals.hh"
00028 #include "sigtype.hh"
00029 #include "recursivness.hh"
00030 #include "sigtyperules.hh"
00031 #include "sigorderrules.hh"
00032 #include "sigprint.hh"
00033 #include "ppsig.hh"
00034 #include "simplify.hh"
00035 #include "num.hh"
00036 #include "xtended.hh"
00037 #include <map>
00038 #include "compatibility.hh"
00039 
00040 #include "normalize.hh"
00041 
00042 #undef TRACE
00043 
00044 // declarations
00045 Tree SIMPLIFIED = tree(symbol("sigSimplifiedProp"));
00046 //static Tree binequiv (Tree sig, int opnum, Tree a, Tree b);
00047 static Tree simplification (Tree sig);
00048 static Tree sigMap (Tree key, tfun f, Tree t);
00049 
00050 static Tree traced_simplification(Tree sig)
00051 {
00052     assert(sig);
00053 #ifdef TRACE
00054     cerr << ++TABBER << "Start simplification of : " << ppsig(sig) << endl;
00055     /*
00056     fprintf(stderr, "\nStart simplification of : ");
00057     printSignal(sig, stderr);
00058     fprintf(stderr, "\n");
00059     */
00060 #endif
00061     Tree r = simplification(sig);
00062     assert(r!=0);
00063 #ifdef TRACE
00064     cerr << --TABBER << "Simplification of : " << ppsig(sig) << " Returns : " << ppsig(r) << endl;
00065     /*
00066     fprintf(stderr, "Simplification of : ");
00067     printSignal(sig, stderr);
00068     fprintf(stderr, " -> ");
00069     printSignal(r, stderr);
00070     fprintf(stderr, "\n");
00071     */
00072 #endif
00073     return r;
00074 }
00075 
00076 Tree simplify (Tree sig)
00077 {
00078     return sigMap(SIMPLIFIED, traced_simplification, sig);
00079 }
00080 
00081 
00082 // Implementation
00083 
00084 static Tree simplification (Tree sig)
00085 {
00086     assert(sig);
00087     int     opnum;
00088     Tree    t1, t2, t3, t4;
00089 
00090     xtended* xt = (xtended*) getUserData(sig);
00091     // primitive elements
00092     if (xt)
00093     {
00094         //return 3;
00095         vector<Tree> args;
00096         for (int i=0; i<sig->arity(); i++) { args.push_back( sig->branch(i) ); }
00097 
00098         // to avoid negative power to further normalization
00099         if (xt != gPowPrim) {
00100             return xt->computeSigOutput(args);
00101         } else {
00102             return normalizeAddTerm(xt->computeSigOutput(args));
00103         }
00104 
00105     } else if (isSigBinOp(sig, &opnum, t1, t2)) {
00106 
00107         BinOp* op = gBinOpTable[opnum];
00108 
00109         Node n1 = t1->node();
00110         Node n2 = t2->node();
00111 
00112         if (isNum(n1) && isNum(n2))         return tree(op->compute(n1,n2));
00113 
00114         else if (op->isLeftNeutral(n1))     return t2;
00115 
00116         else if (op->isRightNeutral(n2))    return t1;
00117 
00118         else                                return normalizeAddTerm(sig);
00119 
00120     } else if (isSigDelay1(sig, t1)) {
00121 
00122         return normalizeDelay1Term (t1);
00123 
00124     } else if (isSigFixDelay(sig, t1, t2)) {
00125 
00126         return normalizeFixedDelayTerm (t1, t2);
00127 
00128     } else if (isSigIntCast(sig, t1)) {
00129 
00130         Tree    tx;
00131         int     i;
00132         double  x;
00133         Node    n1 = t1->node();
00134 
00135         if (isInt(n1, &i))          return t1;
00136         if (isDouble(n1, &x))       return tree(int(x));
00137         if (isSigIntCast(t1, tx))   return t1;
00138 
00139         return sig;
00140 
00141     } else if (isSigFloatCast(sig, t1)) {
00142 
00143         Tree    tx;
00144         int     i;
00145         double  x;
00146         Node    n1 = t1->node();
00147 
00148         if (isInt(n1, &i))              return tree(double(i));
00149         if (isDouble(n1, &x))           return t1;
00150         if (isSigFloatCast(t1, tx))     return t1;
00151 
00152         return sig;
00153 
00154      } else if (isSigSelect2(sig, t1, t2, t3)){
00155 
00156         Node n1 = t1->node();
00157 
00158         if (isZero(n1)) return t2;
00159         if (isNum(n1))  return t3;
00160 
00161         if (t2==t3) return t2;
00162 
00163         return sig;
00164 
00165     } else if (isSigSelect3(sig, t1, t2, t3, t4)){
00166 
00167         Node n1 = t1->node();
00168 
00169         if (isZero(n1)) return t2;
00170         if (isOne(n1))  return t3;
00171         if (isNum(n1))  return t4;
00172 
00173         if (t3==t4) return simplification(sigSelect2(t1,t2,t3));
00174 
00175         return sig;
00176 
00177     } else {
00178 
00179         return sig;
00180     }
00181 }
00182 
00187 static Tree sigMap (Tree key, tfun f, Tree t)
00188 {
00189     //printf("start sigMap\n");
00190     Tree p,id,body;
00191 
00192     if (getProperty(t, key, p)) {
00193 
00194         return (isNil(p)) ? t : p;  // truc pour eviter les boucles
00195 
00196     } else if (isRec(t, id, body)) {
00197 
00198         setProperty(t, key, nil);   // avoid infinite loop
00199         return rec(id, sigMap(key, f, body));
00200 
00201     } else {
00202 
00203         Tree r1=nil;
00204         switch (t->arity()) {
00205 
00206             case 0 :
00207                 r1 = t;
00208                 break;
00209             case 1 :
00210                 r1 = tree(t->node(), sigMap(key,f,t->branch(0)));
00211                 break;
00212             case 2 :
00213                 r1 = tree(t->node(), sigMap(key,f,t->branch(0)), sigMap(key,f,t->branch(1)));
00214                 break;
00215             case 3 :
00216                 r1 = tree(t->node(), sigMap(key,f,t->branch(0)), sigMap(key,f,t->branch(1)),
00217                                            sigMap(key,f,t->branch(2)));
00218                 break;
00219             case 4 :
00220                 r1 = tree(t->node(), sigMap(key,f,t->branch(0)), sigMap(key,f,t->branch(1)),
00221                                            sigMap(key,f,t->branch(2)), sigMap(key,f,t->branch(3)));
00222                 break;
00223         }
00224         Tree r2 = f(r1);
00225         if (r2 == t) {
00226             setProperty(t, key, nil);
00227         } else {
00228             setProperty(t, key, r2);
00229         }
00230         return r2;
00231     }
00232 }
00233 
00234 
00235 
00236 
00237 
00243 static Tree sigMapRename (Tree key, Tree env, tfun f, Tree t)
00244 {
00245     //printf("start sigMap\n");
00246     Tree p,id,body;
00247 
00248     if (getProperty(t, key, p)) {
00249 
00250         return (isNil(p)) ? t : p;  // truc pour eviter les boucles
00251 
00252     } else if (isRec(t, id, body)) {
00253 
00254         assert(isRef(t,id)); // controle temporaire
00255 
00256         Tree id2;
00257         if (searchEnv(id, id2, env)) {
00258             // déjà en cours de visite de cette recursion
00259             return ref(id2);
00260         } else {
00261             // premiere visite de cette recursion
00262             id2 = tree(Node(unique("renamed")));
00263             Tree body2 = sigMapRename(key, pushEnv(id, id2, env), f, body);
00264             return rec(id2,body2);
00265         }
00266 
00267     } else {
00268 
00269         Tree r1=nil;
00270         switch (t->arity()) {
00271 
00272             case 0 :
00273                 r1 = t;
00274                 break;
00275             case 1 :
00276                 r1 = tree(t->node(),    sigMapRename(key,env,f,t->branch(0)));
00277                 break;
00278             case 2 :
00279                 r1 = tree(t->node(),    sigMapRename(key,env,f,t->branch(0)),
00280                                         sigMapRename(key,env,f,t->branch(1)));
00281                 break;
00282             case 3 :
00283                 r1 = tree(t->node(),    sigMapRename(key,env,f,t->branch(0)),
00284                                         sigMapRename(key,env,f,t->branch(1)),
00285                                         sigMapRename(key,env,f,t->branch(2)));
00286                 break;
00287             case 4 :
00288                 r1 = tree(t->node(),    sigMapRename(key,env,f,t->branch(0)),
00289                                         sigMapRename(key,env,f,t->branch(1)),
00290                                         sigMapRename(key,env,f,t->branch(2)),
00291                                         sigMapRename(key,env,f,t->branch(3)));
00292                 break;
00293         }
00294         Tree r2 = f(r1);
00295         if (r2 == t) {
00296             setProperty(t, key, nil);
00297         } else {
00298             setProperty(t, key, r2);
00299         }
00300         return r2;
00301     }
00302 }
00303 
00304 #if 0
00305 static void eraseProperties (Tree key, Tree t)
00306 {
00307     //printf("start sigMap\n");
00308     Tree p,id,body;
00309 
00310     if (getProperty(t, key, p)) {
00311         // already erased, nothing to do
00312 
00313     } else if (isRec(t, id, body)) {
00314         t->clearProperties();
00315         Tree r=rec(id, body);
00316         assert(r==t);
00317         setProperty(t, key, nil);   // avoid infinite loop
00318         eraseProperties(key, body);
00319 
00320     } else {
00321 
00322         for (int i=0; i<t->arity(); i++) {
00323             eraseProperties(key,t->branch(i));
00324         }
00325     }
00326 }
00327 
00328 void eraseAllProperties(Tree t)
00329 {
00330     cerr << "begin eraseAllProperties" << endl;
00331     eraseProperties(tree(Node(unique("erase_"))), t);
00332     cerr << "end eraseAllProperties" << endl;
00333 }
00334 #endif
00335 
00341 Tree DOCTABLES = tree(symbol("DocTablesProp"));
00342 
00343 static Tree docTableConverter (Tree sig);
00344 
00345 static Tree NULLENV = tree(symbol("NullRenameEnv"));
00346 
00347 Tree docTableConvertion (Tree sig)
00348 {
00349     Tree r  = sigMapRename(DOCTABLES, NULLENV, docTableConverter, sig);
00350     return r;
00351 }
00352 
00353 
00354 // Implementation
00355 
00356 static Tree docTableConverter (Tree sig)
00357 {
00358     Tree tbl, tbl2, id, id2, size, igen, isig, ridx, widx, wsig;
00359 
00360     if (isSigRDTbl(sig, tbl, ridx)) {
00361         // we are in a table to convert
00362         if (isSigTable(tbl, id, size, igen)) {
00363             // it's a read only table
00364             assert(isSigGen(igen, isig));
00365             return sigDocAccessTbl(sigDocConstantTbl(size,isig),ridx);
00366         } else {
00367             // it's a read write table
00368             assert(isSigWRTbl(tbl,id,tbl2,widx,wsig));
00369             assert(isSigTable(tbl2, id2, size, igen));
00370             assert(isSigGen(igen, isig));
00371 
00372             return sigDocAccessTbl(sigDocWriteTbl(size,isig,widx,wsig),ridx);
00373         }
00374 
00375     } else {
00376         // nothing to convert
00377         return sig;
00378     }
00379 }