|
FAUST compiler
0.9.9.6b8
|
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 /***************************************************************************** 00025 ****************************************************************************** 00026 TREE 00027 Y. Orlarey, (c) Grame 2002 00028 ------------------------------------------------------------------------------ 00029 Trees are made of a Node associated with a list of branches : (Node x [CTree]). 00030 Up to 4 branches are allowed in this implementation. A hash table is used to 00031 maximize the sharing of trees during construction : trees at different 00032 addresses always have a different content. Reference counting is used for 00033 garbage collection, and smart pointers P<CTree> should be used for permanent 00034 storage of trees. 00035 00036 API: 00037 ---- 00038 tree (n) : tree of node n with no branch 00039 tree (n, t1) : tree of node n with a branch t 00040 tree (n, t1,...,tm) : tree of node n with m branches t1,...,tm 00041 00042 Pattern matching : 00043 00044 if (isTree (t, n)) ... : t has node n and no branches; 00045 if (isTree (t, n, &t1) ... : t has node n and 1 branch, t1 is set accordingly; 00046 if (isTree (t, n, &t1...&tm)...: t has node n and m branches, ti's are set accordingly; 00047 00048 Accessors : 00049 00050 t->node() : the node of t { return fNode; } 00051 t->arity() : the number of branches of t return fArity; } 00052 t->branch(i) : the ith branch of t 00053 00054 Attributs : 00055 00056 t->attribut() : return the attribut (also a tree) of t 00057 t->attribut(t') : set the attribut of t to t' 00058 00059 Warning : 00060 --------- 00061 Since reference counters are used for garbage collecting, one must be careful not to 00062 create cycles in trees The only possible source of cycles is by setting the attribut 00063 of a tree t to a tree t' that contains t as a subtree. 00064 00065 Properties: 00066 ----------- 00067 If p and q are two CTree pointers : 00068 p != q <=> *p != *q 00069 00070 History : 00071 --------- 00072 2002-02-08 : First version 00073 2002-10-14 : counts for height and recursiveness added 00074 00075 ****************************************************************************** 00076 *****************************************************************************/ 00077 00078 #include <stdlib.h> 00079 #include <stdio.h> 00080 #include <string.h> 00081 #include <limits.h> 00082 #include "tree.hh" 00083 #include <fstream> 00084 #include <cstdlib> 00085 00086 Tabber TABBER(1); 00087 extern Tabber TABBER; 00088 00089 00090 static void error(const char * s, Tree t) 00091 { 00092 //fprintf(stderr, "ERROR : %s (%p)\n", s, t); 00093 cerr << "ERROR : " << s << " : " << *t << endl; 00094 } 00095 00096 #define ERROR(s,t) { error(s,t); exit(1); } 00097 00098 00099 Tree CTree::gHashTable[kHashTableSize]; 00100 bool CTree::gDetails = false; 00101 unsigned int CTree::gVisitTime = 0; 00102 00103 // Constructor : add the tree to the hash table 00104 CTree::CTree (unsigned int hk, const Node& n, const tvec& br) 00105 : fNode(n), 00106 fType(0), 00107 fHashKey(hk), 00108 fAperture(calcTreeAperture(n,br)), 00109 fVisitTime(0), 00110 fBranch(br) 00111 { 00112 // link dans la hash table 00113 int j = hk % kHashTableSize; 00114 fNext = gHashTable[j]; 00115 gHashTable[j] = this; 00116 00117 } 00118 00119 // Destructor : remove the tree form the hash table 00120 CTree::~CTree () 00121 { 00122 int i = fHashKey % kHashTableSize; 00123 Tree t = gHashTable[i]; 00124 00125 //printf("Delete of "); this->print(); printf("\n"); 00126 if (t == this) { 00127 gHashTable[i] = fNext; 00128 } else { 00129 Tree p; 00130 while (t != this) { 00131 p = t; 00132 t = t->fNext; 00133 } 00134 p->fNext = fNext; 00135 } 00136 } 00137 00138 // equivalence 00139 bool CTree::equiv (const Node& n, const tvec& br) const 00140 { 00141 return (fNode == n) && (fBranch == br); 00142 } 00143 00144 Sym PROCESS = symbol("process"); 00145 00146 00147 00148 00149 unsigned int CTree::calcTreeHash( const Node& n, const tvec& br ) 00150 { 00151 unsigned int hk = n.type() ^ n.getInt(); 00152 tvec::const_iterator b = br.begin(); 00153 tvec::const_iterator z = br.end(); 00154 00155 while (b != z) { 00156 hk = (hk << 1) ^ (hk >> 20) ^ ((*b)->fHashKey); 00157 ++b; 00158 } 00159 return hk; 00160 } 00161 00162 00163 Tree CTree::make(const Node& n, int ar, Tree* tbl) 00164 { 00165 tvec br(ar); 00166 00167 for (int i=0; i<ar; i++) br[i] = tbl[i]; 00168 00169 unsigned int hk = calcTreeHash(n, br); 00170 Tree t = gHashTable[hk % kHashTableSize]; 00171 00172 while (t && !t->equiv(n, br)) { 00173 t = t->fNext; 00174 } 00175 return (t) ? t : new CTree(hk, n, br); 00176 } 00177 00178 00179 Tree CTree::make(const Node& n, const tvec& br) 00180 { 00181 unsigned int hk = calcTreeHash(n, br); 00182 Tree t = gHashTable[hk % kHashTableSize]; 00183 00184 while (t && !t->equiv(n, br)) { 00185 t = t->fNext; 00186 } 00187 return (t) ? t : new CTree(hk, n, br); 00188 } 00189 00190 ostream& CTree::print (ostream& fout) const 00191 { 00192 if (gDetails) { 00193 // print the adresse of the tree 00194 fout << "<" << this << ">@"; 00195 } 00196 fout << node(); 00197 int a = arity(); 00198 if (a > 0) { 00199 int i; char sep; 00200 for (sep = '[', i = 0; i < a; sep = ',', i++) { 00201 fout << sep; branch(i)->print(fout); 00202 } 00203 fout << ']'; 00204 } 00205 00206 return fout; 00207 } 00208 00209 00210 void CTree::control () 00211 { 00212 printf("\ngHashTable Content :\n\n"); 00213 for (int i = 0; i < kHashTableSize; i++) { 00214 Tree t = gHashTable[i]; 00215 if (t) { 00216 printf ("%4d = ", i); 00217 while (t) { 00218 /*t->print();*/ 00219 printf(" => "); 00220 t = t->fNext; 00221 } 00222 printf("VOID\n"); 00223 } 00224 } 00225 printf("\nEnd gHashTable\n"); 00226 00227 } 00228 00229 // if t has a node of type int, return it otherwise error 00230 int tree2int (Tree t) 00231 { 00232 double x; 00233 int i; 00234 00235 if (isInt(t->node(), &i)) { 00236 // nothing to do 00237 } else if (isDouble(t->node(), &x)) { 00238 i = int(x); 00239 } else { 00240 ERROR("the node of the tree is not an int nor a float", t); 00241 } 00242 return i; 00243 } 00244 00245 // if t has a node of type float, return it otherwise error 00246 double tree2float (Tree t) 00247 { 00248 double x; 00249 int i; 00250 00251 if (isInt(t->node(), &i)) { 00252 x = double(i); 00253 } else if (isDouble(t->node(), &x)) { 00254 //nothing to do 00255 } else { 00256 ERROR("the node of the tree is not a float nor an int", t); 00257 } 00258 return x; 00259 } 00260 00261 // if t has a node of type float, return it as a double otherwise error 00262 double tree2double (Tree t) 00263 { 00264 double x; 00265 int i; 00266 00267 if (isInt(t->node(), &i)) { 00268 x = double(i); 00269 } else if (isDouble(t->node(), &x)) { 00270 //nothing to do 00271 } else { 00272 ERROR("the node of the tree is not a float nor an int", t); 00273 } 00274 return double(x); 00275 } 00276 00277 // if t has a node of type symbol, return its name otherwise error 00278 const char* tree2str (Tree t) 00279 { 00280 Sym s; 00281 if (!isSym(t->node(), &s)) { 00282 ERROR("the node of the tree is not a symbol", t); 00283 } 00284 return name(s); 00285 } 00286 00287 // if t has a node of type ptr, return it otherwise error 00288 void* tree2ptr (Tree t) 00289 { 00290 void* x; 00291 if (! isPointer(t->node(), &x)) { 00292 ERROR("the node of the tree is not a pointer", t); 00293 } 00294 return x; 00295 } 00296 00297 /* 00298 bool isTree (const Tree& t, const Node& n) 00299 { 00300 return (t->node() == n) && (t->arity() == 0); 00301 } 00302 */ 00303 00304 // Si ca ne pose pas de probl�es, c'est plus pratique 00305 bool isTree (const Tree& t, const Node& n) 00306 { 00307 return (t->node() == n); 00308 } 00309 00310 bool isTree (const Tree& t, const Node& n, Tree& a) 00311 { 00312 if ((t->node() == n) && (t->arity() == 1)) { 00313 a=t->branch(0); 00314 return true; 00315 } else { 00316 return false; 00317 } 00318 } 00319 00320 bool isTree (const Tree& t, const Node& n, Tree& a, Tree& b) 00321 { 00322 if ((t->node() == n) && (t->arity() == 2)) { 00323 a=t->branch(0); 00324 b=t->branch(1); 00325 return true; 00326 } else { 00327 return false; 00328 } 00329 } 00330 00331 bool isTree (const Tree& t, const Node& n, Tree& a, Tree& b, Tree& c) 00332 { 00333 if ((t->node() == n) && (t->arity() == 3)) { 00334 a=t->branch(0); 00335 b=t->branch(1); 00336 c=t->branch(2); 00337 return true; 00338 } else { 00339 return false; 00340 } 00341 } 00342 00343 bool isTree (const Tree& t, const Node& n, Tree& a, Tree& b, Tree& c, Tree& d) 00344 { 00345 if ((t->node() == n) && (t->arity() == 4)) { 00346 a=t->branch(0); 00347 b=t->branch(1); 00348 c=t->branch(2); 00349 d=t->branch(3); 00350 return true; 00351 } else { 00352 return false; 00353 } 00354 } 00355 00356 bool isTree (const Tree& t, const Node& n, Tree& a, Tree& b, Tree& c, Tree& d, Tree& e) 00357 { 00358 if ((t->node() == n) && (t->arity() == 5)) { 00359 a=t->branch(0); 00360 b=t->branch(1); 00361 c=t->branch(2); 00362 d=t->branch(3); 00363 e=t->branch(4); 00364 return true; 00365 } else { 00366 return false; 00367 } 00368 } 00369 00370 // July 2005, support for symbol user data 00371 00372 void* getUserData(Tree t) 00373 { 00374 Sym s; 00375 if (isSym(t->node(), &s)) { 00376 return getUserData(s); 00377 } else { 00378 return 0; 00379 } 00380 } 00381 00382 00388 void CTree::exportProperties(vector<Tree>& keys, vector<Tree>& values) 00389 { 00390 for (plist::const_iterator p = fProperties.begin(); p != fProperties.end(); p++) { 00391 keys.push_back(p->first); 00392 values.push_back(p->second); 00393 } 00394 } 00395
1.8.0