FAUST compiler  0.9.9.6b8
boxtype.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 /*****************************************************************************
00025 ******************************************************************************
00026     
00027                               Box Type System
00028     
00029 ******************************************************************************
00030 *****************************************************************************/
00031 
00032 
00042 #include <stdio.h>
00043 #include <string.h>
00044 #include "boxes.hh"
00045 #include "ppbox.hh"
00046 #include "prim2.hh"
00047 #include "xtended.hh"
00048 
00049 
00050 Tree BOXTYPEPROP = tree(symbol("boxTypeProp"));
00051 static bool infereBoxType (Tree box, int* inum, int* onum);
00052 
00053 
00054 
00063 bool getBoxType (Tree box, int* inum, int* onum)
00064 {
00065     Tree t;
00066     if (getProperty(box, BOXTYPEPROP, t)) {
00067         
00068         if (isNil(t)) {
00069             return false;
00070         } else {
00071             *inum = hd(t)->node().getInt();
00072             *onum = tl(t)->node().getInt();
00073             return true;
00074         }
00075         
00076     } else {
00077     
00078         if (infereBoxType(box, inum, onum)) {
00079             setProperty(box, BOXTYPEPROP, cons(tree(*inum), tree(*onum)));
00080             return true;
00081         } else {
00082             setProperty(box, BOXTYPEPROP, nil);
00083             return false;
00084         }
00085     }
00086 }
00087 
00088 
00089 
00101 static bool infereBoxType (Tree t, int* inum, int* onum)
00102 {
00103     Tree a, b, ff, l, s;
00104     //Tree abstr, genv, vis, lenv;
00105     
00106     xtended* p = (xtended*) getUserData(t);
00107 
00108     if (p)                      { *inum = p->arity(); *onum = 1; }
00109     else if (isBoxInt(t))       { *inum = 0; *onum = 1; } 
00110     else if (isBoxReal(t))      { *inum = 0; *onum = 1; } 
00111     else if (isBoxWire(t))      { *inum = 1; *onum = 1; }
00112     else if (isBoxCut(t))       { *inum = 1; *onum = 0; } 
00113 
00114     else if (isBoxSlot(t))          { *inum = 0; *onum = 1; }
00115     else if (isBoxSymbolic(t,s,b))  { if (!getBoxType(b, inum, onum)) return false; *inum += 1; } 
00116     
00117     else if (isBoxPatternVar(t,a))  { return false; }
00118 
00119     else if (isBoxPrim0(t))     { *inum = 0; *onum = 1; }
00120     else if (isBoxPrim1(t))     { *inum = 1; *onum = 1; } 
00121     else if (isBoxPrim2(t))     { *inum = 2; *onum = 1; } 
00122     else if (isBoxPrim3(t))     { *inum = 3; *onum = 1; } 
00123     else if (isBoxPrim4(t))     { *inum = 4; *onum = 1; } 
00124     else if (isBoxPrim5(t))     { *inum = 5; *onum = 1; } 
00125         
00126     else if (isBoxFFun(t,ff))   { *inum = ffarity(ff); *onum = 1; } 
00127     else if (isBoxFConst(t))    { *inum = 0; *onum = 1; } 
00128     else if (isBoxFVar(t))      { *inum = 0; *onum = 1; } 
00129     
00130     else if (isBoxButton(t))    { *inum = 0; *onum = 1; } 
00131     else if (isBoxCheckbox(t))  { *inum = 0; *onum = 1; } 
00132     else if (isBoxVSlider(t))   { *inum = 0; *onum = 1; } 
00133     else if (isBoxHSlider(t))   { *inum = 0; *onum = 1; } 
00134     else if (isBoxNumEntry(t))  { *inum = 0; *onum = 1; } 
00135     else if (isBoxVGroup(t,l,a)){ return getBoxType(a, inum, onum); }
00136     else if (isBoxHGroup(t,l,a)){ return getBoxType(a, inum, onum); }
00137     else if (isBoxTGroup(t,l,a)){ return getBoxType(a, inum, onum); }
00138     
00139     else if (isBoxVBargraph(t))     { *inum = 1; *onum = 1; } 
00140     else if (isBoxHBargraph(t))     { *inum = 1; *onum = 1; } 
00141 
00142     else if (isBoxSeq(t, a, b)) {
00143         
00144         int u,v,x,y;
00145         if (!getBoxType(a, &u, &v)) return false;
00146         if (!getBoxType(b, &x, &y)) return false;
00147 
00148         if (v != x) {
00149             cerr    << "Error in sequential composition (A:B)" << endl
00150                     << "The number of outputs (" << v << ") of A = " << boxpp(a) << endl
00151                     << "must be equal to the number of inputs (" << x << ") of B : " << boxpp(b) << endl;
00152             exit(1);
00153         } else {
00154             *inum = u; *onum = y;
00155         }
00156 
00157     } else if (isBoxPar(t, a, b)) {
00158         
00159         int u,v,x,y;
00160         if (!getBoxType(a, &u, &v)) return false;
00161         if (!getBoxType(b, &x, &y)) return false;
00162 
00163         *inum = u+x; *onum = v+y;
00164 
00165     } else if (isBoxSplit(t, a, b)) {
00166         
00167         int u,v,x,y;
00168         if (!getBoxType(a, &u, &v)) return false;
00169         if (!getBoxType(b, &x, &y)) return false;
00170 
00171         if (v == 0) {
00172             cerr    << "Connection error in : " << boxpp(t) << endl
00173                     << "The first expression : " << boxpp(a) << " has no outputs" << endl;
00174             exit(1);
00175         }
00176         
00177         if (x == 0) {
00178             cerr    << "Connection error in : " << boxpp(t) << endl
00179                     << "The second expression : " << boxpp(b) << " has no inputs" << endl;
00180             exit(1);
00181         }
00182          
00183         if (x % v != 0) {
00184             cerr    << "Connection error in : " << boxpp(t) << endl
00185                     << "The number of outputs " << v
00186                     << " of the first expression should be a divisor of the number of inputs " << x
00187                     << " of the second expression" << endl;
00188             exit(1);
00189         }
00190         
00191         *inum = u; *onum = y;
00192 
00193     } else if (isBoxMerge(t, a, b)) {
00194         
00195         int u,v,x,y;
00196         if (!getBoxType(a, &u, &v)) return false;
00197         if (!getBoxType(b, &x, &y)) return false;
00198 
00199         if (v == 0) {
00200             cerr    << "Connection error in : " << boxpp(t) << endl
00201                     << "The first expression : " << boxpp(a) << " has no outputs" << endl;
00202             exit(1);
00203         }
00204         
00205         if (x == 0) {
00206             cerr    << "Connection error in : " << boxpp(t) << endl
00207                     << "The second expression : " << boxpp(b) << " has no inputs" << endl;
00208             exit(1);
00209         }
00210         
00211         if (v % x != 0) { 
00212             cerr    << "Connection error in : " << boxpp(t) << endl
00213                     << "The number of outputs " << v
00214                     << " of the first expression should be a multiple of the number of inputs " << x
00215                     << " of the second expression" << endl;
00216             exit(1);
00217         }
00218 
00219         *inum = u; *onum = y;
00220 
00221     } else if (isBoxRec(t, a, b)) {
00222         
00223         int u,v,x,y;
00224         if (!getBoxType(a, &u, &v)) return false;
00225         if (!getBoxType(b, &x, &y)) return false;
00226         if ( (x > v) | (y > u) ) { 
00227             cerr    << "Connection error in : " << boxpp(t) << endl;
00228             if (x > v) cerr << "The number of outputs " << v 
00229                             << " of the first expression should be greater or equal \n  to the number of inputs " << x 
00230                             << " of the second expression" << endl;
00231             if (y > u) cerr << "The number of inputs " << u
00232                             << " of the first expression should be greater or equal \n  to the number of outputs " << y
00233                             << " of the second expression" << endl;
00234             exit(1);
00235         }
00236         *inum = max(0,u-y); *onum = v;
00237         
00238     } else if (isBoxEnvironment(t)) {
00239         cerr << "Connection error : an environment is not a block-diagram : " << boxpp(t) << endl;
00240         exit(1);
00241     } else {
00242         cerr << "boxType() internal error : unrecognized box expression " << boxpp(t) << endl;
00243         exit(1);
00244     }
00245     return true;
00246 }   
00247         
00248         
00249