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