X-Git-Url: https://scm.cri.ensmp.fr/git/Faustine.git/blobdiff_plain/c7f552fd8888da2f0d8cfb228fe0f28d3df3a12c..b4b6f2ea75b9f0f3ca918f5b84016610bf7a4d4f:/interpretor/preprocessor/faust-0.9.47mr3/compiler/signals/sigtype.cpp diff --git a/interpretor/preprocessor/faust-0.9.47mr3/compiler/signals/sigtype.cpp b/interpretor/preprocessor/faust-0.9.47mr3/compiler/signals/sigtype.cpp new file mode 100644 index 0000000..b172fb2 --- /dev/null +++ b/interpretor/preprocessor/faust-0.9.47mr3/compiler/signals/sigtype.cpp @@ -0,0 +1,627 @@ +/************************************************************************ + ************************************************************************ + FAUST compiler + Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale + --------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + ************************************************************************ + ************************************************************************/ + + + +#include "tree.hh" +#include "sigtype.hh" +#include "property.hh" + +int AudioType::gAllocationCount = 0; + +bool SimpleType::isMaximal() const ///< true when type is maximal (and therefore can't change depending of hypothesis) +{ + return (fNature==kReal) + && (fVariability==kSamp) + && (fComputability==kExec); + +} + + +//------------------------------------------------------------------------------------ +// +// Surcharges de l'operateur d'impression << +// +//------------------------------------------------------------------------------------ + + +ostream& operator<<(ostream& dst, const Type& t) { return t->print(dst);} + +ostream& operator<<(ostream& dst, const SimpleType& t) { return t.print(dst); } + +ostream& operator<<(ostream& dst, const TableType& t) { return t.print(dst); } + +ostream& operator<<(ostream& dst, const TupletType& t) { return t.print(dst); } + +ostream& operator<<(ostream& dst, const VectorType& t) { return t.print(dst); } + + +//------------------------------------------------------------------------------------ +// +// Definition des methodes d'impression +// +//------------------------------------------------------------------------------------ + + +/** + * Print the content of a simple type on a stream + */ +ostream& SimpleType::print(ostream& dst) const +{ + return dst << "NR"[nature()] + << "KB?S"[variability()] + << "CI?E"[computability()] + << "VS?TS"[vectorability()] + << "N?B"[boolean()] + << " " << fInterval; +} + + +/** + * Print the content of a table type on a stream + */ +ostream& TableType::print(ostream& dst) const +{ + dst << "KB?S"[variability()] + << "CI?E"[computability()] + << " " << fInterval + << ":Table("; + fContent->print(dst); + return dst << ')'; +} + + +/** + * true when type is maximal (and therefore can't change depending of hypothesis) + */ +bool TableType::isMaximal() const +{ + return (fNature==kReal) + && (fVariability==kSamp) + && (fComputability==kExec); +} + + + +/** + * Print the content of a tuplet of types on a stream + */ +ostream& TupletType::print(ostream& dst) const +{ + dst << "KB?S"[variability()] + << "CI?E"[computability()] + << " " << fInterval + << " : {"; + string sep = ""; + for (unsigned int i = 0; i < fComponents.size(); i++, sep="*") { + dst << sep; + fComponents[i]->print(dst); + } + dst << '}'; + return dst; +} + + + +/** + * Print the content of a vector type on a stream + */ +ostream& VectorType::print(ostream& dst) const +{ + dst << "vector[" << fSize << "," << fContent << "]"; + return dst; +} + + +/** + * true when type is maximal (and therefore can't change depending of hypothesis) + */ +bool TupletType::isMaximal() const +{ + for (unsigned int i = 0; i < fComponents.size(); i++) { + if (! fComponents[i]->isMaximal()) return false; + } + return true; +} + + +//------------------------------------------------------------------------------------ +// +// Construction des types +// t := p, table(t), t|t, t*t +// +//------------------------------------------------------------------------------------ + +// Essential predefined types + +Type TINT = makeSimpleType(kInt, kKonst, kComp, kVect, kNum, interval()); +Type TREAL = makeSimpleType(kReal, kKonst, kComp, kVect, kNum, interval()); + +Type TKONST = makeSimpleType(kInt, kKonst, kComp, kVect, kNum, interval()); +Type TBLOCK = makeSimpleType(kInt, kBlock, kComp, kVect, kNum, interval()); +Type TSAMP = makeSimpleType(kInt, kSamp, kComp, kVect, kNum, interval()); + +Type TCOMP = makeSimpleType(kInt, kKonst, kComp, kVect, kNum, interval()); +Type TINIT = makeSimpleType(kInt, kKonst, kInit, kVect, kNum, interval()); +Type TEXEC = makeSimpleType(kInt, kKonst, kExec, kVect, kNum, interval()); + +// more predefined types + +Type TINPUT = makeSimpleType(kReal, kSamp, kExec, kVect, kNum, interval()); +Type TGUI = makeSimpleType(kReal, kBlock,kExec, kVect, kNum, interval()); +Type TGUI01 = makeSimpleType(kReal, kBlock,kExec, kVect, kNum, interval(0,1)); +Type INT_TGUI = makeSimpleType(kInt, kBlock,kExec, kVect, kNum, interval()); +//Type TREC = makeSimpleType(kInt, kSamp, kInit, kVect, kNum, interval()); // kVect ou kScal ? + +// trying to accelerate type convergence +//Type TREC = TINT; +Type TREC = makeSimpleType(kInt, kSamp, kInit, kScal, kNum, interval()); // kVect ou kScal ? + + +Type operator| ( const Type& t1, const Type& t2) +{ + SimpleType *st1, *st2; + TableType *tt1, *tt2; + TupletType *nt1, *nt2; + + if ( (st1 = isSimpleType(t1)) && (st2 = isSimpleType(t2)) ) { + + return makeSimpleType( st1->nature()|st2->nature(), + st1->variability()|st2->variability(), + st1->computability()|st2->computability(), + st1->vectorability()|st2->vectorability(), + st1->boolean()|st2->boolean(), + reunion(st1->getInterval(), st2->getInterval()) + ); + + } else if ( (tt1 = isTableType(t1)) && (tt2 = isTableType(t2)) ) { + + return makeTableType( tt1->content() | tt2->content() ); + + } else if ( (nt1 = isTupletType(t1)) && (nt2 = isTupletType(t2)) ) { + + vector v; + int n = min(nt1->arity(), nt2->arity()); + for (int i=0; i D1, D2, D3; + Type b1 = t1->dimensions(D1); + Type b2 = t2->dimensions(D2); + if (maxdimensions(D1, D2, D3)) { + Type b3 = b1|b2; + return makeVectorType(b3, D3); + } + + cerr << "Error : trying to combine incompatible types, " << t1 << " and " << t2 << endl; + exit(1); + return 0; + } +} + +bool operator== ( const Type& t1, const Type& t2) +{ + SimpleType *st1, *st2; + TableType *tt1, *tt2; + TupletType *nt1, *nt2; + VectorType *vt1, *vt2; + + if (t1->variability() != t2->variability()) return false; + if (t1->computability() != t2->computability()) return false; + + if ( (st1 = isSimpleType(t1)) && (st2 = isSimpleType(t2)) ) + return (st1->nature() == st2->nature()) + && (st1->variability() == st2->variability()) + && (st1->computability() == st2->computability()) + && (st1->vectorability() == st2->vectorability()) + && (st1->boolean() == st2->boolean()) + && (st1->getInterval().lo == st2->getInterval().lo) + && (st1->getInterval().hi == st2->getInterval().hi) + && (st1->getInterval().valid == st2->getInterval().valid); + if ( (tt1 = isTableType(t1)) && (tt2 = isTableType(t2)) ) + return tt1->content()== tt2->content(); + if ( (nt1 = isTupletType(t1)) && (nt2 = isTupletType(t2)) ) { + int a1 = nt1->arity(); + int a2 = nt2->arity(); + if (a1 == a2) { + for (int i=0; isize() == vt2->size()) { + return vt1->content() == vt2->content(); + } else { + return false; + } + } + + // types are different + return false; +} + +bool operator<= ( const Type& t1, const Type& t2) +{ + return (t1|t2) == t2; +} + + + +Type operator* (const Type& t1, const Type& t2) +{ + vector v; + + TupletType* nt1 = dynamic_cast((AudioType*)t1); + TupletType* nt2 = dynamic_cast((AudioType*)t2); + + if (nt1) { + for (int i=0; iarity(); i++) { + v.push_back((*nt1)[i]); + } + } else { + v.push_back(t1); + } + + if (nt2) { + for (int i=0; iarity(); i++) { + v.push_back((*nt2)[i]); + } + } else { + v.push_back(t2); + } + return new TupletType(v); +} + + +SimpleType* isSimpleType(AudioType* t) { return dynamic_cast(t); } +TableType* isTableType(AudioType* t) { return dynamic_cast(t); } +TupletType* isTupletType(AudioType* t) { return dynamic_cast(t); } +VectorType* isVectorType(AudioType* t) { return dynamic_cast(t); } + + + +//-------------------------------------------------- +// verification de type + +Type checkInt(Type t) +{ + // verifie que t est entier + SimpleType* st = isSimpleType(t); + if (st == 0 || st->nature() > kInt) { + cerr << "Error : checkInt failed for type " << t << endl; + exit(1); + } + return t; +} + +Type checkKonst(Type t) +{ + // verifie que t est constant + if (t->variability() > kKonst) { + cerr << "Error : checkKonst failed for type " << t << endl; + exit(1); + } + return t; +} + +Type checkInit(Type t) +{ + // verifie que t est connu a l'initialisation + if (t->computability() > kInit) { + cerr << "Error : checkInit failed for type " << t << endl; + exit(1); + } + return t; +} + +Type checkIntParam(Type t) +{ + return checkInit(checkKonst(checkInt(t))); +} + +Type checkWRTbl(Type tbl, Type wr) +{ + // verifie que wr est compatible avec le contenu de tbl + if (wr->nature() > tbl->nature()) { + cerr << "Error : checkWRTbl failed, the content of " << tbl << " is incompatible with " << wr << endl; + exit(1); + } + return tbl; +} + +/** + \brief Check is a type is appropriate for a delay. + @return -1 if not appropriate, mxd (max delay) if appropriate + + */ +int checkDelayInterval(Type t) +{ + interval i = t->getInterval(); + if (i.valid && i.lo >= 0) { + return int(i.hi+0.5); + } else { + //cerr << "checkDelayInterval failed for : " << i << endl; + return -1; + } +} + + +// Donne le nom du type C correspondant �la nature d'un signal +string cType (Type t) +{ + return (t->nature() == kInt) ? "int" : "float"; +} + + + +/***************************************************************************** + * + * codeAudioType(Type) -> Tree + * Code an audio type as a tree in order to benefit of memoization + * + *****************************************************************************/ + +// memoized type contruction + +property MemoizedTypes; + + +Sym SIMPLETYPE = symbol ("SimpleType"); +Sym TABLETYPE = symbol ("TableType"); +Sym TUPLETTYPE = symbol ("TupletType"); +Sym VECTORTYPE = symbol ("VectorType"); + +static Tree codeSimpleType(SimpleType* st); +static Tree codeTableType(TableType* st); +static Tree codeTupletType(TupletType* st); +static Tree codeVectorType(VectorType* st); + + +/** + * codeAudioType(Type) -> Tree + * Code an audio type as a tree in order to benefit of memoization + * The type field (of the coded type) is used to store the audio + * type + */ +Tree codeAudioType(AudioType* t) +{ + SimpleType* st; + TableType* tt; + TupletType* nt; + VectorType* vt; + + Tree r; + + if ((r=t->getCode())) return r; + + if ((st = isSimpleType(t))) { + r = codeSimpleType(st); + } else if ((tt = isTableType(t))) { + r = codeTableType(tt); + } else if ((nt = isTupletType(t))) { + r = codeTupletType(nt); + } else if ((vt = isVectorType(t))) { + r = codeVectorType(vt); + } else { + cerr << "ERROR in codeAudioType() : invalide pointer " << t << endl; + exit(1); + } + + r->setType(t); + return r; + +} + + +/** + * Code a simple audio type as a tree in order to benefit of memoization + */ +static Tree codeSimpleType(SimpleType* st) +{ + vector elems; + elems.push_back(tree(st->nature())); + elems.push_back(tree(st->variability())); + elems.push_back(tree(st->computability())); + elems.push_back(tree(st->vectorability())); + elems.push_back(tree(st->boolean())); + + elems.push_back(tree(st->getInterval().valid)); + elems.push_back(tree(st->getInterval().lo)); + elems.push_back(tree(st->getInterval().hi)); + + return CTree::make(SIMPLETYPE, elems); + +} + +AudioType* makeSimpleType(int n, int v, int c, int vec, int b, const interval& i) +{ + SimpleType prototype(n,v,c,vec,b,i); + Tree code = codeAudioType(&prototype); + + AudioType* t; + if (MemoizedTypes.get(code, t)) { + return t; + } else { + AudioType::gAllocationCount++; + t = new SimpleType(n,v,c,vec,b,i); + MemoizedTypes.set(code, t); + t->setCode(code); + return t; + } +} + + +/** + * Code a table type as a tree in order to benefit of memoization + */ + +static Tree codeTableType(TableType* tt) +{ + return tree(TABLETYPE, codeAudioType(tt->content())); +} + +AudioType* makeTableType(const Type& ct) +{ + TableType prototype(ct); + Tree code = codeAudioType(&prototype); + + AudioType* tt; + if (MemoizedTypes.get(code, tt)) { + return tt; + } else { + AudioType::gAllocationCount++; + tt = new TableType(ct); + MemoizedTypes.set(code, tt); + tt->setCode(code); + return tt; + } +} + +AudioType* makeTableType(const Type& ct, int n, int v, int c, int vec, int b, const interval& i) +{ + TableType prototype(ct,n,v,c,vec,b,i); + Tree code = codeAudioType(&prototype); + + AudioType* tt; + if (MemoizedTypes.get(code, tt)) { + return tt; + } else { + AudioType::gAllocationCount++; + tt = new TableType(ct); + MemoizedTypes.set(code, tt); + tt->setCode(code); + return tt; + } +} + +AudioType* makeTableType(const Type& ct, int n, int v, int c, int vec) +{ + TableType prototype(ct,n,v,c,vec); + Tree code = codeAudioType(&prototype); + + AudioType* tt; + if (MemoizedTypes.get(code, tt)) { + return tt; + } else { + AudioType::gAllocationCount++; + tt = new TableType(ct); + MemoizedTypes.set(code, tt); + tt->setCode(code); + return tt; + } +} + + +/** + * Code a tuplet type as a tree in order to benefit of memoization + */ + +static Tree codeTupletType(TupletType* nt) +{ + vector elems; + for (int i=0; iarity(); i++) { + elems.push_back(codeAudioType((*nt)[i])); + } + return CTree::make(TUPLETTYPE, elems); +} + +AudioType* makeTupletType(const vector& vt) +{ + TupletType prototype(vt); + Tree code = codeAudioType(&prototype); + + AudioType* t; + if (MemoizedTypes.get(code, t)) { + return t; + } else { + AudioType::gAllocationCount++; + t = new TupletType(vt); + MemoizedTypes.set(code, t); + t->setCode(code); + return t; + } + +} + +AudioType* makeTupletType(const vector& vt, int n, int v, int c, int vec, int b, const interval& i) +{ + TupletType prototype(vt,n,v,c,vec,b,i); + Tree code = codeAudioType(&prototype); + + AudioType* t; + if (MemoizedTypes.get(code, t)) { + return t; + } else { + AudioType::gAllocationCount++; + t = new TupletType(vt,n,v,c,vec,b,i); + MemoizedTypes.set(code, t); + t->setCode(code); + return t; + } + +} + +/** + * Code a vector type as a tree in order to benefit of memoization + */ + +static Tree codeVectorType(VectorType* vt) +{ + assert(vt); + //cerr << "codeVectorType(" << *vt << ")" << endl; + int i = vt->size(); + return tree(VECTORTYPE, tree(i), codeAudioType(vt->content())); +} + +Type makeVectorType(const Type& b, const vector& dim) +{ + Type r = b; + for (unsigned int i=0; i& D1, const vector& D2, vector& D3) +{ + unsigned int n1 = D1.size(); + unsigned int n2 = D2.size(); + unsigned int i = 0; + while ( (i