-/************************************************************************
- ************************************************************************
- 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);
- }
-}