--- /dev/null
+/************************************************************************
+ ************************************************************************
+ 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 <stdio.h>
+#include <assert.h>
+#include <iostream>
+#include <fstream>
+#include <time.h>
+
+
+#include "sigtype.hh"
+#include "sigprint.hh"
+#include "ppsig.hh"
+//#include "prim.hh"
+#include "prim2.hh"
+#include "tlib.hh"
+#include "sigtyperules.hh"
+#include "xtended.hh"
+#include "recursivness.hh"
+#include "sigraterules.hh"
+
+
+//--------------------------------------------------------------------------
+// Uncomment to activate type inference tracing
+
+//#define TRACE(x) x
+#define TRACE(x) 0;
+
+
+
+//--------------------------------------------------------------------------
+// prototypes
+static ostream& printRateEnvironment(ostream& fout, Tree E);
+static Tree inferreMultiRates(Tree lsig, bool& success);
+static ostream& printRateEnvironmentList(ostream& fout, Tree LE);
+
+static void setSigType(Tree sig, Type t);
+static Type getSigType(Tree sig);
+static Type initialRecType(Tree t);
+
+static Type T(Tree term, Tree env);
+
+static Type infereSigType(Tree term, Tree env);
+static Type infereFFType (Tree ff, Tree ls, Tree env);
+static Type infereFConstType (Tree type);
+static Type infereFVarType (Tree type);
+static Type infereRecType (Tree var, Tree body, Tree env);
+static Type infereReadTableType(Type tbl, Type ri);
+static Type infereWriteTableType(Type tbl, Type wi, Type wd);
+static Type infereProjType(Type t, int i, int vec);
+static Type infereXType(Tree sig, Tree env);
+static Type infereDocConstantTblType(Type size, Type init);
+static Type infereDocWriteTblType(Type size, Type init, Type widx, Type wsig);
+static Type infereDocAccessTblType(Type tbl, Type ridx);
+static interval arithmetic (int opcode, const interval& x, const interval& y);
+
+
+static Type infereVectorizeType(Tree sig, Type T, Type Tsize);
+static Type infereSerializeType(Tree sig, Type Tvec);
+static Type infereConcatType(Type Tvec1, Type Tvec2);
+static Type infereVectorAtType(Type Tvec, Type Tidx);
+
+
+
+
+/**
+ * The empty type environment (also property key for closed term type)
+ */
+static Tree NULLTYPEENV = tree(symbol("NullTypeEnv"));
+
+static int countInferences;
+static int countMaximal;
+
+
+
+/**
+ * Fully annotate every subtree of term with type information.
+ * @param sig the signal term tree to annotate
+ */
+
+void typeAnnotation(Tree sig)
+{
+ Tree sl = symlist(sig);
+ int n = len(sl);
+
+ vector<Tree> vrec, vdef;
+ vector<Type> vtype;
+
+ //cerr << "Symlist " << *sl << endl;
+ for (Tree l=sl; isList(l); l=tl(l)) {
+ Tree id, body;
+ assert(isRec(hd(l), id, body));
+
+ vrec.push_back(hd(l));
+ vdef.push_back(body);
+ }
+
+ // init recursive types
+ for (int i=0; i<n; i++) {
+ vtype.push_back(initialRecType(vdef[i]));
+ }
+
+ assert (int(vrec.size())==n);
+ assert (int(vdef.size())==n);
+ assert (int(vtype.size())==n);
+
+ // find least fixpoint
+ for (bool finished = false; !finished; ) {
+
+ // init recursive types
+ CTree::startNewVisit();
+ for (int i=0; i<n; i++) {
+ setSigType(vrec[i], vtype[i]);
+ vrec[i]->setVisited();
+ }
+
+ // compute recursive types
+ for (int i=0; i<n; i++) {
+ vtype[i] = T(vdef[i], NULLTYPEENV);
+ }
+
+ // check finished
+ finished = true;
+ for (int i=0; i<n; i++) {
+ //cerr << i << "-" << *vrec[i] << ":" << *getSigType(vrec[i]) << " => " << *vtype[i] << endl;
+ finished = finished & (getSigType(vrec[i]) == vtype[i]);
+ }
+ }
+
+ // type full term
+ T(sig, NULLTYPEENV);
+
+#if 0
+ //cerr << TABBER << "COUNT INFERENCE " << countInferences << " AT TIME " << clock()/CLOCKS_PER_SEC << 's' << endl;
+ fixInferredType(sig, NULLTYPEENV);
+ //cerr << --TABBER << "EXIT TYPE ANNOTATION OF " << *sig << " AT TIME " << clock()/CLOCKS_PER_SEC << 's' << endl;
+
+#if 0
+ bool success;
+ Tree RE = inferreMultiRates(sig, success);
+ if (success) {
+ printRateEnvironment(cerr, RE); cerr << endl;
+ } else {
+ cerr << "ERROR can't inferre rate environment of " << ppsig(sig) << endl;
+ }
+#else
+ //RateInferrer R(sig);
+
+#endif
+#endif
+
+}
+
+
+void annotationStatistics()
+{
+ cerr << TABBER << "COUNT INFERENCE " << countInferences << " AT TIME " << clock()/CLOCKS_PER_SEC << 's' << endl;
+ cerr << TABBER << "COUNT ALLOCATION " << AudioType::gAllocationCount << endl;
+ cerr << TABBER << "COUNT MAXIMAL " << countMaximal << endl;
+}
+
+/**
+ * Retrieve the type of sig and check it exists. Produces an
+ * error if the signal has no type associated
+ * @param sig the signal we want to know the type
+ * @return the type of the signal
+ */
+Type getCertifiedSigType(Tree sig)
+{
+ Type ty = getSigType(sig);
+ assert(ty);
+ return ty;
+}
+
+
+
+/***********************************************
+ * Set and get the type property of a signal
+ * (we suppose the signal have been previously
+ * annotated with type information)
+ ***********************************************/
+
+/**
+ * Set the type annotation of sig
+ * @param sig the signal we want to type
+ * @param t the type of the signal
+ */
+static void setSigType(Tree sig, Type t)
+{
+ TRACE(cerr << TABBER << "SET FIX TYPE OF " << *sig << " TO TYPE " << *t << endl;)
+ sig->setType(t);
+}
+
+
+/**
+ * Retrieve the type annotation of sig
+ * @param sig the signal we want to know the type
+ */
+static Type getSigType(Tree sig)
+{
+ AudioType* ty = (AudioType*) sig->getType();
+ if (ty == 0)
+ TRACE(cerr << TABBER << "GET FIX TYPE OF " << *sig << " HAS NO TYPE YET" << endl;)
+ else
+ TRACE(cerr << TABBER << "GET FIX TYPE OF " << *sig << " IS TYPE " << *ty << endl;)
+ return ty;
+}
+
+
+
+
+
+/**************************************************************************
+
+ Type Inference System
+
+***************************************************************************/
+
+
+/**************************************************************************
+
+ Infered Type property
+
+***************************************************************************/
+
+/**
+ * Shortcut to getOrInferType, retrieve or infere the type of a term according to its surrounding type environment
+ * @param sig the signal to analyze
+ * @param env the type environment
+ * @return the type of sig according to environment env
+ * @see getCertifiedSigType
+ */
+static Type T(Tree term, Tree ignoreenv)
+{
+ TRACE(cerr << ++TABBER << "ENTER T() " << *term << endl;)
+
+ if (term->isAlreadyVisited()) {
+ Type ty = getSigType(term);
+ TRACE(cerr << --TABBER << "EXIT 1 T() " << *term << " AS TYPE " << *ty << endl);
+ return ty;
+
+ } else {
+ Type ty = infereSigType(term, ignoreenv);
+ setSigType(term,ty);
+ term->setVisited();
+ TRACE(cerr << --TABBER << "EXIT 2 T() " << *term << " AS TYPE " << *ty << endl);
+ return ty;
+ }
+}
+
+
+/**
+ * Infere the type of a term according to its surrounding type environment
+ * @param sig the signal to aanlyze
+ * @param env the type environment
+ * @return the type of sig according to environment env
+ */
+
+static Type infereSigType(Tree sig, Tree env)
+{
+ int i;
+ double r;
+ Tree sel, s1, s2, s3, ff, id, ls, l, x, y, z, u, var, body, type, name, file;
+ Tree label, cur, min, max, step;
+
+ countInferences++;
+
+ if ( getUserData(sig) ) return infereXType(sig, env);
+
+ else if (isSigInt(sig, &i)) { Type t = makeSimpleType(kInt, kKonst, kComp, kVect, kNum, interval(i));
+ /*sig->setType(t);*/ return t; }
+
+ else if (isSigReal(sig, &r)) { Type t = makeSimpleType(kReal, kKonst, kComp, kVect, kNum, interval(r));
+ /*sig->setType(t);*/ return t; }
+
+ else if (isSigInput(sig, &i)) { /*sig->setType(TINPUT);*/ return TINPUT; }
+
+ else if (isSigOutput(sig, &i, s1)) return sampCast(T(s1,env));
+
+ else if (isSigDelay1(sig, s1)) {
+ Type t = T(s1,env);
+ return castInterval(sampCast(t), reunion(t->getInterval(), interval(0,0)));
+ }
+
+ else if (isSigPrefix(sig, s1, s2)) {
+ Type t1 = T(s1,env);
+ Type t2 = T(s2,env);
+ checkInit(t1);
+ return castInterval(sampCast(t1|t2), reunion(t1->getInterval(), t2->getInterval()));
+ }
+
+ else if (isSigFixDelay(sig, s1, s2)) {
+ Type vt1 = T(s1,env);
+ vector<int> dim;
+ Type t1 = vt1->dimensions(dim);
+ Type t2 = T(s2,env);
+ interval i = t2->getInterval();
+
+// cerr << "for sig fix delay : s1 = "
+// << t1 << ':' << ppsig(s1) << ", s2 = "
+// << t2 << ':' << ppsig(s2) << endl;
+ if (!i.valid) {
+ cerr << "ERROR : can't compute the min and max values of : " << ppsig(s2) << endl;
+ cerr << " used in delay expression : " << ppsig(sig) << endl;
+ cerr << " (probably a recursive signal)" << endl;
+ exit(1);
+ } else if (i.lo < 0) {
+ cerr << "ERROR : possible negative values of : " << ppsig(s2) << endl;
+ cerr << " used in delay expression : " << ppsig(sig) << endl;
+ cerr << " " << i << endl;
+ exit(1);
+ }
+
+ Type nt1 = castInterval(sampCast(t1), reunion(t1->getInterval(), interval(0,0)));
+ return makeVectorType(nt1,dim);
+ }
+
+ else if (isSigBinOp(sig, &i, s1, s2)) {
+
+ Type t1 = T(s1,env);
+ Type t2 = T(s2,env);
+
+ vector<int> D1, D2, D3;
+ Type b1 = t1->dimensions(D1);
+ Type b2 = t2->dimensions(D2);
+
+ if (maxdimensions(D1, D2, D3)) {
+ Type b3 = castInterval(b1 | b2, arithmetic(i, b1->getInterval(), b2->getInterval()));
+ if ((i>=kGT) && (i<=kNE)) b3 = intCast(b3);
+ Type t3 = makeVectorType(b3, D3);
+ return t3;
+ } else {
+ cerr << "ERROR operation on incompatible types : " << *t1 << " and " << *t2
+ << " in expression : " << ppsig(sig) << endl;
+ exit(1);
+ }
+ //cerr <<"type rule for : " << ppsig(sig) << " -> " << *t3 << endl;
+ //return (!gVectorSwitch && (i>=kGT) && (i<=kNE)) ? intCast(t3) : t3; // for comparaison operation the result is int
+ //return ((i>=kGT) && (i<=kNE)) ? intCast(t3) : t3; // for comparaison operation the result is int
+ }
+
+ else if (isSigIntCast(sig, s1)) return intCast(T(s1,env));
+
+ else if (isSigFloatCast(sig, s1)) return floatCast(T(s1,env));
+
+ else if (isSigFFun(sig, ff, ls)) return infereFFType(ff,ls,env);
+
+ else if (isSigFConst(sig,type,name,file)) return infereFConstType(type);
+
+ else if (isSigFVar(sig,type,name,file)) return infereFVarType(type);
+
+ else if (isSigButton(sig)) { /*sig->setType(TGUI01);*/ return TGUI01; }
+
+ else if (isSigCheckbox(sig)) { /*sig->setType(TGUI01);*/ return TGUI01; }
+
+ else if (isSigVSlider(sig,label,cur,min,max,step))
+ return castInterval(TGUI,interval(tree2float(min),tree2float(max)));
+
+ else if (isSigHSlider(sig,label,cur,min,max,step))
+ return castInterval(TGUI,interval(tree2float(min),tree2float(max)));
+
+ else if (isSigNumEntry(sig,label,cur,min,max,step))
+ return castInterval(TGUI,interval(tree2float(min),tree2float(max)));
+
+ else if (isSigHBargraph(sig, l, x, y, s1)) return T(s1,env);
+
+ else if (isSigVBargraph(sig, l, x, y, s1)) return T(s1,env);
+
+ else if (isSigAttach(sig, s1, s2)) { T(s2,env); return T(s1,env); }
+
+ else if (isRec(sig, var, body)) return infereRecType(sig, body, env);
+
+ else if (isProj(sig, &i, s1)) return infereProjType(T(s1,env),i,kScal);
+
+ else if (isSigTable(sig, id, s1, s2)) { checkInt(checkInit(T(s1,env))); return makeTableType(checkInit(T(s2,env))); }
+
+ else if (isSigWRTbl(sig, id, s1, s2, s3)) return infereWriteTableType(T(s1,env), T(s2,env), T(s3,env));
+
+ else if (isSigRDTbl(sig, s1, s2)) return infereReadTableType(T(s1,env), T(s2,env));
+
+ else if (isSigGen(sig, s1)) return T(s1,NULLTYPEENV);
+
+ else if ( isSigDocConstantTbl(sig, x, y) ) return infereDocConstantTblType(T(x,env), T(y,env));
+ else if ( isSigDocWriteTbl(sig,x,y,z,u) ) return infereDocWriteTblType(T(x,env), T(y,env), T(z,env), T(u,env));
+ else if ( isSigDocAccessTbl(sig, x, y) ) return infereDocAccessTblType(T(x,env), T(y,env));
+
+ else if (isSigSelect2(sig,sel,s1,s2)) {
+ SimpleType *st1, *st2, *stsel;
+
+ st1 = isSimpleType(T(s1,env));
+ st2 = isSimpleType(T(s2,env));
+ stsel = isSimpleType(T(sel,env));
+
+ return makeSimpleType( st1->nature()|st2->nature(),
+ st1->variability()|st2->variability()|stsel->variability(),
+ st1->computability()|st2->computability()|stsel->computability(),
+ st1->vectorability()|st2->vectorability()|stsel->vectorability(),
+ st1->boolean()|st2->boolean(),
+ reunion(st1->getInterval(), st2->getInterval())
+ );
+ }
+
+ else if (isSigSelect3(sig,sel,s1,s2,s3)) { return T(sel,env)|T(s1,env)|T(s2,env)|T(s3,env); }
+
+ else if (isNil(sig)) { Type t = new TupletType(); /*sig->setType(t);*/ return t; }
+
+ else if (isList(sig)) { return T( hd(sig),env ) * T( tl(sig),env ); }
+
+ else if ( isSigVectorize(sig, x, y) ) return infereVectorizeType(sig, T(x,env), T(y,env));
+ else if ( isSigSerialize(sig, x) ) return infereSerializeType(sig, T(x,env));
+ else if ( isSigConcat(sig, x, y) ) return infereConcatType(T(x,env), T(y,env));
+ else if ( isSigVectorAt(sig, x, y) ) return infereVectorAtType(T(x,env), T(y,env));
+
+ else if ( isSigUpSample(sig, x, y) ) { T(x,env); return T(y,env); }
+ else if ( isSigDownSample(sig, x, y) ) { T(x,env); return T(y,env); }
+
+ // unrecognized signal here
+ fprintf(stderr, "ERROR in ***infereSigType()***, unrecognized signal : "); print(sig, stderr); fprintf(stderr, "\n");
+ exit(1);
+ return 0;
+}
+
+
+/**
+ * Infere the type of a projection (selection) of a tuplet element
+ */
+static Type infereProjType(Type t, int i, int vec)
+{
+ TupletType* tt = isTupletType(t);
+ if (tt == 0) {
+ cerr << "ERROR infering projection type, not a tuplet type : " << t << endl;
+ exit(1);
+ }
+ //return (*tt)[i] ->promoteVariability(t->variability())
+ // ->promoteComputability(t->computability());
+ Type temp = (*tt)[i] ->promoteVariability(t->variability())
+ ->promoteComputability(t->computability())
+ ->promoteVectorability(vec/*t->vectorability()*/);
+ //->promoteBooleanity(t->boolean());
+
+ if(vec==kVect) temp = vecCast(temp);
+ //cerr << "infereProjType(" << t << ',' << i << ',' << vec << ")" << " -> " << temp << endl;
+
+ return temp;
+}
+
+
+
+/**
+ * Infere the type of the result of writing into a table
+ */
+static Type infereWriteTableType(Type tbl, Type wi, Type wd)
+{
+ TableType* tt = isTableType(tbl);
+ if (tt == 0) {
+ cerr << "ERROR infering write table type, wrong table type : " << tbl << endl;
+ exit(1);
+ }
+ SimpleType* st = isSimpleType(wi);
+ if (st == 0 || st->nature() > kInt) {
+ cerr << "ERROR infering write table type, wrong write index type : " << wi << endl;
+ exit(1);
+ }
+
+ int n = tt->nature();
+ int v = wi->variability() | wd->variability();
+ int c = wi->computability() | wd->computability();
+ int vec = wi->vectorability() | wd->vectorability();
+
+ return makeTableType(tt->content(), n, v, c, vec);
+
+}
+
+
+
+/**
+ * Infere the type of the result of reading a table
+ */
+static Type infereReadTableType(Type tbl, Type ri)
+{
+ TableType* tt = isTableType(tbl);
+ if (tt == 0) {
+ cerr << "ERROR infering read table type, wrong table type : " << tbl << endl;
+ exit(1);
+ }
+ SimpleType* st = isSimpleType(ri);
+ if (st == 0 || st->nature() > kInt) {
+ cerr << "ERROR infering read table type, wrong write index type : " << ri << endl;
+ exit(1);
+ }
+
+ Type temp = tt->content()->promoteVariability(ri->variability()|tt->variability())
+ ->promoteComputability(ri->computability()|tt->computability())
+ ->promoteVectorability(ri->vectorability()|tt->vectorability())
+ ->promoteBoolean(ri->boolean()|tt->boolean())
+ ;
+
+ return temp;
+
+}
+
+
+static Type infereDocConstantTblType(Type size, Type init)
+{
+ checkKonst(checkInt(checkInit(size)));
+
+ return init;
+}
+
+static Type infereDocWriteTblType(Type size, Type init, Type widx, Type wsig)
+{
+ checkKonst(checkInt(checkInit(size)));
+
+ Type temp = init
+ ->promoteVariability(kSamp) // difficult to tell, therefore kSamp to be safe
+ ->promoteComputability(widx->computability()|wsig->computability())
+ ->promoteVectorability(kScal) // difficult to tell, therefore kScal to be safe
+ ->promoteNature(wsig->nature()) // nature of the initial and written signal
+ ->promoteBoolean(wsig->boolean()) // booleanity of the initial and written signal
+ ;
+ return temp;
+}
+
+static Type infereDocAccessTblType(Type tbl, Type ridx)
+{
+ Type temp = tbl
+ ->promoteVariability(ridx->variability())
+ ->promoteComputability(ridx->computability())
+ ->promoteVectorability(ridx->vectorability())
+ ;
+ return temp;
+}
+
+
+/**
+ * Compute an initial type solution for a recursive block
+ * E1,E2,...En -> TREC,TREC,...TREC
+ */
+static Type initialRecType(Tree t)
+{
+ assert (isList(t));
+
+ vector<Type> v;
+ while (isList(t)) { v.push_back(TREC); t = tl(t); };
+ return new TupletType(v);
+}
+
+
+/**
+ * Infere the type of e recursive block by trying solutions of
+ * increasing generality
+ */
+static Type infereRecType (Tree sig, Tree body, Tree env)
+{
+ assert(false); // we should not come here
+ return 0;
+}
+
+
+/**
+ * Infere the type of a foreign function call
+ */
+static Type infereFFType (Tree ff, Tree ls, Tree env)
+{
+ // une primitive externe ne peut pas se calculer au plus tot qu'a
+ // l'initialisation. Sa variabilite depend de celle de ses arguments
+ // sauf si elle n'en pas, auquel cas on considere que c'est comme
+ // rand() c'est a dire que le resultat varie a chaque appel.
+ if (ffarity(ff)==0) {
+ // case of functions like rand()
+ return makeSimpleType(ffrestype(ff),kSamp,kInit,kVect,kNum, interval());
+ } else {
+ // otherwise variability and computability depends
+ // arguments (OR of all arg types)
+ Type t = makeSimpleType(kInt,kKonst,kInit,kVect,kNum, interval());
+ while (isList(ls)) { t = t|T(hd(ls),env); ls=tl(ls); }
+ // but the result type is defined by the function
+
+ //return t;
+ return makeSimpleType( ffrestype(ff),
+ t->variability(),
+ t->computability(),
+ t->vectorability(),
+ t->boolean(),
+ interval() );
+ }
+}
+
+
+/**
+ * Infere the type of a foreign constant
+ */
+static Type infereFConstType (Tree type)
+{
+ // une constante externe ne peut pas se calculer au plus tot qu'a
+ // l'initialisation. Elle est constante, auquel cas on considere que c'est comme
+ // rand() c'est a dire que le resultat varie a chaque appel.
+ return makeSimpleType(tree2int(type),kKonst,kInit,kVect,kNum, interval());
+}
+
+
+/**
+ * Infere the type of a foreign variable
+ */
+static Type infereFVarType (Tree type)
+{
+ // une variable externe ne peut pas se calculer au plus tot qu'a
+ // l'execution. Elle est varie par blocs comme les éléments d'interface utilisateur.
+ return makeSimpleType(tree2int(type),kBlock,kExec,kVect,kNum, interval());
+}
+
+
+/**
+ * Infere the type of an extended (primitive) block
+ */
+static Type infereXType(Tree sig, Tree env)
+{
+ //cerr << "infereXType :" << endl;
+ //cerr << "infereXType of " << *sig << endl;
+ xtended* p = (xtended*) getUserData(sig);
+ vector<Type> vt;
+
+ for (int i = 0; i < sig->arity(); i++) vt.push_back(T(sig->branch(i), env));
+ return p->infereSigType(vt);
+}
+
+
+
+
+
+/**
+ * Compute the resulting interval of an arithmetic operation
+ * @param op code of the operation
+ * @param s1 interval of the left operand
+ * @param s2 interval of the right operand
+ * @return the resulting interval
+ */
+
+static interval arithmetic (int opcode, const interval& x, const interval& y)
+{
+ switch (opcode) {
+ case kAdd: return x+y;
+ case kSub: return x-y;
+ case kMul: return x*y;
+ case kDiv: return x/y;
+ case kRem: return x%y;
+ case kLsh: return x<<y;
+ case kRsh: return x>>y;
+ case kGT: return x>y;
+ case kLT: return x<y;
+ case kGE: return x>=y;
+ case kLE: return x<=y;
+ case kEQ: return x==y;
+ case kNE: return x!=y;
+ case kAND: return x&y;
+ case kOR: return x|y;
+ case kXOR: return x^y;
+ default:
+ cerr << "Unrecognized opcode : " << opcode << endl;
+ exit(1);
+ }
+
+ return interval();
+}
+
+
+
+static Type infereVectorizeType(Tree sig, Type Tsize, Type T)
+{
+ SimpleType* st = isSimpleType(Tsize);
+ if (st && st->nature()==kInt) {
+ interval i = Tsize->getInterval();
+ if (i.valid && i.lo >= 0 && i.lo == i.hi) {
+ return new VectorType(int(i.lo+0.5), T);
+ }
+ }
+ cerr << "ERROR in expression : " << ppsig(sig) << endl;
+ cerr << "the size of the vector is not of a valide type : " << *Tsize << endl;
+ exit(1);
+}
+
+static Type infereSerializeType(Tree sig, Type Tvec)
+{
+ VectorType* vt = isVectorType(Tvec);
+ if (vt) {
+ return vt->content();
+ } else {
+ cerr << "ERROR in expression : " << ppsig(sig) << endl;
+ cerr << "the 'serialize' operation can only be used on vectorized signals" << endl;
+ exit(1);
+ }
+}
+
+static Type infereConcatType(Type Tvec1, Type Tvec2)
+{
+ VectorType* vt1 = isVectorType(Tvec1);
+ VectorType* vt2 = isVectorType(Tvec2);
+
+ if (vt1 && vt2) {
+ Type ct1 = vt1->content();
+ Type ct2 = vt2->content();
+ if (ct1 == ct2) {
+ return new VectorType(vt1->size()+vt2->size(), ct1);
+ }
+ }
+ cerr << "ERROR in vector concatenation, the types : " << Tvec1 << " and " << Tvec2 << " are incompatible" << endl;
+ exit(1);
+}
+
+static Type infereVectorAtType(Type Tvec, Type Tidx)
+{
+ VectorType* vt = isVectorType(Tvec);
+ SimpleType* it = isSimpleType(Tidx);
+
+ if (vt && it) {
+ Type ct = vt->content();
+ int n = vt->size();
+ interval i = it->getInterval();
+ if (i.valid && i.lo >= 0 && i.hi <= n) {
+ return ct;
+ }
+ }
+ cerr << "ERROR in vector access, with types : " << Tvec << " and " << Tidx << endl;
+ exit(1);
+}