FAUST compiler  0.9.9.6b8
recursive-tree.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 <assert.h>
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <limits.h>
00028 #include "tlib.hh"
00029 
00030 // Declaration of implementation
00031 static Tree calcDeBruijn2Sym (Tree t);
00032 static Tree substitute(Tree t, int n, Tree id);
00033 static Tree calcsubstitute(Tree t, int level, Tree id);
00034 static Tree liftn(Tree t, int threshold);
00035 static Tree calcliftn(Tree t, int threshold);
00036 
00037 // recursive trees
00038 
00039 Sym     DEBRUIJN    = symbol ("DEBRUIJN");
00040 Sym     DEBRUIJNREF = symbol ("DEBRUIJNREF");
00041 Sym     SUBSTITUTE  = symbol ("SUBSTITUTE");
00042 
00043 Sym     SYMREC      = symbol ("SYMREC");
00044 Sym     SYMRECREF   = symbol ("SYMRECREF");
00045 Sym     SYMLIFTN    = symbol ("LIFTN");
00046 
00047 //Tree  NOVAR       = tree("NOVAR");
00048 
00049 //-----------------------------------------------------------------------------------------
00050 // rec, isRec : declare recursive trees
00051 //-----------------------------------------------------------------------------------------
00052 
00053 // de Bruijn declaration of a recursive tree
00054 Tree rec(Tree body)
00055 {
00056     return tree(DEBRUIJN, body);
00057 }
00058 
00059 bool isRec(Tree t, Tree& body)
00060 {
00061     return isTree(t, DEBRUIJN, body);
00062 }
00063 
00064 Tree ref(int level)
00065 {
00066     assert(level > 0);
00067     return tree(DEBRUIJNREF, tree(level));  // reference to enclosing recursive tree starting from 1
00068 }
00069 
00070 bool isRef(Tree t, int& level)
00071 {
00072     Tree    u;
00073 
00074     if (isTree(t, DEBRUIJNREF, u)) {
00075         return isInt(u->node(), &level);
00076     } else {
00077         return false;
00078     }
00079 }
00080 
00081 
00082 //-----------------------------------------------------------------------------------------
00083 // Recursive tree in symbolic notation (using a recursive definition property)
00084 //-----------------------------------------------------------------------------------------
00085 Tree RECDEF = tree(symbol("RECDEF"));
00086 
00087 // declaration of a recursive tree using a symbolic variable
00088 Tree rec(Tree var, Tree body)
00089 {
00090     Tree t = tree(SYMREC, var);
00091     t->setProperty(RECDEF, body);
00092     return t;
00093 }
00094 
00095 bool isRec(Tree t, Tree& var, Tree& body)
00096 {
00097     if (isTree(t, SYMREC, var)) {
00098         body = t->getProperty(RECDEF);
00099         return true;
00100     } else {
00101         return false;
00102     }
00103 }
00104 
00105 
00106 Tree ref(Tree id)
00107 {
00108     return tree(SYMREC, id);            // reference to a symbolic id
00109 }
00110 
00111 bool isRef(Tree t, Tree& v)
00112 {
00113     return isTree(t, SYMREC, v);
00114 }
00115 
00116 //-----------------------------------------------------------------------------------------
00117 // L'aperture d'un arbre est la plus profonde reference de Bruijn qu'il contienne.
00118 // Les references symboliques compte pour zero ce qui veut dire qu'un arbre d'aperture
00119 // 0 ne compte aucun reference de bruijn libres.
00120 
00121 int CTree::calcTreeAperture( const Node& n, const tvec& br  )
00122 {
00123     int x;
00124     if (n == DEBRUIJNREF) {
00125 
00126         if (isInt(br[0]->node(), &x)) {
00127             return x;
00128         } else {
00129             return 0;
00130         }
00131 
00132     } else if (n == DEBRUIJN) {
00133 
00134         return br[0]->fAperture - 1;
00135 
00136     } else {
00137         // return max aperture of branches
00138         int rc = 0;
00139         tvec::const_iterator    b = br.begin();
00140         tvec::const_iterator    z = br.end();
00141         while (b != z) {
00142             if ((*b)->aperture() > rc) rc = (*b)->aperture();
00143             ++b;
00144         }
00145         return rc;
00146     }
00147 }
00148 
00149 Tree lift(Tree t) { return liftn(t, 1); }
00150 
00151 void printSignal(Tree sig, FILE* out, int prec=0);
00152 
00153 // lift (t) : increase free references by 1
00154 
00155 #if 0
00156 static Tree _liftn(Tree t, int threshold);
00157 
00158 static Tree liftn(Tree t, int threshold)
00159 {
00160     fprintf(stderr, "call of liftn("); printSignal(t, stderr); fprintf(stderr, ", %d)\n", threshold);
00161     Tree r = _liftn(t, threshold);
00162     fprintf(stderr, "return of liftn("); printSignal(t, stderr); fprintf(stderr, ", %d) -> ", threshold);
00163     printSignal(r, stderr); fprintf(stderr, "\n");
00164     return r;
00165 }
00166 #endif
00167 
00168 
00169 static Tree liftn(Tree t, int threshold)
00170 {
00171     Tree L  = tree( Node(SYMLIFTN), tree(Node(threshold)) );
00172     Tree t2 = t->getProperty(L);
00173 
00174     if (!t2) {
00175         t2 = calcliftn(t, threshold);
00176         t->setProperty(L, t2);
00177     }
00178     return t2;
00179     
00180 }
00181 
00182 static Tree calcliftn(Tree t, int threshold)
00183 {
00184     int     n;
00185     Tree    u;
00186 
00187     if (isClosed(t)) {
00188 
00189         return t;
00190 
00191     } else if (isRef(t,n)) {
00192 
00193         if (n < threshold) {
00194             // it is a bounded reference
00195             return t;
00196         } else {
00197             // it is a free reference
00198             return ref(n+1);
00199         }
00200 
00201     } else if (isRec(t,u)) {
00202 
00203         return rec(liftn(u, threshold+1));
00204 
00205     } else {
00206         int n = t->arity();
00207         //Tree  br[4];
00208         tvec    br(n);
00209         for (int i = 0; i < n; i++) {
00210             br[i] = liftn(t->branch(i), threshold);
00211         }
00212         //return CTree::make(t->node(), n, br);
00213         return CTree::make(t->node(), br);
00214     }
00215 
00216 }
00217 
00218 //-----------------------------------------------------------
00219 // Transform a tree from deBruijn to symbolic representation
00220 //-----------------------------------------------------------
00221 Tree DEBRUIJN2SYM = tree(symbol("deBruijn2Sym"));
00222 
00223 Tree deBruijn2Sym (Tree t)
00224 {
00225     assert(isClosed(t));
00226     Tree t2 = t->getProperty(DEBRUIJN2SYM);
00227 
00228     if (!t2) {
00229         t2 = calcDeBruijn2Sym(t);
00230         t->setProperty(DEBRUIJN2SYM, t2);
00231     }
00232     return t2;
00233 }
00234 
00235 static Tree calcDeBruijn2Sym (Tree t)
00236 {
00237     Tree    body, var;
00238     int     i;
00239 
00240     if (isRec(t,body)) {
00241 
00242         var = tree(unique("W"));
00243         return rec(var, deBruijn2Sym(substitute(body,1,ref(var))));
00244 
00245     } else if (isRef(t,var)) {
00246 
00247         return t;
00248 
00249     } else if (isRef(t,i)) {
00250 
00251         fprintf(stderr, "ERREUR, une reference de Bruijn touvee ! : ");
00252         printSignal(t, stderr);
00253         fprintf(stderr, ")\n");
00254         exit(1);
00255         return t;
00256 
00257     } else {
00258 
00259         //Tree  br[4];
00260         int     a = t->arity();
00261         tvec    br(a);
00262 
00263         for (int i = 0; i < a; i++) {
00264             br[i] = deBruijn2Sym(t->branch(i));
00265         }
00266         //return CTree::make(t->node(), a, br);
00267         return CTree::make(t->node(), br);
00268     }
00269 }
00270 
00271 static Tree substitute(Tree t, int level, Tree id)
00272 {
00273     Tree S  = tree( Node(SUBSTITUTE), tree(Node(level)), id );
00274     Tree t2 = t->getProperty(S);
00275 
00276     if (!t2) {
00277         t2 = calcsubstitute(t, level, id);
00278         t->setProperty(S, t2);
00279     }
00280     return t2;
00281     
00282 }
00283 
00284 static Tree calcsubstitute(Tree t, int level, Tree id)
00285 {
00286     int     l;
00287     Tree    body;
00288 
00289     if (t->aperture()<level) {
00290 //      fprintf(stderr, "aperture %d < level %d !!\n", t->aperture(), level);
00291         return t;
00292     }
00293     if (isRef(t,l))          return (l == level) ? id : t;
00294     if (isRec(t,body))       return rec(substitute(body, level+1, id));
00295 
00296     int     ar = t->arity();
00297     //Tree  br[4];
00298     tvec    br(ar);
00299     for (int i = 0; i < ar; i++) {
00300         br[i] = substitute(t->branch(i), level, id);
00301     }
00302     //return CTree::make(t->node(), ar, br);
00303     return CTree::make(t->node(), br);
00304 }
00305 
00306 
00307 //--------------------------------------------------------------------------
00308 // UpdateAperture (t) : recursively mark open and closed terms.
00309 // closed term : fAperture == 0,  open term fAperture == -1
00310 
00311 struct Env {
00312     Tree fTree; Env* fNext;
00313     Env(Tree t, Env* nxt) : fTree(t), fNext(nxt) {}
00314 };
00315 
00316 static void markOpen(Tree t);
00317 static int recomputeAperture(Tree t, Env* p);
00318 static int orderof (Tree t, Env* p);
00319 
00320 void updateAperture(Tree t)
00321 {
00322     markOpen(t);
00323     recomputeAperture(t, NULL);
00324 }
00325 
00326 //----------------------implementation--------------------------------
00327 
00328 static void markOpen(Tree t)
00329 {
00330     if (t->aperture() == INT_MAX) return;
00331     t->setAperture(INT_MAX);
00332     int ar = t->arity();
00333     for (int i = 0; i < ar; i++) {
00334         markOpen(t->branch(i));
00335     }
00336 }
00337 
00338 static int recomputeAperture(Tree t, Env* env)
00339 {
00340     Tree    var, body;
00341 
00342     if (t->aperture() == 0) return 0;
00343 
00344     if (isRef(t, var)) {
00345 
00346         return orderof(var, env);
00347 
00348     } else if (isRec(t, var, body)) {
00349 
00350         Env e(var,env);
00351         int a = recomputeAperture(body, &e) - 1;
00352         if (a<=0) { /*print(t, stderr);*/ t->setAperture(0); }
00353         return a;
00354 
00355     } else {
00356         // return max aperture of branches
00357         int ma = 0;
00358         int ar = t->arity();
00359         for (int i = 0; i<ar; i++) {
00360             int a = recomputeAperture(t->branch(i), env);
00361             if (ma < a) ma = a;
00362         }
00363         if (ma <= 0)  { /*print(t, stderr);*/ t->setAperture(0); }
00364         return ma;
00365     }
00366 }
00367 
00368 
00369 static int orderof (Tree t, Env* p)
00370 {
00371     if (p == NULL) return 0;
00372     if (t == p->fTree) return 1;
00373 
00374     int pos = 1;
00375     while (p != NULL) {
00376         if (t == p->fTree) return pos;
00377         p = p->fNext;
00378         pos++;
00379     }
00380     return 0;
00381 }