FAUST compiler  0.9.9.6b8
recursivness.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 #include <assert.h>
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <limits.h>
00025 #include "recursivness.hh"
00026 #include "property.hh"
00027 
00028 #include "signals.hh"
00029 #include "ppsig.hh"
00030 #include "set"
00031 
00032 using namespace std;
00033 
00034 
00046 //--------------------------------------------------------------------------
00047 static int annotate(Tree env, Tree sig);
00048 static int position (Tree env, Tree t, int p=1);
00049 
00050 Tree RECURSIVNESS = tree(symbol("RecursivnessProp"));
00051 //--------------------------------------------------------------------------
00052 
00053 
00059 void recursivnessAnnotation(Tree sig)
00060 {
00061     annotate(nil, sig);
00062 }
00063 
00064 
00072 int getRecursivness(Tree sig)
00073 {
00074     Tree tr;
00075     if ( ! getProperty(sig, RECURSIVNESS, tr)) {
00076         cerr << "Error in getRecursivness of " << *sig << endl;
00077         exit(1);
00078     }
00079     return tree2int(tr);
00080 }
00081 
00082 //-------------------------------------- IMPLEMENTATION ------------------------------------
00089 static int annotate(Tree env, Tree sig)
00090 {
00091     Tree tr, var, body;
00092 
00093     if (getProperty(sig, RECURSIVNESS, tr)) {
00094         return tree2int(tr);    // already annotated
00095     } else if (isRec(sig, var, body)) {
00096         int p = position(env, sig);
00097         if (p > 0) {
00098             return p;   // we are inside \x.(...)
00099         } else {
00100             int r = annotate(cons(sig, env), body) - 1;
00101             if (r<0) r=0;
00102             setProperty(sig, RECURSIVNESS, tree(r));
00103             return r;
00104         }
00105     } else {
00106         int rmax = 0;
00107         vector<Tree> v; getSubSignals(sig, v);
00108         for (unsigned int i=0; i<v.size(); i++) {
00109             int r = annotate(env, v[i]);
00110             if (r>rmax) rmax=r;
00111         }
00112         setProperty(sig, RECURSIVNESS, tree(rmax));
00113         return rmax;
00114     }
00115 }
00116 
00117 
00118 
00125 static int position (Tree env, Tree t, int p)
00126 {
00127     if (isNil(env)) return 0;   // was not in the environment
00128     if (hd(env) == t) return p;
00129     else return position (tl(env), t, p+1);
00130 }
00131 
00132 
00133 //-----------------------------------list recursive symbols-----------------------
00134 
00135 
00136 
00143 // the property used to memoize the results
00144 property<Tree>  SymListProp;
00145 
00146 Tree    symlistVisit(Tree sig, set<Tree>& visited)
00147 {
00148     Tree S;
00149     if (SymListProp.get(sig, S)) {
00150         return S;
00151     } else if ( visited.count(sig) > 0 ){
00152         return nil;
00153     } else {
00154         visited.insert(sig);
00155         Tree id, body;
00156         if (isRec(sig, id, body)) {
00157             Tree U = singleton(sig);
00158             for (int i=0; i<len(body); i++) {
00159                 U = setUnion(U, symlistVisit(nth(body,i), visited));
00160             }
00161             return U;
00162         } else {
00163             vector<Tree> subsigs;
00164             int n = getSubSignals(sig, subsigs, true); // il faut visiter aussi les tables
00165             Tree U = nil;
00166             for (int i=0; i<n; i++) {
00167                 U = setUnion(U, symlistVisit(subsigs[i], visited));
00168             }
00169             return U;
00170         }
00171     }
00172 }
00173 
00174 Tree    symlist(Tree sig)
00175 {
00176     Tree    S;
00177     if (!SymListProp.get(sig, S)) {
00178         set<Tree> visited;
00179         S = symlistVisit(sig, visited);
00180         SymListProp.set(sig, S);
00181     }
00182     //cerr << "SYMLIST " << *S << " OF " << ppsig(sig) << endl;
00183     return S;
00184 }