2 sourcereader : Faust source file reader
4 This component is in charge of mapping filenames to
5 the list of faust definitions they contain.
14 #include "sourcereader.hh"
15 #include "enrobage.hh"
20 extern map
<Tree
, set
<Tree
> > gMetaDataSet
;
21 extern string gMasterDocument
;
22 extern vector
<Tree
> gDocVector
;
23 extern bool gLatexDocSwitch
;
25 /****************************************************************
27 *****************************************************************/
36 extern const char * yyfilename
;
45 * Checks an argument list for containing only
46 * standard identifiers, no patterns and
48 * @param args the argument list to check
49 * @return true if it contains only identifiers
52 static bool standardArgList(Tree args
)
55 while (isList(args
)) {
56 if (!isBoxIdent(hd(args
))) return false;
57 if (++L
[hd(args
)] > 1) return false;
64 static void printPatternError(Tree lhs1
, Tree rhs1
, Tree lhs2
, Tree rhs2
)
66 cerr
<< "ERROR : inconsistent number of parameters in pattern-matching rule: "
67 << boxpp(reverse(lhs2
)) << " => " << boxpp(rhs2
) << ";"
68 << " previous rule was: "
69 << boxpp(reverse(lhs1
)) << " => " << boxpp(rhs1
) << ";"
73 Tree
checkRulelist (Tree lr
)
76 if (isNil(lrules
)) { cerr
<< "ERROR : a case expression can't be empty" << endl
; exit(1); }
77 // first pattern used as a reference
78 Tree lhs1
= hd(hd(lrules
));
79 Tree rhs1
= tl(hd(lrules
));
82 while (! isNil(lrules
)) {
83 Tree lhs2
= hd(hd(lrules
));
84 Tree rhs2
= tl(hd(lrules
));
85 if (npat
!= len(lhs2
)) {
86 printPatternError(lhs1
,rhs1
,lhs2
,rhs2
);
99 * Transforms a list of variants (arglist.body)
100 * into an abstraction or a boxCase.
101 * @param variants list of variants (arglist.body)
102 * @return the corresponding box expression
104 static Tree
makeDefinition(list
<Tree
>& variants
)
106 if (variants
.size() == 1) {
107 Tree rhs
= *(variants
.begin());
113 } else if (standardArgList(args
)) {
114 return buildBoxAbstr(args
, body
);
116 return boxCase(cons(rhs
,nil
));
119 list
<Tree
>::iterator p
;
121 Tree prev
= *variants
.begin();
122 int npat
= len(hd(prev
));
123 for (p
=variants
.begin(); p
!=variants
.end(); p
++) {
125 if (npat
!= len(hd(cur
))) {
126 printPatternError(hd(prev
), tl(prev
), hd(cur
), tl(cur
));
139 * Formats a list of raw definitions represented by triplets
140 * <name,arglist,body> into abstractions or pattern
141 * matching rules when appropriate.
143 * @param rldef list of raw definitions in reverse order
144 * @return the list of formatted definitions
146 Tree
formatDefinitions(Tree rldef
)
148 map
<Tree
,list
<Tree
> > dic
;
149 map
<Tree
,list
<Tree
> >::iterator p
;
153 //cout << "Format definitions " << *rldef << endl;
154 // collects the definitions in a dictionnary
155 while (!isNil(rldef
)) {
156 Tree def
= hd(rldef
);
158 if (isImportFile(def
, file
)) {
159 ldef2
= cons(def
,ldef2
);
160 } else if (!isNil(def
)) {
161 //cout << " def : " << *def << endl;
162 dic
[hd(def
)].push_front(tl(def
));
166 // produce the definitions
168 for (p
=dic
.begin(); p
!=dic
.end(); p
++) {
169 ldef2
= cons (cons(p
->first
, makeDefinition(p
->second
)), ldef2
);
172 //cout << "list of definitions : " << *ldef2 << endl;
179 * Parse a single faust source file. returns the list of
180 * definitions it contains.
182 * @param fname the name of the file to parse
183 * @return the list of definitions it contains
186 Tree
SourceReader::parse(string fname
)
192 yyfilename
= fname
.c_str();
193 yyin
= fopensearch(yyfilename
, fullpath
);
195 fprintf(stderr
, "ERROR : Unable to open file %s \n", yyfilename
);
202 fprintf(stderr
, "Parse error : code = %d \n", r
);
205 //fprintf(stderr, "Erreur de parsing 2, count = %d \n", yyerr);
209 // we have parsed a valid file
210 fFilePathnames
.push_back(fullpath
);
216 * Check if a file as been read and is in the "cache"
218 * @param fname the name of the file to check
219 * @return true if the file is in the cache
222 bool SourceReader::cached(string fname
)
224 return fFileCache
.find(fname
) != fFileCache
.end();
229 * Return the list of definitions file contains. Cache the result.
231 * @param fname the name of the file to check
232 * @return the list of definitions it contains
235 Tree
SourceReader::getlist(string fname
)
237 if (!cached(fname
)) {
238 fFileCache
[fname
] = parse(fname
);
240 if (fFileCache
[fname
] == 0) exit(1);
241 return fFileCache
[fname
];
246 * Return a vector of pathnames representing the list
247 * of all the source files that have been required
248 * to evaluate process (those in fFileCache)
251 vector
<string
> SourceReader::listSrcFiles()
253 // vector<string> srcfiles;
255 // for (map<string, Tree>::const_iterator p = fFileCache.begin(); p != fFileCache.end(); p++) {
256 // srcfiles.push_back(p->first);
260 return fFilePathnames
;
265 * Return the list of definitions where all imports have been expanded.
267 * @param ldef the list of definitions to expand
268 * @return the expanded list of definitions
271 Tree
SourceReader::expandlist(Tree ldef
)
274 return expandrec(ldef
, visited
, nil
);
277 Tree
SourceReader::expandrec(Tree ldef
, set
<string
>& visited
, Tree lresult
)
279 for (;!isNil(ldef
); ldef
= tl(ldef
)) {
283 // skill null definitions produced by declarations
284 } else if (isImportFile(d
,fname
)) {
285 string f
= tree2str(fname
);
286 //cerr << "import(" << f << ")" << endl;
288 //string f = tree2str(fname);
289 if (visited
.find(f
) == visited
.end()) {
291 //Tree l = getlist(f);
292 lresult
= expandrec(getlist(f
), visited
, lresult
);
296 lresult
= cons(d
, lresult
);
303 void declareMetadata(Tree key
, Tree value
)
305 if (gMasterDocument
== yyfilename
) {
306 // inside master document, no prefix needed to declare metadata
307 gMetaDataSet
[key
].insert(value
);
309 string
fkey(yyfilename
);
311 fkey
+= tree2str(key
);
312 gMetaDataSet
[tree(fkey
.c_str())].insert(value
);
314 //cout << "Master " << gMasterDocument << ", file " << yyfilename << " : declare " << *key << "," << *value << endl;
318 void declareDoc(Tree t
)
320 //gLatexDocSwitch = true;
321 gDocVector
.push_back(t
);