FAUST compiler  0.9.9.6b8
sourcereader.cpp
Go to the documentation of this file.
00001 /*
00002     sourcereader : Faust source file reader
00003     
00004     This component is in charge of mapping filenames to 
00005     the list of faust definitions they contain.
00006     
00007 */
00008 #include <iostream>
00009 #include <map>
00010 #include <list>
00011 #include <string>
00012 
00013 
00014 #include "sourcereader.hh"
00015 #include "enrobage.hh"
00016 #include "ppbox.hh"
00017 
00018 using namespace std;
00019 
00020 extern map<Tree, set<Tree> > gMetaDataSet;
00021 extern string gMasterDocument;
00022 extern vector<Tree> gDocVector;
00023 extern bool gLatexDocSwitch;
00024 
00025 /****************************************************************
00026                         Parser variables
00027 *****************************************************************/
00028 
00029 
00030 int yyparse();
00031 
00032 extern int      yyerr;
00033 extern int      yydebug;
00034 extern FILE*    yyin;
00035 extern int      yylineno;
00036 extern const char * yyfilename;
00037 
00038 extern Tree     gResult;
00039 extern Tree     gResult2;
00040 
00041  
00042 
00043 
00052 static bool standardArgList(Tree args)
00053 {
00054     map<Tree,int>   L;
00055     while (isList(args)) {
00056         if (!isBoxIdent(hd(args))) return false;
00057         if (++L[hd(args)] > 1) return false;
00058         args = tl(args);
00059     }
00060     return true;
00061 }
00062 
00063 
00064 static void printPatternError(Tree lhs1, Tree rhs1, Tree lhs2, Tree rhs2)
00065 {
00066     cerr    << "ERROR : inconsistent number of parameters in pattern-matching rule: "
00067             << boxpp(reverse(lhs2)) << " => " << boxpp(rhs2) << ";"
00068             << " previous rule was: " 
00069             << boxpp(reverse(lhs1)) << " => " << boxpp(rhs1) << ";"
00070             << endl;
00071 }
00072 
00073 Tree checkRulelist (Tree lr)
00074 {
00075     Tree lrules = lr;
00076     if (isNil(lrules)) { cerr << "ERROR : a case expression can't be empty" << endl; exit(1); }
00077     // first pattern used as a reference
00078     Tree lhs1 = hd(hd(lrules));
00079     Tree rhs1 = tl(hd(lrules));
00080     int npat = len(lhs1); 
00081     lrules = tl(lrules);
00082     while (! isNil(lrules)) {
00083         Tree lhs2 = hd(hd(lrules));
00084         Tree rhs2 = tl(hd(lrules));
00085         if (npat != len(lhs2)) {
00086             printPatternError(lhs1,rhs1,lhs2,rhs2);
00087             exit(1);
00088         }
00089         
00090         lhs1 = lhs2;
00091         rhs1 = rhs2;
00092         lrules = tl(lrules);
00093     }   
00094     return lr;
00095 }
00096 
00097 
00104 static Tree makeDefinition(list<Tree>& variants)
00105 {
00106     if (variants.size() == 1) {
00107         Tree rhs = *(variants.begin());
00108         Tree args= hd(rhs);
00109         Tree body= tl(rhs);
00110         
00111         if (isNil(args)) {
00112             return body;
00113         } else if (standardArgList(args)) {
00114             return buildBoxAbstr(args, body);
00115         } else {
00116             return boxCase(cons(rhs,nil));
00117         }
00118     } else {
00119         list<Tree>::iterator p;
00120         Tree    l = nil;
00121         Tree    prev = *variants.begin();
00122         int     npat = len(hd(prev));
00123         for (p=variants.begin(); p!=variants.end(); p++) {
00124             Tree cur = *p;
00125             if (npat != len(hd(cur))) {
00126                 printPatternError(hd(prev), tl(prev), hd(cur), tl(cur));
00127                 exit(1);
00128             }
00129             prev = cur;
00130             l = cons(*p,l);
00131         }
00132         return boxCase(l);
00133     }
00134 }
00135 
00136 
00137 
00146 Tree formatDefinitions(Tree rldef)
00147 {
00148     map<Tree,list<Tree> > dic;
00149     map<Tree,list<Tree> >::iterator p;
00150     Tree ldef2 = nil;
00151     Tree file;
00152     
00153     //cout << "Format definitions " << *rldef << endl;
00154     // collects the definitions in a dictionnary
00155     while (!isNil(rldef)) {
00156         Tree def = hd(rldef);       
00157         rldef = tl(rldef);
00158         if (isImportFile(def, file)) {
00159             ldef2 = cons(def,ldef2);
00160         } else if (!isNil(def)) { 
00161             //cout << " def : " << *def << endl; 
00162             dic[hd(def)].push_front(tl(def)); 
00163         }
00164     }
00165     
00166     // produce the definitions
00167     
00168     for (p=dic.begin(); p!=dic.end(); p++) {
00169         ldef2 = cons (cons(p->first, makeDefinition(p->second)), ldef2);
00170     }
00171     
00172     //cout << "list of definitions : " << *ldef2 << endl;
00173     return ldef2;
00174         
00175 }
00176 
00177 
00186 Tree SourceReader::parse(string fname)
00187 {
00188     string  fullpath;
00189     
00190     yyerr = 0;
00191     
00192     yyfilename = fname.c_str();
00193     yyin = fopensearch(yyfilename, fullpath);
00194     if (yyin == NULL) {
00195         fprintf(stderr, "ERROR : Unable to open file  %s \n", yyfilename); 
00196         exit(1);
00197     }
00198     
00199     yylineno = 1;
00200     int r = yyparse();
00201     if (r) { 
00202         fprintf(stderr, "Parse error : code = %d \n", r); 
00203     }
00204     if (yyerr > 0) {
00205         //fprintf(stderr, "Erreur de parsing 2, count = %d \n", yyerr); 
00206         exit(1);
00207     }
00208 
00209     // we have parsed a valid file
00210     fFilePathnames.push_back(fullpath);
00211     return gResult;
00212 }
00213 
00214 
00222 bool SourceReader::cached(string fname)
00223 {
00224     return fFileCache.find(fname) != fFileCache.end();
00225 }
00226 
00227 
00235 Tree SourceReader::getlist(string fname)
00236 {
00237     if (!cached(fname)) {
00238         fFileCache[fname] = parse(fname);
00239     }
00240     if (fFileCache[fname] == 0) exit(1);
00241     return fFileCache[fname];
00242 }
00243 
00244  
00251 vector<string> SourceReader::listSrcFiles()
00252 {
00253 //  vector<string>                      srcfiles;
00254 
00255 //  for (map<string, Tree>::const_iterator p = fFileCache.begin(); p != fFileCache.end(); p++) {
00256 //      srcfiles.push_back(p->first);
00257 //  }
00258 
00259 //  return srcfiles;    
00260     return fFilePathnames;
00261 }
00262 
00263  
00271 Tree SourceReader::expandlist(Tree ldef)
00272 {
00273     set<string> visited;
00274     return expandrec(ldef, visited, nil);   
00275 }
00276 
00277 Tree SourceReader::expandrec(Tree ldef, set<string>& visited, Tree lresult)
00278 {
00279     for (;!isNil(ldef); ldef = tl(ldef)) {
00280         Tree d = hd(ldef); 
00281         Tree fname;
00282         if (isNil(d)) {
00283             // skill null definitions produced by declarations
00284         } else if (isImportFile(d,fname)) {
00285             string f = tree2str(fname);
00286             //cerr << "import(" << f << ")" << endl;
00287             
00288             //string f = tree2str(fname);
00289             if (visited.find(f) == visited.end()) {
00290                 visited.insert(f);
00291                 //Tree l = getlist(f);
00292                 lresult = expandrec(getlist(f), visited, lresult);
00293             }
00294             
00295         } else {
00296             lresult = cons(d, lresult);
00297         }
00298     }
00299     return lresult;
00300 }
00301                 
00302 
00303 void declareMetadata(Tree key, Tree value)
00304 {
00305     if (gMasterDocument == yyfilename) {
00306         // inside master document, no prefix needed to declare metadata
00307         gMetaDataSet[key].insert(value);
00308     } else {
00309         string fkey(yyfilename);
00310         fkey += "/";
00311         fkey += tree2str(key);
00312         gMetaDataSet[tree(fkey.c_str())].insert(value);
00313     }
00314     //cout << "Master " << gMasterDocument  << ", file " << yyfilename <<  " : declare " << *key << "," << *value << endl;
00315 }
00316 
00317 
00318 void declareDoc(Tree t)
00319 {
00320     //gLatexDocSwitch = true;
00321     gDocVector.push_back(t);
00322 }