1 /************************************************************************
2  ************************************************************************
3     FAUST compiler
4     Copyright (C) 2003-2018 GRAME, Centre National de Creation Musicale
5     ---------------------------------------------------------------------
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  ************************************************************************
20  ************************************************************************/
21 
22 #include <climits>
23 #include <iostream>
24 #include <sstream>
25 
26 #include "exception.hh"
27 #include "global.hh"
28 #include "property.hh"
29 #include "sigtype.hh"
30 #include "tree.hh"
31 
32 using namespace std;
33 
isMaximal() const34 bool SimpleType::isMaximal() const  ///< true when type is maximal (and therefore can't change depending of hypothesis)
35 {
36     return (fNature == kReal) && (fVariability == kSamp) && (fComputability == kExec);
37 }
38 
39 //------------------------------------------------------------------------------------
40 //
41 //		Overloading << printing operator
42 //
43 //------------------------------------------------------------------------------------
44 
operator <<(ostream & dst,const Type & t)45 ostream& operator<<(ostream& dst, const Type& t)
46 {
47     return t->print(dst);
48 }
49 
operator <<(ostream & dst,const SimpleType & t)50 ostream& operator<<(ostream& dst, const SimpleType& t)
51 {
52     return t.print(dst);
53 }
54 
operator <<(ostream & dst,const TableType & t)55 ostream& operator<<(ostream& dst, const TableType& t)
56 {
57     return t.print(dst);
58 }
59 
operator <<(ostream & dst,const TupletType & t)60 ostream& operator<<(ostream& dst, const TupletType& t)
61 {
62     return t.print(dst);
63 }
64 
65 //------------------------------------------------------------------------------------
66 //
67 //		Print method definition
68 //
69 //------------------------------------------------------------------------------------
70 
71 /**
72  * Print the content of a simple type on a stream
73  */
print(ostream & dst) const74 ostream& SimpleType::print(ostream& dst) const
75 {
76     return dst << "NR"[nature()] << "KB?S"[variability()] << "CI?E"[computability()] << "VS?TS"[vectorability()]
77                << "N?B"[boolean()] << " " << fInterval;
78 }
79 
80 /**
81  * Print the content of a table type on a stream
82  */
print(ostream & dst) const83 ostream& TableType::print(ostream& dst) const
84 {
85     dst << "KB?S"[variability()] << "CI?E"[computability()] << " " << fInterval << ":Table(";
86     fContent->print(dst);
87     return dst << ')';
88 }
89 
90 /**
91  *  True when type is maximal (and therefore can't change depending of hypothesis)
92  */
isMaximal() const93 bool TableType::isMaximal() const
94 {
95     return (fNature == kReal) && (fVariability == kSamp) && (fComputability == kExec);
96 }
97 
98 /**
99  * Print the content of a tuplet of types on a stream
100  */
print(ostream & dst) const101 ostream& TupletType::print(ostream& dst) const
102 {
103     dst << "KB?S"[variability()] << "CI?E"[computability()] << " " << fInterval << " : {";
104     string sep = "";
105     for (unsigned int i = 0; i < fComponents.size(); i++, sep = "*") {
106         dst << sep;
107         fComponents[i]->print(dst);
108     }
109     dst << '}';
110     return dst;
111 }
112 
113 /**
114  *  True when type is maximal (and therefore can't change depending of hypothesis)
115  */
isMaximal() const116 bool TupletType::isMaximal() const
117 {
118     for (unsigned int i = 0; i < fComponents.size(); i++) {
119         if (!fComponents[i]->isMaximal()) return false;
120     }
121     return true;
122 }
123 
124 //------------------------------------------------------------------------------------
125 //
126 //		Types constructions
127 // 		t := p, table(t), t|t, t*t
128 //
129 //------------------------------------------------------------------------------------
130 
operator |(const Type & t1,const Type & t2)131 Type operator|(const Type& t1, const Type& t2)
132 {
133     SimpleType *st1, *st2;
134     TableType * tt1, *tt2;
135     TupletType *nt1, *nt2;
136 
137     if ((st1 = isSimpleType(t1)) && (st2 = isSimpleType(t2))) {
138         return makeSimpleType(st1->nature() | st2->nature(), st1->variability() | st2->variability(),
139                               st1->computability() | st2->computability(), st1->vectorability() | st2->vectorability(),
140                               st1->boolean() | st2->boolean(), reunion(st1->getInterval(), st2->getInterval()));
141 
142     } else if ((tt1 = isTableType(t1)) && (tt2 = isTableType(t2))) {
143         return makeTableType(tt1->content() | tt2->content());
144 
145     } else if ((nt1 = isTupletType(t1)) && (nt2 = isTupletType(t2))) {
146         vector<Type> v;
147         int          n = (int)min(nt1->arity(), nt2->arity());
148         for (int i = 0; i < n; i++) {
149             v.push_back((*nt1)[i] | (*nt2)[i]);
150         }
151         return new TupletType(v);
152 
153     } else {
154         stringstream error;
155         error << "ERROR : trying to combine incompatible types, " << t1 << " and " << t2 << endl;
156         throw faustexception(error.str());
157     }
158 }
159 
operator ==(const Type & t1,const Type & t2)160 bool operator==(const Type& t1, const Type& t2)
161 {
162     SimpleType *st1, *st2;
163     TableType * tt1, *tt2;
164     TupletType *nt1, *nt2;
165 
166     if (t1->variability() != t2->variability()) return false;
167     if (t1->computability() != t2->computability()) return false;
168 
169     if ((st1 = isSimpleType(t1)) && (st2 = isSimpleType(t2)))
170         return (st1->nature() == st2->nature()) && (st1->variability() == st2->variability()) &&
171                (st1->computability() == st2->computability()) && (st1->vectorability() == st2->vectorability()) &&
172                (st1->boolean() == st2->boolean()) && (st1->getInterval().lo == st2->getInterval().lo) &&
173                (st1->getInterval().hi == st2->getInterval().hi) &&
174                (st1->getInterval().valid == st2->getInterval().valid) && st1->getRes().valid == st2->getRes().valid &&
175                st1->getRes().index == st2->getRes().index;
176     if ((tt1 = isTableType(t1)) && (tt2 = isTableType(t2))) return tt1->content() == tt2->content();
177     if ((nt1 = isTupletType(t1)) && (nt2 = isTupletType(t2))) {
178         int a1 = nt1->arity();
179         int a2 = nt2->arity();
180         if (a1 == a2) {
181             for (int i = 0; i < a1; i++) {
182                 if ((*nt1)[i] != (*nt2)[i]) return false;
183             }
184             return true;
185         } else {
186             return false;
187         }
188     }
189     return false;
190 }
191 
operator <=(const Type & t1,const Type & t2)192 bool operator<=(const Type& t1, const Type& t2)
193 {
194     return (t1 | t2) == t2;
195 }
196 
operator *(const Type & t1,const Type & t2)197 Type operator*(const Type& t1, const Type& t2)
198 {
199     vector<Type> v;
200 
201     TupletType* nt1 = dynamic_cast<TupletType*>((AudioType*)t1);
202     TupletType* nt2 = dynamic_cast<TupletType*>((AudioType*)t2);
203 
204     if (nt1) {
205         for (int i = 0; i < nt1->arity(); i++) {
206             v.push_back((*nt1)[i]);
207         }
208     } else {
209         v.push_back(t1);
210     }
211 
212     if (nt2) {
213         for (int i = 0; i < nt2->arity(); i++) {
214             v.push_back((*nt2)[i]);
215         }
216     } else {
217         v.push_back(t2);
218     }
219     return new TupletType(v);
220 }
221 
isSimpleType(AudioType * t)222 SimpleType* isSimpleType(AudioType* t)
223 {
224     return dynamic_cast<SimpleType*>(t);
225 }
isTableType(AudioType * t)226 TableType* isTableType(AudioType* t)
227 {
228     return dynamic_cast<TableType*>(t);
229 }
isTupletType(AudioType * t)230 TupletType* isTupletType(AudioType* t)
231 {
232     return dynamic_cast<TupletType*>(t);
233 }
234 
235 //--------------------------------------------------
236 // Type checking
237 
checkInt(Type t)238 Type checkInt(Type t)
239 {
240     // check that t is an integer
241     SimpleType* st = isSimpleType(t);
242     if (st == 0 || st->nature() > kInt) {
243         stringstream error;
244         error << "ERROR : checkInt failed for type " << t << endl;
245         throw faustexception(error.str());
246     }
247     return t;
248 }
249 
checkKonst(Type t)250 Type checkKonst(Type t)
251 {
252     // check that t is a constant
253     if (t->variability() > kKonst) {
254         stringstream error;
255         error << "ERROR : checkKonst failed for type " << t << endl;
256         throw faustexception(error.str());
257     }
258     return t;
259 }
260 
checkInit(Type t)261 Type checkInit(Type t)
262 {
263     // check that t is a known at init time
264     if (t->computability() > kInit) {
265         stringstream error;
266         error << "ERROR : checkInit failed for type " << t << endl;
267         throw faustexception(error.str());
268     }
269     return t;
270 }
271 
checkIntParam(Type t)272 Type checkIntParam(Type t)
273 {
274     return checkInit(checkKonst(checkInt(t)));
275 }
276 
checkWRTbl(Type tbl,Type wr)277 Type checkWRTbl(Type tbl, Type wr)
278 {
279     // check that wr is compatible with tbl content
280     if (wr->nature() > tbl->nature()) {
281         stringstream error;
282         error << "ERROR : checkWRTbl failed, the content of " << tbl << " is incompatible with " << wr << endl;
283         throw faustexception(error.str());
284     }
285     return tbl;
286 }
287 
288 /**
289     \brief Check is a type is appropriate for a delay.
290     @return an exception if not appropriate, mxd (max delay) if appropriate
291 
292  */
checkDelayInterval(Type t)293 int checkDelayInterval(Type t)
294 {
295     interval i = t->getInterval();
296     if (i.valid && i.lo >= 0 && i.hi < INT_MAX) {
297         return int(i.hi + 0.5);
298     } else {
299         stringstream error;
300         error << "ERROR : invalid delay parameter range: " << i << ". The range must be between 0 and MAX_INT" << endl;
301         throw faustexception(error.str());
302     }
303 }
304 
305 /*****************************************************************************
306  *
307  *      codeAudioType(Type) -> Tree
308  *      Code an audio type as a tree in order to benefit of memoization
309  *
310  *****************************************************************************/
311 
312 static Tree codeSimpleType(SimpleType* st);
313 static Tree codeTableType(TableType* st);
314 static Tree codeTupletType(TupletType* st);
315 
316 /**
317  * codeAudioType(Type) -> Tree
318  * Code an audio type as a tree in order to benefit of memoization
319  * The type field (of the coded type) is used to store the audio
320  * type
321  */
codeAudioType(AudioType * t)322 Tree codeAudioType(AudioType* t)
323 {
324     SimpleType* st;
325     TableType*  tt;
326     TupletType* nt;
327 
328     Tree r;
329 
330     if ((r = t->getCode())) return r;
331 
332     if ((st = isSimpleType(t))) {
333         r = codeSimpleType(st);
334     } else if ((tt = isTableType(t))) {
335         r = codeTableType(tt);
336     } else if ((nt = isTupletType(t))) {
337         r = codeTupletType(nt);
338     } else {
339         stringstream error;
340         error << "ERROR in codeAudioType() : invalid pointer " << t << endl;
341         throw faustexception(error.str());
342     }
343 
344     r->setType(t);
345     return r;
346 }
347 
348 /**
349  * Code a simple audio type as a tree in order to benefit of memoization
350  */
codeSimpleType(SimpleType * st)351 static Tree codeSimpleType(SimpleType* st)
352 {
353     vector<Tree> elems;
354     elems.push_back(tree(st->nature()));
355     elems.push_back(tree(st->variability()));
356     elems.push_back(tree(st->computability()));
357     elems.push_back(tree(st->vectorability()));
358     elems.push_back(tree(st->boolean()));
359 
360     elems.push_back(tree(st->getInterval().valid));
361     elems.push_back(tree(st->getInterval().lo));
362     elems.push_back(tree(st->getInterval().hi));
363 
364     elems.push_back(tree(st->getRes().valid));
365     elems.push_back(tree(st->getRes().index));
366     return CTree::make(gGlobal->SIMPLETYPE, elems);
367 }
368 
makeSimpleType(int n,int v,int c,int vec,int b,const interval & i)369 AudioType* makeSimpleType(int n, int v, int c, int vec, int b, const interval& i){
370     return makeSimpleType(n, v, c, vec, b, i, gGlobal->RES);
371 }
372 
makeSimpleType(int n,int v,int c,int vec,int b,const interval & i,const res & lsb)373 AudioType* makeSimpleType(int n, int v, int c, int vec, int b, const interval& i, const res& lsb)
374 {
375     SimpleType prototype(n, v, c, vec, b, i, lsb);
376     Tree       code = codeAudioType(&prototype);
377 
378     AudioType* t;
379     if (gGlobal->gMemoizedTypes->get(code, t)) {
380         return t;
381     } else {
382         gGlobal->gAllocationCount++;
383         t = new SimpleType(n, v, c, vec, b, i, lsb);
384         gGlobal->gMemoizedTypes->set(code, t);
385         t->setCode(code);
386         return t;
387     }
388 }
389 
390 /**
391  * Code a table type as a tree in order to benefit of memoization
392  */
codeTableType(TableType * tt)393 static Tree codeTableType(TableType* tt)
394 {
395     return tree(gGlobal->TABLETYPE, codeAudioType(tt->content()));
396 }
397 
makeTableType(const Type & ct)398 AudioType* makeTableType(const Type& ct)
399 {
400     TableType prototype(ct);
401     Tree      code = codeAudioType(&prototype);
402 
403     AudioType* tt;
404     if (gGlobal->gMemoizedTypes->get(code, tt)) {
405         return tt;
406     } else {
407         gGlobal->gAllocationCount++;
408         tt = new TableType(prototype);
409         gGlobal->gMemoizedTypes->set(code, tt);
410         tt->setCode(code);
411         return tt;
412     }
413 }
414 
makeTableType(const Type & ct,int n,int v,int c,int vec,int b,const interval & i)415 AudioType* makeTableType(const Type& ct, int n, int v, int c, int vec, int b, const interval& i)
416 {
417     TableType prototype(ct, n, v, c, vec, b, i);
418     Tree      code = codeAudioType(&prototype);
419 
420     AudioType* tt;
421     if (gGlobal->gMemoizedTypes->get(code, tt)) {
422         return tt;
423     } else {
424         gGlobal->gAllocationCount++;
425         tt = new TableType(prototype);
426         gGlobal->gMemoizedTypes->set(code, tt);
427         tt->setCode(code);
428         return tt;
429     }
430 }
431 
makeTableType(const Type & ct,int n,int v,int c,int vec)432 AudioType* makeTableType(const Type& ct, int n, int v, int c, int vec)
433 {
434     TableType  prototype(ct, n, v, c, vec);
435     Tree       code = codeAudioType(&prototype);
436     AudioType* tt;
437     if (gGlobal->gMemoizedTypes->get(code, tt)) {
438         return tt;
439     } else {
440         gGlobal->gAllocationCount++;
441         tt = new TableType(prototype);
442         gGlobal->gMemoizedTypes->set(code, tt);
443         tt->setCode(code);
444         return tt;
445     }
446 }
447 
448 /**
449  * Code a tuplet type as a tree in order to benefit of memoization
450  */
codeTupletType(TupletType * nt)451 static Tree codeTupletType(TupletType* nt)
452 {
453     vector<Tree> elems;
454     for (int i = 0; i < nt->arity(); i++) {
455         elems.push_back(codeAudioType((*nt)[i]));
456     }
457     return CTree::make(gGlobal->TUPLETTYPE, elems);
458 }
459 
makeTupletType(const vector<Type> & vt)460 AudioType* makeTupletType(const vector<Type>& vt)
461 {
462     TupletType prototype(vt);
463     Tree       code = codeAudioType(&prototype);
464 
465     AudioType* t;
466     if (gGlobal->gMemoizedTypes->get(code, t)) {
467         return t;
468     } else {
469         gGlobal->gAllocationCount++;
470         t = new TupletType(vt);
471         gGlobal->gMemoizedTypes->set(code, t);
472         t->setCode(code);
473         return t;
474     }
475 }
476 
makeTupletType(const vector<Type> & vt,int n,int v,int c,int vec,int b,const interval & i)477 AudioType* makeTupletType(const vector<Type>& vt, int n, int v, int c, int vec, int b, const interval& i)
478 {
479     TupletType prototype(vt, n, v, c, vec, b, i);
480     Tree       code = codeAudioType(&prototype);
481 
482     AudioType* t;
483     if (gGlobal->gMemoizedTypes->get(code, t)) {
484         return t;
485     } else {
486         gGlobal->gAllocationCount++;
487         t = new TupletType(vt, n, v, c, vec, b, i);
488         gGlobal->gMemoizedTypes->set(code, t);
489         t->setCode(code);
490         return t;
491     }
492 }
493