FAUST compiler  0.9.9.6b8
compile.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                             FAUST SIGNAL COMPILER
00027                         Y. Orlarey, (c) Grame 2002
00028 ------------------------------------------------------------------------------
00029 Compile a list of FAUST signals into a C++ class .
00030 
00031  History :
00032  ---------
00033     2002-02-08 : First version
00034 
00035 ******************************************************************************
00036 *****************************************************************************/
00037 
00038 
00039 
00040 #include "timing.hh"
00041 #include "compile.hh"
00042 #include "floats.hh"
00043 #include "sigtype.hh"
00044 
00045 #include <stdio.h>
00046 //#include <iostream>
00047 
00048 #include "sigprint.hh"
00049 #include "ppsig.hh"
00050 
00051 #include "sigtyperules.hh"
00052 #include "simplify.hh"
00053 #include "privatise.hh"
00054 //#include "factorize.hh"
00055 
00056 //#include "grouper.hh"
00057 //#include "sigvisitor.hh"
00058 
00059 
00060 
00061 
00062 /*****************************************************************************
00063 ******************************************************************************
00064 
00065                                     API
00066 
00067 ******************************************************************************
00068 *****************************************************************************/
00069 
00070 extern int      gDetailsSwitch;
00071 extern string   gMasterName;
00072 
00073 
00074 
00075 
00076 /*****************************************************************************
00077 ******************************************************************************
00078 
00079                           GENERAL COMPILER METHODS
00080 
00081 ******************************************************************************
00082 *****************************************************************************/
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 /*****************************************************************************
00091                                constructor
00092 *****************************************************************************/
00093 
00094 Compiler::Compiler(const string& name, const string& super, int numInputs, int numOutputs, bool vec)
00095         : fClass(new Klass(name, super, numInputs, numOutputs, vec)),
00096           fNeedToDeleteClass(true), 
00097           fUIRoot(uiFolder(cons(tree(0), tree(subst("$0", gMasterName))))),
00098           fDescription(0)
00099 {}
00100 
00101 Compiler::Compiler(Klass* k)
00102         : fClass(k),
00103           fNeedToDeleteClass(false), 
00104           fUIRoot(uiFolder(cons(tree(0), tree(subst("$0", gMasterName))))),
00105           fDescription(0)
00106 {}
00107 
00108 
00109 Compiler::~Compiler()
00110 { 
00111     if (fNeedToDeleteClass) delete fClass;
00112 }
00113 
00114 
00115 
00116 /*****************************************************************************
00117                             user interface elements
00118 *****************************************************************************/
00119 
00123 void Compiler::addUIWidget(Tree path, Tree widget)
00124 {
00125     fUIRoot = putSubFolder(fUIRoot, path, widget);
00126 }
00127 
00128 
00133 Tree Compiler::prepareUserInterfaceTree(Tree t)
00134 {
00135     Tree root, elems;
00136     if (isUiFolder(t, root, elems) && isList(elems) && isNil(tl(elems)) ) {
00137         Tree folder = right(hd(elems));
00138         return (isUiFolder(folder)) ? folder : t;
00139     }
00140     return t;
00141 }
00142 
00143 //================================= some string processing utilities =================================
00144 
00148 static string wdel(const string& s)
00149 {
00150     size_t i = 0;
00151     size_t j = s.size();
00152     while (i<j && s[i]==' ') i++;
00153     while (j>i && s[j-1] == ' ') j--;
00154     return s.substr(i,j-i);
00155 }
00156 
00157 
00158 //================================= BUILD USER INTERFACE METHOD =================================
00159 
00164 void Compiler::generateUserInterfaceTree(Tree t)
00165 {
00166     Tree    label, elements, varname, sig;
00167 
00168     if (isUiFolder(t, label, elements)) {
00169         const int       orient = tree2int(left(label));
00170         const char *    str = tree2str(right(label));
00171         const char *    model;
00172 
00173         // extract metadata from group label str resulting in a simplifiedLabel
00174         // and metadata declarations for fictive zone at address 0
00175         string  simplifiedLabel;
00176         map<string, set<string> >   metadata;
00177         extractMetadata(str, simplifiedLabel, metadata);
00178 
00179         // add metadata if any
00180         for (map<string, set<string> >::iterator i = metadata.begin(); i != metadata.end(); i++) {
00181             const string& key = i->first;
00182             const set<string>& values = i->second;
00183             for (set<string>::const_iterator j = values.begin(); j != values.end(); j++) {
00184                 fClass->addUICode(subst("interface->declare($0, \"$1\", \"$2\");", "0", wdel(key) ,wdel(*j)));
00185             }
00186         }
00187         //-----------------
00188 
00189 
00190         switch (orient) {
00191             case 0 : model = "interface->openVerticalBox(\"$0\");"; break;
00192             case 1 : model = "interface->openHorizontalBox(\"$0\");"; break;
00193             case 2 : model = "interface->openTabBox(\"$0\");"; break;
00194             default :
00195                     fprintf(stderr, "error in user interface generation 1\n");
00196                 exit(1);
00197         }
00198         fClass->addUICode(subst(model, simplifiedLabel));
00199         generateUserInterfaceElements(elements);
00200         fClass->addUICode("interface->closeBox();");
00201 
00202     } else if (isUiWidget(t, label, varname, sig)) {
00203 
00204         generateWidgetCode(label, varname, sig);
00205 
00206     } else {
00207 
00208         fprintf(stderr, "error in user interface generation 2\n");
00209         exit(1);
00210 
00211     }
00212 }
00213 
00217 void Compiler::generateUserInterfaceElements(Tree elements)
00218 {
00219     while (!isNil(elements)) {
00220         generateUserInterfaceTree(right(hd(elements)));
00221         elements = tl(elements);
00222     }
00223 }
00224 
00229 void Compiler::generateWidgetCode(Tree fulllabel, Tree varname, Tree sig)
00230 {
00231     Tree path, c, x, y, z;
00232     string label;
00233     map<string, set<string> >   metadata;
00234 
00235     extractMetadata(tree2str(fulllabel), label, metadata);
00236 
00237     // add metadata if any
00238     for (map<string, set<string> >::iterator i = metadata.begin(); i != metadata.end(); i++) {
00239         const string& key = i->first;
00240         const set<string>& values = i->second;
00241         for (set<string>::const_iterator j = values.begin(); j != values.end(); j++) {
00242             fClass->addUICode(subst("interface->declare(&$0, \"$1\", \"$2\");", tree2str(varname), wdel(key) ,wdel(*j)));
00243         }
00244     }
00245 
00246     if ( isSigButton(sig, path) )                   {
00247         fClass->incUIActiveCount();
00248         fClass->addUICode(subst("interface->addButton(\"$0\", &$1);", label, tree2str(varname)));
00249 
00250     } else if ( isSigCheckbox(sig, path) )          {
00251         fClass->incUIActiveCount();
00252         fClass->addUICode(subst("interface->addCheckButton(\"$0\", &$1);", label, tree2str(varname)));
00253 
00254     } else if ( isSigVSlider(sig, path,c,x,y,z) )   {
00255         fClass->incUIActiveCount();
00256         fClass->addUICode(subst("interface->addVerticalSlider(\"$0\", &$1, $2, $3, $4, $5);",
00257                 label,
00258                 tree2str(varname),
00259                 T(tree2float(c)),
00260                 T(tree2float(x)),
00261                 T(tree2float(y)),
00262                 T(tree2float(z))));
00263 
00264     } else if ( isSigHSlider(sig, path,c,x,y,z) )   {
00265         fClass->incUIActiveCount();
00266         fClass->addUICode(subst("interface->addHorizontalSlider(\"$0\", &$1, $2, $3, $4, $5);",
00267                 label,
00268                 tree2str(varname),
00269                 T(tree2float(c)),
00270                 T(tree2float(x)),
00271                 T(tree2float(y)),
00272                 T(tree2float(z))));
00273 
00274     } else if ( isSigNumEntry(sig, path,c,x,y,z) )  {
00275         fClass->incUIActiveCount();
00276         fClass->addUICode(subst("interface->addNumEntry(\"$0\", &$1, $2, $3, $4, $5);",
00277                 label,
00278                 tree2str(varname),
00279                 T(tree2float(c)),
00280                 T(tree2float(x)),
00281                 T(tree2float(y)),
00282                 T(tree2float(z))));
00283 
00284     } else if ( isSigVBargraph(sig, path,x,y,z) )   {
00285         fClass->incUIPassiveCount();
00286         fClass->addUICode(subst("interface->addVerticalBargraph(\"$0\", &$1, $2, $3);",
00287                 label,
00288                 tree2str(varname),
00289                 T(tree2float(x)),
00290                 T(tree2float(y))));
00291 
00292     } else if ( isSigHBargraph(sig, path,x,y,z) )   {
00293         fClass->incUIPassiveCount();
00294         fClass->addUICode(subst("interface->addHorizontalBargraph(\"$0\", &$1, $2, $3);",
00295                 label,
00296                 tree2str(varname),
00297                 T(tree2float(x)),
00298                 T(tree2float(y))));
00299 
00300     } else {
00301         fprintf(stderr, "Error in generating widget code\n");
00302         exit(1);
00303     }
00304 }
00305 
00306 //==================================== USER INTERFACE MACROS ==================================
00307 
00312 void Compiler::generateMacroInterfaceTree(const string& pathname, Tree t)
00313 {
00314     Tree    label, elements, varname, sig;
00315 
00316     if (isUiFolder(t, label, elements)) {
00317         string pathname2 = pathname;
00318         //string str = unquote(tree2str(right(label)));
00319         string str = tree2str(right(label));
00320         if (str.length()>0) pathname2 += str + "/";
00321         generateMacroInterfaceElements(pathname2, elements);
00322 
00323     } else if (isUiWidget(t, label, varname, sig)) {
00324 
00325         generateWidgetMacro(pathname, label, varname, sig);
00326 
00327     } else {
00328 
00329         fprintf(stderr, "error in user interface macro generation 2\n");
00330         exit(1);
00331 
00332     }
00333 }
00334 
00335 
00339 void Compiler::generateMacroInterfaceElements(const string& pathname, Tree elements)
00340 {
00341     while (!isNil(elements)) {
00342         generateMacroInterfaceTree(pathname, right(hd(elements)));
00343         elements = tl(elements);
00344     }
00345 }
00346 
00347 
00352 void Compiler::generateWidgetMacro(const string& pathname, Tree fulllabel, Tree varname, Tree sig)
00353 {
00354     Tree path, c, x, y, z;
00355     string label;
00356     map<string, set<string> >   metadata;
00357 
00358     extractMetadata(tree2str(fulllabel), label, metadata);
00359 
00360     //string pathlabel = pathname+unquote(label);
00361     string pathlabel = pathname+label;
00362 
00363 
00364     if ( isSigButton(sig, path) )                   {
00365         fClass->addUIMacro(subst("FAUST_ADDBUTTON(\"$0\", $1);", pathlabel, tree2str(varname)));
00366 
00367     } else if ( isSigCheckbox(sig, path) )          {
00368         fClass->addUIMacro(subst("FAUST_ADDCHECKBOX(\"$0\", $1);", pathlabel, tree2str(varname)));
00369 
00370     } else if ( isSigVSlider(sig, path,c,x,y,z) )   {
00371         fClass->addUIMacro(subst("FAUST_ADDVERTICALSLIDER(\"$0\", $1, $2, $3, $4, $5);",
00372                 pathlabel,
00373                 tree2str(varname),
00374                 T(tree2float(c)),
00375                 T(tree2float(x)),
00376                 T(tree2float(y)),
00377                 T(tree2float(z))));
00378 
00379     } else if ( isSigHSlider(sig, path,c,x,y,z) )   {
00380         fClass->addUIMacro(subst("FAUST_ADDHORIZONTALSLIDER(\"$0\", $1, $2, $3, $4, $5);",
00381                 pathlabel,
00382                 tree2str(varname),
00383                 T(tree2float(c)),
00384                 T(tree2float(x)),
00385                 T(tree2float(y)),
00386                 T(tree2float(z))));
00387 
00388     } else if ( isSigNumEntry(sig, path,c,x,y,z) )  {
00389         fClass->addUIMacro(subst("FAUST_ADDNUMENTRY(\"$0\", $1, $2, $3, $4, $5);",
00390                 pathlabel,
00391                 tree2str(varname),
00392                 T(tree2float(c)),
00393                 T(tree2float(x)),
00394                 T(tree2float(y)),
00395                 T(tree2float(z))));
00396 
00397     } else if ( isSigVBargraph(sig, path,x,y,z) )   {
00398         fClass->addUIMacro(subst("FAUST_ADDVERTICALBARGRAPH(\"$0\", $1, $2, $3);",
00399                 pathlabel,
00400                 tree2str(varname),
00401                 T(tree2float(x)),
00402                 T(tree2float(y))));
00403 
00404     } else if ( isSigHBargraph(sig, path,x,y,z) )   {
00405         fClass->addUIMacro(subst("FAUST_ADDHORIZONTALBARGRAPH(\"$0\", $1, $2, $3);",
00406                 pathlabel,
00407                 tree2str(varname),
00408                 T(tree2float(x)),
00409                 T(tree2float(y))));
00410 
00411     } else {
00412         fprintf(stderr, "Error in generating widget code\n");
00413         exit(1);
00414     }
00415 }