FAUST compiler  0.9.9.6b8
sigtyperules.cpp
Go to the documentation of this file.
00001 /************************************************************************
00002  ************************************************************************
00003     FAUST compiler
00004     Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
00005     ---------------------------------------------------------------------
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  ************************************************************************
00020  ************************************************************************/
00021 
00022 
00023 
00024 #include <stdio.h>
00025 #include <assert.h>
00026 #include <iostream>
00027 #include <fstream>
00028 #include <time.h>
00029 
00030 
00031 #include "sigtype.hh"
00032 #include "sigprint.hh"
00033 #include "ppsig.hh"
00034 //#include "prim.hh"
00035 #include "prim2.hh"
00036 #include "tlib.hh"
00037 #include "sigtyperules.hh"
00038 #include "xtended.hh"
00039 #include "recursivness.hh"
00040 
00041 
00042 //--------------------------------------------------------------------------
00043 // prototypes
00044 
00045 static void setSigType(Tree sig, Type t);
00046 static Type getSigType(Tree sig);
00047 static Type initialRecType(Tree t);
00048 
00049 static Type T(Tree term, Tree env);
00050 
00051 static Type infereSigType(Tree term, Tree env);
00052 static Type infereFFType (Tree ff, Tree ls, Tree env);
00053 static Type infereFConstType (Tree type);
00054 static Type infereFVarType (Tree type);
00055 static Type infereRecType (Tree var, Tree body, Tree env);
00056 static Type infereReadTableType(Type tbl, Type ri);
00057 static Type infereWriteTableType(Type tbl, Type wi, Type wd);
00058 static Type infereProjType(Type t, int i, int vec);
00059 static Type infereXType(Tree sig, Tree env);
00060 static Type infereDocConstantTblType(Type size, Type init);
00061 static Type infereDocWriteTblType(Type size, Type init, Type widx, Type wsig);
00062 static Type infereDocAccessTblType(Type tbl, Type ridx);
00063 static interval arithmetic (int opcode, const interval& x, const interval& y);
00064 
00065 
00066 
00067 // Uncomment to activate type inferrence tracing
00068 //#define TRACE(x) x
00069 #define TRACE(x) 0;
00070 
00071 
00075 static Tree NULLTYPEENV = tree(symbol("NullTypeEnv"));
00076 
00077 static int countInferences;
00078 static int countMaximal;
00079 
00080 
00081 
00087 void typeAnnotation(Tree sig)
00088 {
00089     Tree            sl = symlist(sig);
00090     int             n = len(sl);
00091 
00092     vector<Tree>    vrec, vdef;
00093     vector<Type>    vtype;
00094 
00095     //cerr << "Symlist " << *sl << endl;
00096     for (Tree l=sl; isList(l); l=tl(l)) {
00097         Tree    id, body;
00098         assert(isRec(hd(l), id, body));
00099 
00100         vrec.push_back(hd(l));
00101         vdef.push_back(body);
00102     }
00103 
00104     // init recursive types
00105     for (int i=0; i<n; i++) {
00106         vtype.push_back(initialRecType(vdef[i]));
00107     }
00108 
00109     assert (int(vrec.size())==n);
00110     assert (int(vdef.size())==n);
00111     assert (int(vtype.size())==n);
00112 
00113     // find least fixpoint
00114     for (bool finished = false; !finished; ) {
00115 
00116         // init recursive types
00117         CTree::startNewVisit();
00118         for (int i=0; i<n; i++) {
00119             setSigType(vrec[i], vtype[i]);
00120             vrec[i]->setVisited();
00121         }
00122 
00123         // compute recursive types
00124         for (int i=0; i<n; i++) {
00125             vtype[i] = T(vdef[i], NULLTYPEENV);
00126         }
00127 
00128         // check finished
00129         finished = true;
00130         for (int i=0; i<n; i++) {
00131             //cerr << i << "-" << *vrec[i] << ":" << *getSigType(vrec[i]) << " => " << *vtype[i] << endl;
00132             finished =  finished & (getSigType(vrec[i]) == vtype[i]);
00133         }
00134     }
00135 
00136     // type full term
00137     T(sig, NULLTYPEENV);
00138 }
00139 
00140 
00141 void annotationStatistics()
00142 {
00143     cerr << TABBER << "COUNT INFERENCE  " << countInferences << " AT TIME " << clock()/CLOCKS_PER_SEC << 's' << endl;
00144     cerr << TABBER << "COUNT ALLOCATION " << AudioType::gAllocationCount << endl;
00145     cerr << TABBER << "COUNT MAXIMAL " << countMaximal << endl;
00146 }
00147 
00154 Type getCertifiedSigType(Tree sig)
00155 {
00156     Type ty = getSigType(sig);
00157     assert(ty);
00158     return ty;
00159 }
00160 
00161 
00162 
00163 /***********************************************
00164  * Set and get the type property of a signal
00165  * (we suppose the signal have been previously
00166  * annotated with type information)
00167  ***********************************************/
00168 
00174 static void setSigType(Tree sig, Type t)
00175 {
00176     TRACE(cerr << TABBER << "SET FIX TYPE OF " << *sig << " TO TYPE " << *t << endl;)
00177     sig->setType(t);
00178 }
00179 
00180 
00185 static Type getSigType(Tree sig)
00186 {
00187     AudioType* ty = (AudioType*) sig->getType();
00188     if (ty == 0)
00189         TRACE(cerr << TABBER << "GET FIX TYPE OF " << *sig << " HAS NO TYPE YET" << endl;)
00190     else
00191         TRACE(cerr << TABBER << "GET FIX TYPE OF " << *sig << " IS TYPE " << *ty << endl;)
00192     return ty;
00193 }
00194 
00195 
00196 
00197 
00198 
00199 /**************************************************************************
00200 
00201                         Type Inference System
00202 
00203 ***************************************************************************/
00204 
00205 /**************************************************************************
00206 
00207                         Infered Type property
00208 
00209 ***************************************************************************/
00210 
00218 static Type T(Tree term, Tree ignoreenv)
00219 {
00220     TRACE(cerr << ++TABBER << "ENTER T() " << *term << endl;)
00221 
00222     if (term->isAlreadyVisited()) {
00223         Type    ty =  getSigType(term);
00224         TRACE(cerr << --TABBER << "EXIT 1 T() " << *term << " AS TYPE " << *ty << endl);
00225         return ty;
00226 
00227     } else {
00228         Type ty = infereSigType(term, ignoreenv);
00229         setSigType(term,ty);
00230         term->setVisited();
00231         TRACE(cerr << --TABBER << "EXIT 2 T() " << *term << " AS TYPE " << *ty << endl);
00232         return ty;
00233     }
00234 }
00235 
00236 
00244 static Type infereSigType(Tree sig, Tree env)
00245 {
00246     int         i;
00247     double      r;
00248     Tree        sel, s1, s2, s3, ff, id, ls, l, x, y, z, u, var, body, type, name, file;
00249     Tree        label, cur, min, max, step;
00250 
00251     countInferences++;
00252 
00253          if ( getUserData(sig) )            return infereXType(sig, env);
00254 
00255     else if (isSigInt(sig, &i))             {   Type t = makeSimpleType(kInt, kKonst, kComp, kVect, kNum, interval(i));
00256                                                 /*sig->setType(t);*/ return t; }
00257 
00258     else if (isSigReal(sig, &r))            {   Type t = makeSimpleType(kReal, kKonst, kComp, kVect, kNum, interval(r));
00259                                                 /*sig->setType(t);*/ return t; }
00260 
00261     else if (isSigInput(sig, &i))           {   /*sig->setType(TINPUT);*/ return TINPUT; }
00262 
00263     else if (isSigOutput(sig, &i, s1))      return sampCast(T(s1,env));
00264 
00265     else if (isSigDelay1(sig, s1))          {
00266         Type t = T(s1,env);
00267         return castInterval(sampCast(t), reunion(t->getInterval(), interval(0,0)));
00268     }
00269 
00270     else if (isSigPrefix(sig, s1, s2))      {
00271         Type t1 = T(s1,env);
00272         Type t2 = T(s2,env);
00273         checkInit(t1);
00274         return castInterval(sampCast(t1|t2), reunion(t1->getInterval(), t2->getInterval()));
00275     }
00276 
00277     else if (isSigFixDelay(sig, s1, s2))        {
00278         Type t1 = T(s1,env);
00279         Type t2 = T(s2,env);
00280         interval i = t2->getInterval();
00281 
00282 //        cerr << "for sig fix delay : s1 = "
00283 //              << t1 << ':' << ppsig(s1) << ", s2 = "
00284 //                << t2 << ':' << ppsig(s2) << endl;
00285         if (!i.valid) {
00286             cerr << "ERROR : can't compute the min and max values of : " << ppsig(s2) << endl;
00287             cerr << "        used in delay expression : " << ppsig(sig) << endl;
00288             cerr << "        (probably a recursive signal)" << endl;
00289             exit(1);
00290         } else if (i.lo < 0) {
00291             cerr << "ERROR : possible negative values of : " << ppsig(s2) << endl;
00292             cerr << "        used in delay expression : " << ppsig(sig) << endl;
00293             cerr << "        " << i << endl;
00294             exit(1);
00295         }
00296 
00297         return castInterval(sampCast(t1), reunion(t1->getInterval(), interval(0,0)));
00298     }
00299 
00300     else if (isSigBinOp(sig, &i, s1, s2)) {
00301         //Type t = T(s1,env)|T(s2,env);
00302         Type t1 = T(s1,env);
00303         Type t2 = T(s2,env);
00304         Type t3 = castInterval(t1 | t2, arithmetic(i, t1->getInterval(), t2->getInterval()));
00305         //cerr <<"type rule for : " << ppsig(sig) << " -> " << *t3 << endl;
00306         //return (!gVectorSwitch && (i>=kGT) && (i<=kNE)) ?  intCast(t3) : t3; // for comparaison operation the result is int
00307         return ((i>=kGT) && (i<=kNE)) ?  intCast(t3) : t3; // for comparaison operation the result is int
00308     }
00309 
00310     else if (isSigIntCast(sig, s1))             return intCast(T(s1,env));
00311 
00312     else if (isSigFloatCast(sig, s1))           return floatCast(T(s1,env));
00313 
00314     else if (isSigFFun(sig, ff, ls))            return infereFFType(ff,ls,env);
00315 
00316     else if (isSigFConst(sig,type,name,file))   return infereFConstType(type);
00317 
00318     else if (isSigFVar(sig,type,name,file))     return infereFVarType(type);
00319 
00320     else if (isSigButton(sig))                  { /*sig->setType(TGUI01);*/ return TGUI01; }
00321 
00322     else if (isSigCheckbox(sig))                { /*sig->setType(TGUI01);*/ return TGUI01; }
00323 
00324     else if (isSigVSlider(sig,label,cur,min,max,step))
00325                                                 return castInterval(TGUI,interval(tree2float(min),tree2float(max)));
00326 
00327     else if (isSigHSlider(sig,label,cur,min,max,step))
00328                                                 return castInterval(TGUI,interval(tree2float(min),tree2float(max)));
00329 
00330     else if (isSigNumEntry(sig,label,cur,min,max,step))
00331                                                 return castInterval(TGUI,interval(tree2float(min),tree2float(max)));
00332 
00333     else if (isSigHBargraph(sig, l, x, y, s1))  return T(s1,env);
00334 
00335     else if (isSigVBargraph(sig, l, x, y, s1))  return T(s1,env);
00336 
00337     else if (isSigAttach(sig, s1, s2))          { T(s2,env); return T(s1,env); }
00338 
00339     else if (isRec(sig, var, body))             return infereRecType(sig, body, env);
00340 
00341     else if (isProj(sig, &i, s1))               return infereProjType(T(s1,env),i,kScal);
00342 
00343     else if (isSigTable(sig, id, s1, s2))       { checkInt(checkInit(T(s1,env))); return makeTableType(checkInit(T(s2,env))); }
00344 
00345     else if (isSigWRTbl(sig, id, s1, s2, s3))   return infereWriteTableType(T(s1,env), T(s2,env), T(s3,env));
00346 
00347     else if (isSigRDTbl(sig, s1, s2))           return infereReadTableType(T(s1,env), T(s2,env));
00348 
00349     else if (isSigGen(sig, s1))                 return T(s1,NULLTYPEENV);
00350 
00351     else if ( isSigDocConstantTbl(sig, x, y) )  return infereDocConstantTblType(T(x,env), T(y,env));
00352     else if ( isSigDocWriteTbl(sig,x,y,z,u) )   return infereDocWriteTblType(T(x,env), T(y,env), T(z,env), T(u,env));
00353     else if ( isSigDocAccessTbl(sig, x, y) )    return infereDocAccessTblType(T(x,env), T(y,env));
00354 
00355     else if (isSigSelect2(sig,sel,s1,s2))       {
00356                                                   SimpleType *st1, *st2, *stsel;
00357 
00358                                                   st1 = isSimpleType(T(s1,env));
00359                                                   st2 = isSimpleType(T(s2,env));
00360                                                   stsel = isSimpleType(T(sel,env));
00361 
00362                                                   return makeSimpleType( st1->nature()|st2->nature(),
00363                                                              st1->variability()|st2->variability()|stsel->variability(),
00364                                                              st1->computability()|st2->computability()|stsel->computability(),
00365                                                              st1->vectorability()|st2->vectorability()|stsel->vectorability(),
00366                                                              st1->boolean()|st2->boolean(),
00367                                                              reunion(st1->getInterval(), st2->getInterval())
00368                                                              );
00369                                                 }
00370 
00371     else if (isSigSelect3(sig,sel,s1,s2,s3))    { return T(sel,env)|T(s1,env)|T(s2,env)|T(s3,env); }
00372 
00373     else if (isNil(sig))                        { Type t = new TupletType(); /*sig->setType(t);*/ return t; }
00374 
00375     else if (isList(sig))                       { return T( hd(sig),env ) * T( tl(sig),env ); }
00376 
00377     // unrecognized signal here
00378     fprintf(stderr, "ERROR infering signal type : unrecognized signal  : "); print(sig, stderr); fprintf(stderr, "\n");
00379     exit(1);
00380     return 0;
00381 }
00382 
00383 
00384 
00388 static Type infereProjType(Type t, int i, int vec)
00389 {
00390     TupletType* tt = isTupletType(t);
00391     if (tt == 0) {
00392         cerr << "ERROR infering projection type, not a tuplet type : " << t << endl;
00393         exit(1);
00394     }
00395     //return (*tt)[i]   ->promoteVariability(t->variability())
00396     //      ->promoteComputability(t->computability());
00397     Type temp = (*tt)[i]    ->promoteVariability(t->variability())
00398       ->promoteComputability(t->computability())
00399       ->promoteVectorability(vec/*t->vectorability()*/);
00400     //->promoteBooleanity(t->boolean());
00401 
00402     if(vec==kVect) temp = vecCast(temp);
00403     //cerr << "infereProjType(" << t << ',' << i << ',' << vec << ")" << " -> " << temp << endl;
00404 
00405     return temp;
00406 }
00407 
00408 
00409 
00413 static Type infereWriteTableType(Type tbl, Type wi, Type wd)
00414 {
00415     TableType* tt = isTableType(tbl);
00416     if (tt == 0) {
00417         cerr << "ERROR infering write table type, wrong table type : " << tbl << endl;
00418         exit(1);
00419     }
00420     SimpleType* st = isSimpleType(wi);
00421     if (st == 0 || st->nature() > kInt) {
00422         cerr << "ERROR infering write table type, wrong write index type : " << wi << endl;
00423         exit(1);
00424     }
00425 
00426     int n = tt->nature();
00427     int v = wi->variability() | wd->variability();
00428     int c = wi->computability() | wd->computability();
00429     int vec = wi->vectorability() | wd->vectorability();
00430 
00431     return makeTableType(tt->content(), n, v, c, vec);
00432 
00433 }
00434 
00435 
00436 
00440 static Type infereReadTableType(Type tbl, Type ri)
00441 {
00442     TableType*  tt = isTableType(tbl);
00443     if (tt == 0) {
00444         cerr << "ERROR infering read table type, wrong table type : " << tbl << endl;
00445         exit(1);
00446     }
00447     SimpleType* st = isSimpleType(ri);
00448     if (st == 0 || st->nature() > kInt) {
00449         cerr << "ERROR infering read table type, wrong write index type : " << ri << endl;
00450         exit(1);
00451     }
00452 
00453     Type temp =  tt->content()->promoteVariability(ri->variability()|tt->variability())
00454       ->promoteComputability(ri->computability()|tt->computability())
00455       ->promoteVectorability(ri->vectorability()|tt->vectorability())
00456       ->promoteBoolean(ri->boolean()|tt->boolean())
00457       ;
00458 
00459     return temp;
00460 
00461 }
00462 
00463 
00464 static Type infereDocConstantTblType(Type size, Type init)
00465 {
00466     checkKonst(checkInt(checkInit(size)));
00467 
00468     return init;
00469 }
00470 
00471 static Type infereDocWriteTblType(Type size, Type init, Type widx, Type wsig)
00472 {
00473     checkKonst(checkInt(checkInit(size)));
00474 
00475     Type temp =  init
00476       ->promoteVariability(kSamp)       // difficult to tell, therefore kSamp to be safe
00477       ->promoteComputability(widx->computability()|wsig->computability())
00478       ->promoteVectorability(kScal)     // difficult to tell, therefore kScal to be safe
00479       ->promoteNature(wsig->nature())   // nature of the initial and written signal
00480       ->promoteBoolean(wsig->boolean()) // booleanity of the initial and written signal
00481       ;
00482     return temp;
00483 }
00484 
00485 static Type infereDocAccessTblType(Type tbl, Type ridx)
00486 {
00487     Type temp =  tbl
00488       ->promoteVariability(ridx->variability())
00489       ->promoteComputability(ridx->computability())
00490       ->promoteVectorability(ridx->vectorability())
00491       ;
00492     return temp;
00493 }
00494 
00495 
00500 static Type initialRecType(Tree t)
00501 {
00502     assert (isList(t));
00503 
00504     vector<Type> v;
00505     while (isList(t)) { v.push_back(TREC); t = tl(t); };
00506     return new TupletType(v);
00507 }
00508 
00509 
00514 static Type infereRecType (Tree sig, Tree body, Tree env)
00515 {
00516     assert(false); // we should not come here
00517     return 0;
00518 }
00519 
00520 
00524 static Type infereFFType (Tree ff, Tree ls, Tree env)
00525 {
00526     // une primitive externe ne peut pas se calculer au plus tot qu'a
00527     // l'initialisation. Sa variabilite depend de celle de ses arguments
00528     // sauf si elle n'en pas, auquel cas on considere que c'est comme
00529     // rand() c'est a dire que le resultat varie a chaque appel.
00530     if (ffarity(ff)==0) {
00531         // case of functions like rand()
00532         return makeSimpleType(ffrestype(ff),kSamp,kInit,kVect,kNum, interval());
00533     } else {
00534         // otherwise variability and computability depends
00535         // arguments (OR of all arg types)
00536         Type t = makeSimpleType(kInt,kKonst,kInit,kVect,kNum, interval());
00537         while (isList(ls)) { t = t|T(hd(ls),env); ls=tl(ls); }
00538         // but the result type is defined by the function
00539 
00540         //return t;
00541         return makeSimpleType(  ffrestype(ff),
00542                                 t->variability(),
00543                                 t->computability(),
00544                                 t->vectorability(),
00545                                 t->boolean(),
00546                                 interval() );
00547     }
00548 }
00549 
00550 
00554 static Type infereFConstType (Tree type)
00555 {
00556     // une constante externe ne peut pas se calculer au plus tot qu'a
00557     // l'initialisation. Elle est constante, auquel cas on considere que c'est comme
00558     // rand() c'est a dire que le resultat varie a chaque appel.
00559     return makeSimpleType(tree2int(type),kKonst,kInit,kVect,kNum, interval());
00560 }
00561 
00562 
00566 static Type infereFVarType (Tree type)
00567 {
00568     // une variable externe ne peut pas se calculer au plus tot qu'a
00569     // l'execution. Elle est varie par blocs comme les éléments d'interface utilisateur.
00570     return makeSimpleType(tree2int(type),kBlock,kExec,kVect,kNum, interval());
00571 }
00572 
00573 
00577 static Type infereXType(Tree sig, Tree env)
00578 {
00579     //cerr << "infereXType :" << endl;
00580     //cerr << "infereXType of " << *sig << endl;
00581     xtended* p = (xtended*) getUserData(sig);
00582     vector<Type> vt;
00583 
00584     for (int i = 0; i < sig->arity(); i++) vt.push_back(T(sig->branch(i), env));
00585     return p->infereSigType(vt);
00586 }
00587 
00588 
00589 
00590 
00591 
00600 static interval arithmetic (int opcode, const interval& x, const interval& y)
00601 {
00602     switch (opcode) {
00603         case kAdd: return x+y;
00604         case kSub: return x-y;
00605         case kMul:  return x*y;
00606         case kDiv: return x/y;
00607         case kRem: return x%y;
00608         case kLsh: return x<<y;
00609         case kRsh: return x>>y;
00610         case kGT:  return x>y;
00611         case kLT:  return x<y;
00612         case kGE:  return x>=y;
00613         case kLE:  return x<=y;
00614         case kEQ:  return x==y;
00615         case kNE:   return x!=y;
00616         case kAND:  return x&y;
00617         case kOR:  return x|y;
00618         case kXOR: return x^y;
00619         default:
00620             cerr << "Unrecognized opcode : " << opcode << endl;
00621             exit(1);
00622     }
00623 
00624     return interval();
00625 }