Rename interpretor to interpreter.
[Faustine.git] / interpreter / preprocessor / faust-0.9.47mr3 / compiler / generator / compile.cpp
diff --git a/interpreter/preprocessor/faust-0.9.47mr3/compiler/generator/compile.cpp b/interpreter/preprocessor/faust-0.9.47mr3/compiler/generator/compile.cpp
new file mode 100644 (file)
index 0000000..770afcb
--- /dev/null
@@ -0,0 +1,415 @@
+/************************************************************************
+ ************************************************************************
+    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.
+ ************************************************************************
+ ************************************************************************/
+
+
+
+/*****************************************************************************
+******************************************************************************
+                                                       FAUST SIGNAL COMPILER
+                                               Y. Orlarey, (c) Grame 2002
+------------------------------------------------------------------------------
+Compile a list of FAUST signals into a C++ class .
+
+ History :
+ ---------
+       2002-02-08 : First version
+
+******************************************************************************
+*****************************************************************************/
+
+
+
+#include "timing.hh"
+#include "compile.hh"
+#include "floats.hh"
+#include "sigtype.hh"
+
+#include <stdio.h>
+//#include <iostream>
+
+#include "sigprint.hh"
+#include "ppsig.hh"
+
+#include "sigtyperules.hh"
+#include "simplify.hh"
+#include "privatise.hh"
+//#include "factorize.hh"
+
+//#include "grouper.hh"
+//#include "sigvisitor.hh"
+
+
+
+
+/*****************************************************************************
+******************************************************************************
+
+                                                               API
+
+******************************************************************************
+*****************************************************************************/
+
+extern int             gDetailsSwitch;
+extern string  gMasterName;
+
+
+
+
+/*****************************************************************************
+******************************************************************************
+
+                                                 GENERAL COMPILER METHODS
+
+******************************************************************************
+*****************************************************************************/
+
+
+
+
+
+
+
+/*****************************************************************************
+                                                          constructor
+*****************************************************************************/
+
+Compiler::Compiler(const string& name, const string& super, int numInputs, int numOutputs, bool vec)
+               : fClass(new Klass(name, super, numInputs, numOutputs, vec)),
+                 fNeedToDeleteClass(true), 
+                 fUIRoot(uiFolder(cons(tree(0), tree(subst("$0", gMasterName))))),
+                 fDescription(0)
+{}
+
+Compiler::Compiler(Klass* k)
+               : fClass(k),
+                 fNeedToDeleteClass(false), 
+                 fUIRoot(uiFolder(cons(tree(0), tree(subst("$0", gMasterName))))),
+                 fDescription(0)
+{}
+
+
+Compiler::~Compiler()
+{ 
+       if (fNeedToDeleteClass) delete fClass;
+}
+
+
+
+/*****************************************************************************
+                                                       user interface elements
+*****************************************************************************/
+
+/**
+ * Add a widget with a certain path to the user interface tree
+ */
+void Compiler::addUIWidget(Tree path, Tree widget)
+{
+       fUIRoot = putSubFolder(fUIRoot, path, widget);
+}
+
+
+/**
+ * Remove fake root folder if not needed (that is if the UI
+ * is completely enclosed in one folder
+ */
+Tree Compiler::prepareUserInterfaceTree(Tree t)
+{
+       Tree root, elems;
+       if (isUiFolder(t, root, elems) && isList(elems) && isNil(tl(elems)) ) {
+               Tree folder = right(hd(elems));
+               return (isUiFolder(folder)) ? folder : t;
+       }
+       return t;
+}
+
+//================================= some string processing utilities =================================
+
+/**
+ * Removes enclosing whitespaces : '  toto  ' -> 'toto'
+ */
+static string wdel(const string& s)
+{
+    size_t i = 0;
+    size_t j = s.size();
+    while (i<j && s[i]==' ') i++;
+    while (j>i && s[j-1] == ' ') j--;
+    return s.substr(i,j-i);
+}
+
+
+//================================= BUILD USER INTERFACE METHOD =================================
+
+/**
+ * Generate buildUserInterface C++ lines of code corresponding 
+ * to user interface element t
+ */
+void Compiler::generateUserInterfaceTree(Tree t)
+{
+       Tree    label, elements, varname, sig;
+
+       if (isUiFolder(t, label, elements)) {
+               const int               orient = tree2int(left(label));
+               const char *    str = tree2str(right(label));
+        const char *   model;
+
+        // extract metadata from group label str resulting in a simplifiedLabel
+               // and metadata declarations for fictive zone at address 0
+        string  simplifiedLabel;
+        map<string, set<string> >   metadata;
+        extractMetadata(str, simplifiedLabel, metadata);
+
+        // add metadata if any
+        for (map<string, set<string> >::iterator i = metadata.begin(); i != metadata.end(); i++) {
+            const string& key = i->first;
+            const set<string>& values = i->second;
+            for (set<string>::const_iterator j = values.begin(); j != values.end(); j++) {
+                fClass->addUICode(subst("interface->declare($0, \"$1\", \"$2\");", "0", wdel(key) ,wdel(*j)));
+            }
+        }
+        //-----------------
+
+
+               switch (orient) {
+                       case 0 : model = "interface->openVerticalBox(\"$0\");"; break;
+                       case 1 : model = "interface->openHorizontalBox(\"$0\");"; break;
+                       case 2 : model = "interface->openTabBox(\"$0\");"; break;
+                       default :
+                                       fprintf(stderr, "error in user interface generation 1\n");
+                               exit(1);
+               }
+        fClass->addUICode(subst(model, simplifiedLabel));
+               generateUserInterfaceElements(elements);
+               fClass->addUICode("interface->closeBox();");
+
+       } else if (isUiWidget(t, label, varname, sig)) {
+
+               generateWidgetCode(label, varname, sig);
+
+       } else {
+
+               fprintf(stderr, "error in user interface generation 2\n");
+               exit(1);
+
+       }
+}
+
+/**
+ * Iterate generateUserInterfaceTree on a list of user interface elements
+ */
+void Compiler::generateUserInterfaceElements(Tree elements)
+{
+       while (!isNil(elements)) {
+               generateUserInterfaceTree(right(hd(elements)));
+               elements = tl(elements);
+       }
+}
+
+/**
+ * Generate buildUserInterface C++ lines of code corresponding 
+ * to user interface widget t
+ */
+void Compiler::generateWidgetCode(Tree fulllabel, Tree varname, Tree sig)
+{
+       Tree path, c, x, y, z;
+    string label;
+    map<string, set<string> >   metadata;
+
+    extractMetadata(tree2str(fulllabel), label, metadata);
+
+    // add metadata if any
+    for (map<string, set<string> >::iterator i = metadata.begin(); i != metadata.end(); i++) {
+        const string& key = i->first;
+        const set<string>& values = i->second;
+        for (set<string>::const_iterator j = values.begin(); j != values.end(); j++) {
+            fClass->addUICode(subst("interface->declare(&$0, \"$1\", \"$2\");", tree2str(varname), wdel(key) ,wdel(*j)));
+        }
+    }
+
+       if ( isSigButton(sig, path) )                                   {
+        fClass->incUIActiveCount();
+               fClass->addUICode(subst("interface->addButton(\"$0\", &$1);", label, tree2str(varname)));
+
+       } else if ( isSigCheckbox(sig, path) )                  {
+        fClass->incUIActiveCount();
+               fClass->addUICode(subst("interface->addCheckButton(\"$0\", &$1);", label, tree2str(varname)));
+
+       } else if ( isSigVSlider(sig, path,c,x,y,z) )   {
+        fClass->incUIActiveCount();
+               fClass->addUICode(subst("interface->addVerticalSlider(\"$0\", &$1, $2, $3, $4, $5);",
+                               label,
+                               tree2str(varname),
+                               T(tree2float(c)),
+                               T(tree2float(x)),
+                               T(tree2float(y)),
+                               T(tree2float(z))));
+
+       } else if ( isSigHSlider(sig, path,c,x,y,z) )   {
+        fClass->incUIActiveCount();
+               fClass->addUICode(subst("interface->addHorizontalSlider(\"$0\", &$1, $2, $3, $4, $5);",
+                               label,
+                               tree2str(varname),
+                               T(tree2float(c)),
+                               T(tree2float(x)),
+                               T(tree2float(y)),
+                               T(tree2float(z))));
+
+       } else if ( isSigNumEntry(sig, path,c,x,y,z) )  {
+        fClass->incUIActiveCount();
+               fClass->addUICode(subst("interface->addNumEntry(\"$0\", &$1, $2, $3, $4, $5);",
+                               label,
+                               tree2str(varname),
+                               T(tree2float(c)),
+                               T(tree2float(x)),
+                               T(tree2float(y)),
+                               T(tree2float(z))));
+
+       } else if ( isSigVBargraph(sig, path,x,y,z) )   {
+        fClass->incUIPassiveCount();
+               fClass->addUICode(subst("interface->addVerticalBargraph(\"$0\", &$1, $2, $3);",
+                               label,
+                               tree2str(varname),
+                               T(tree2float(x)),
+                               T(tree2float(y))));
+
+       } else if ( isSigHBargraph(sig, path,x,y,z) )   {
+        fClass->incUIPassiveCount();
+               fClass->addUICode(subst("interface->addHorizontalBargraph(\"$0\", &$1, $2, $3);",
+                label,
+                               tree2str(varname),
+                               T(tree2float(x)),
+                               T(tree2float(y))));
+
+       } else {
+               fprintf(stderr, "Error in generating widget code\n");
+               exit(1);
+       }
+}
+
+//==================================== USER INTERFACE MACROS ==================================
+
+/**
+ * Generate user interface macros corresponding 
+ * to user interface element t
+ */
+void Compiler::generateMacroInterfaceTree(const string& pathname, Tree t)
+{
+       Tree    label, elements, varname, sig;
+
+       if (isUiFolder(t, label, elements)) {
+               string pathname2 = pathname;
+               //string str = unquote(tree2str(right(label)));
+               string str = tree2str(right(label));
+               if (str.length()>0) pathname2 += str + "/";
+               generateMacroInterfaceElements(pathname2, elements);
+
+       } else if (isUiWidget(t, label, varname, sig)) {
+
+               generateWidgetMacro(pathname, label, varname, sig);
+
+       } else {
+
+               fprintf(stderr, "error in user interface macro generation 2\n");
+               exit(1);
+
+       }
+}
+
+
+/**
+ * Iterate generateMacroInterfaceTree on a list of user interface elements
+ */
+void Compiler::generateMacroInterfaceElements(const string& pathname, Tree elements)
+{
+       while (!isNil(elements)) {
+               generateMacroInterfaceTree(pathname, right(hd(elements)));
+               elements = tl(elements);
+       }
+}
+
+
+/**
+ * Generate user interface macros corresponding 
+ * to a user interface widget
+ */
+void Compiler::generateWidgetMacro(const string& pathname, Tree fulllabel, Tree varname, Tree sig)
+{
+       Tree path, c, x, y, z;
+    string label;
+    map<string, set<string> >   metadata;
+
+    extractMetadata(tree2str(fulllabel), label, metadata);
+
+    //string pathlabel = pathname+unquote(label);
+       string pathlabel = pathname+label;
+
+
+       if ( isSigButton(sig, path) )                                   {
+               fClass->addUIMacro(subst("FAUST_ADDBUTTON(\"$0\", $1);", pathlabel, tree2str(varname)));
+
+       } else if ( isSigCheckbox(sig, path) )                  {
+               fClass->addUIMacro(subst("FAUST_ADDCHECKBOX(\"$0\", $1);", pathlabel, tree2str(varname)));
+
+       } else if ( isSigVSlider(sig, path,c,x,y,z) )   {
+               fClass->addUIMacro(subst("FAUST_ADDVERTICALSLIDER(\"$0\", $1, $2, $3, $4, $5);",
+                               pathlabel,
+                               tree2str(varname),
+                               T(tree2float(c)),
+                               T(tree2float(x)),
+                               T(tree2float(y)),
+                               T(tree2float(z))));
+
+       } else if ( isSigHSlider(sig, path,c,x,y,z) )   {
+               fClass->addUIMacro(subst("FAUST_ADDHORIZONTALSLIDER(\"$0\", $1, $2, $3, $4, $5);",
+                               pathlabel,
+                               tree2str(varname),
+                               T(tree2float(c)),
+                               T(tree2float(x)),
+                               T(tree2float(y)),
+                               T(tree2float(z))));
+
+       } else if ( isSigNumEntry(sig, path,c,x,y,z) )  {
+               fClass->addUIMacro(subst("FAUST_ADDNUMENTRY(\"$0\", $1, $2, $3, $4, $5);",
+                               pathlabel,
+                               tree2str(varname),
+                               T(tree2float(c)),
+                               T(tree2float(x)),
+                               T(tree2float(y)),
+                               T(tree2float(z))));
+
+       } else if ( isSigVBargraph(sig, path,x,y,z) )   {
+               fClass->addUIMacro(subst("FAUST_ADDVERTICALBARGRAPH(\"$0\", $1, $2, $3);",
+                               pathlabel,
+                               tree2str(varname),
+                               T(tree2float(x)),
+                               T(tree2float(y))));
+
+       } else if ( isSigHBargraph(sig, path,x,y,z) )   {
+               fClass->addUIMacro(subst("FAUST_ADDHORIZONTALBARGRAPH(\"$0\", $1, $2, $3);",
+                               pathlabel,
+                               tree2str(varname),
+                               T(tree2float(x)),
+                               T(tree2float(y))));
+
+       } else {
+               fprintf(stderr, "Error in generating widget code\n");
+               exit(1);
+       }
+}