New directory tree, with preprocessor/ inside interpretor/.
[Faustine.git] / 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 (file)
index 0000000..b172fb2
--- /dev/null
@@ -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<Type> v;
+               int n = min(nt1->arity(), nt2->arity());
+               for (int i=0; i<n; i++) { v.push_back( (*nt1)[i] | (*nt2)[i]); }
+               return new TupletType( v );
+               
+       } else {
+
+        vector<int> 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; i<a1; i++)  { if ((*nt1)[i] != (*nt2)[i]) return false; }
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+
+    // compare vector types
+    if ( (vt1 = isVectorType(t1)) && (vt2 = isVectorType(t2)) ) {
+        if (vt1->size() == 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<Type>    v;
+       
+       TupletType* nt1 = dynamic_cast<TupletType*>((AudioType*)t1);
+       TupletType* nt2 = dynamic_cast<TupletType*>((AudioType*)t2);
+       
+       if (nt1) {
+               for (int i=0; i<nt1->arity(); i++) {
+                       v.push_back((*nt1)[i]);
+               }
+       } else {
+               v.push_back(t1);
+       }
+       
+       if (nt2) {
+               for (int i=0; i<nt2->arity(); i++) {
+                       v.push_back((*nt2)[i]);
+               }
+       } else {
+               v.push_back(t2);
+       }
+       return new TupletType(v);       
+}
+       
+
+SimpleType*    isSimpleType(AudioType* t)      { return dynamic_cast<SimpleType*>(t); }
+TableType*     isTableType(AudioType* t)       { return dynamic_cast<TableType*>(t);  }
+TupletType*    isTupletType(AudioType* t)      { return dynamic_cast<TupletType*>(t); }
+VectorType* isVectorType(AudioType* t) { return dynamic_cast<VectorType*>(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<AudioType*> 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<Tree> 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<Tree> elems;
+    for (int i=0; i<nt->arity(); i++) {
+        elems.push_back(codeAudioType((*nt)[i]));
+    }
+    return CTree::make(TUPLETTYPE, elems);
+}
+
+AudioType* makeTupletType(const vector<Type>& 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<Type>& 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<int>& dim)
+{
+    Type r = b;
+    for (unsigned   int i=0; i<dim.size(); i++) r = new VectorType(dim[i],r);
+    return r;
+}
+
+
+/**
+ * Returns true if D1 and D2 are compatible (one is the prefix of the other)).
+ * In this case D3 contains the longuest vector D1 or D2
+ */
+bool maxdimensions(const vector<int>& D1, const vector<int>& D2, vector<int>& D3)
+{
+    unsigned int n1 = D1.size();
+    unsigned int n2 = D2.size();
+    unsigned int i = 0;
+    while ( (i<n1) && (i<n2) && (D1[i]==D2[i]) ) i++;
+    if (i==n1) {
+        D3=D2;
+        return true;
+    } else if (i==n2) {
+        D3=D1;
+        return true;
+    } else {
+        return false;
+    }
+}