FAUST compiler  0.9.9.6b8
compile.cpp
Go to the documentation of this file.
1 /************************************************************************
2  ************************************************************************
3  FAUST compiler
4  Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
5  ---------------------------------------------------------------------
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  ************************************************************************
20  ************************************************************************/
21 
22 
23 
24 /*****************************************************************************
25 ******************************************************************************
26  FAUST SIGNAL COMPILER
27  Y. Orlarey, (c) Grame 2002
28 ------------------------------------------------------------------------------
29 Compile a list of FAUST signals into a C++ class .
30 
31  History :
32  ---------
33  2002-02-08 : First version
34 
35 ******************************************************************************
36 *****************************************************************************/
37 
38 
39 
40 #include "timing.hh"
41 #include "compile.hh"
42 #include "floats.hh"
43 #include "sigtype.hh"
44 
45 #include <stdio.h>
46 //#include <iostream>
47 
48 #include "sigprint.hh"
49 #include "ppsig.hh"
50 
51 #include "sigtyperules.hh"
52 #include "simplify.hh"
53 #include "privatise.hh"
54 //#include "factorize.hh"
55 
56 //#include "grouper.hh"
57 //#include "sigvisitor.hh"
58 
59 
60 
61 
62 /*****************************************************************************
63 ******************************************************************************
64 
65  API
66 
67 ******************************************************************************
68 *****************************************************************************/
69 
70 extern int gDetailsSwitch;
71 extern string gMasterName;
72 
73 
74 
75 
76 /*****************************************************************************
77 ******************************************************************************
78 
79  GENERAL COMPILER METHODS
80 
81 ******************************************************************************
82 *****************************************************************************/
83 
84 
85 
86 
87 
88 
89 
90 /*****************************************************************************
91  constructor
92 *****************************************************************************/
93 
94 Compiler::Compiler(const string& name, const string& super, int numInputs, int numOutputs, bool vec)
95  : fClass(new Klass(name, super, numInputs, numOutputs, vec)),
96  fNeedToDeleteClass(true),
97  fUIRoot(uiFolder(cons(tree(0), tree(subst("$0", gMasterName))))),
98  fDescription(0)
99 {}
100 
102  : fClass(k),
103  fNeedToDeleteClass(false),
104  fUIRoot(uiFolder(cons(tree(0), tree(subst("$0", gMasterName))))),
105  fDescription(0)
106 {}
107 
108 
110 {
111  if (fNeedToDeleteClass) delete fClass;
112 }
113 
114 
115 
116 /*****************************************************************************
117  user interface elements
118 *****************************************************************************/
119 
123 void Compiler::addUIWidget(Tree path, Tree widget)
124 {
125  fUIRoot = putSubFolder(fUIRoot, path, widget);
126 }
127 
128 
134 {
135  Tree root, elems;
136  if (isUiFolder(t, root, elems) && isList(elems) && isNil(tl(elems)) ) {
137  Tree folder = right(hd(elems));
138  return (isUiFolder(folder)) ? folder : t;
139  }
140  return t;
141 }
142 
143 //================================= some string processing utilities =================================
144 
148 static string wdel(const string& s)
149 {
150  size_t i = 0;
151  size_t j = s.size();
152  while (i<j && s[i]==' ') i++;
153  while (j>i && s[j-1] == ' ') j--;
154  return s.substr(i,j-i);
155 }
156 
157 
158 //================================= BUILD USER INTERFACE METHOD =================================
159 
165 {
166  Tree label, elements, varname, sig;
167 
168  if (isUiFolder(t, label, elements)) {
169  const int orient = tree2int(left(label));
170  const char * str = tree2str(right(label));
171  const char * model;
172 
173  // extract metadata from group label str resulting in a simplifiedLabel
174  // and metadata declarations for fictive zone at address 0
175  string simplifiedLabel;
176  map<string, set<string> > metadata;
177  extractMetadata(str, simplifiedLabel, metadata);
178 
179  // add metadata if any
180  for (map<string, set<string> >::iterator i = metadata.begin(); i != metadata.end(); i++) {
181  const string& key = i->first;
182  const set<string>& values = i->second;
183  for (set<string>::const_iterator j = values.begin(); j != values.end(); j++) {
184  fClass->addUICode(subst("interface->declare($0, \"$1\", \"$2\");", "0", wdel(key) ,wdel(*j)));
185  }
186  }
187  //-----------------
188 
189 
190  switch (orient) {
191  case 0 : model = "interface->openVerticalBox(\"$0\");"; break;
192  case 1 : model = "interface->openHorizontalBox(\"$0\");"; break;
193  case 2 : model = "interface->openTabBox(\"$0\");"; break;
194  default :
195  fprintf(stderr, "error in user interface generation 1\n");
196  exit(1);
197  }
198  fClass->addUICode(subst(model, simplifiedLabel));
200  fClass->addUICode("interface->closeBox();");
201 
202  } else if (isUiWidget(t, label, varname, sig)) {
203 
204  generateWidgetCode(label, varname, sig);
205 
206  } else {
207 
208  fprintf(stderr, "error in user interface generation 2\n");
209  exit(1);
210 
211  }
212 }
213 
218 {
219  while (!isNil(elements)) {
220  generateUserInterfaceTree(right(hd(elements)));
221  elements = tl(elements);
222  }
223 }
224 
229 void Compiler::generateWidgetCode(Tree fulllabel, Tree varname, Tree sig)
230 {
231  Tree path, c, x, y, z;
232  string label;
233  map<string, set<string> > metadata;
234 
235  extractMetadata(tree2str(fulllabel), label, metadata);
236 
237  // add metadata if any
238  for (map<string, set<string> >::iterator i = metadata.begin(); i != metadata.end(); i++) {
239  const string& key = i->first;
240  const set<string>& values = i->second;
241  for (set<string>::const_iterator j = values.begin(); j != values.end(); j++) {
242  fClass->addUICode(subst("interface->declare(&$0, \"$1\", \"$2\");", tree2str(varname), wdel(key) ,wdel(*j)));
243  }
244  }
245 
246  if ( isSigButton(sig, path) ) {
248  fClass->addUICode(subst("interface->addButton(\"$0\", &$1);", label, tree2str(varname)));
249 
250  } else if ( isSigCheckbox(sig, path) ) {
252  fClass->addUICode(subst("interface->addCheckButton(\"$0\", &$1);", label, tree2str(varname)));
253 
254  } else if ( isSigVSlider(sig, path,c,x,y,z) ) {
256  fClass->addUICode(subst("interface->addVerticalSlider(\"$0\", &$1, $2, $3, $4, $5);",
257  label,
258  tree2str(varname),
259  T(tree2float(c)),
260  T(tree2float(x)),
261  T(tree2float(y)),
262  T(tree2float(z))));
263 
264  } else if ( isSigHSlider(sig, path,c,x,y,z) ) {
266  fClass->addUICode(subst("interface->addHorizontalSlider(\"$0\", &$1, $2, $3, $4, $5);",
267  label,
268  tree2str(varname),
269  T(tree2float(c)),
270  T(tree2float(x)),
271  T(tree2float(y)),
272  T(tree2float(z))));
273 
274  } else if ( isSigNumEntry(sig, path,c,x,y,z) ) {
276  fClass->addUICode(subst("interface->addNumEntry(\"$0\", &$1, $2, $3, $4, $5);",
277  label,
278  tree2str(varname),
279  T(tree2float(c)),
280  T(tree2float(x)),
281  T(tree2float(y)),
282  T(tree2float(z))));
283 
284  } else if ( isSigVBargraph(sig, path,x,y,z) ) {
286  fClass->addUICode(subst("interface->addVerticalBargraph(\"$0\", &$1, $2, $3);",
287  label,
288  tree2str(varname),
289  T(tree2float(x)),
290  T(tree2float(y))));
291 
292  } else if ( isSigHBargraph(sig, path,x,y,z) ) {
294  fClass->addUICode(subst("interface->addHorizontalBargraph(\"$0\", &$1, $2, $3);",
295  label,
296  tree2str(varname),
297  T(tree2float(x)),
298  T(tree2float(y))));
299 
300  } else {
301  fprintf(stderr, "Error in generating widget code\n");
302  exit(1);
303  }
304 }
305 
306 //==================================== USER INTERFACE MACROS ==================================
307 
312 void Compiler::generateMacroInterfaceTree(const string& pathname, Tree t)
313 {
314  Tree label, elements, varname, sig;
315 
316  if (isUiFolder(t, label, elements)) {
317  string pathname2 = pathname;
318  //string str = unquote(tree2str(right(label)));
319  string str = tree2str(right(label));
320  if (str.length()>0) pathname2 += str + "/";
321  generateMacroInterfaceElements(pathname2, elements);
322 
323  } else if (isUiWidget(t, label, varname, sig)) {
324 
325  generateWidgetMacro(pathname, label, varname, sig);
326 
327  } else {
328 
329  fprintf(stderr, "error in user interface macro generation 2\n");
330  exit(1);
331 
332  }
333 }
334 
335 
339 void Compiler::generateMacroInterfaceElements(const string& pathname, Tree elements)
340 {
341  while (!isNil(elements)) {
342  generateMacroInterfaceTree(pathname, right(hd(elements)));
343  elements = tl(elements);
344  }
345 }
346 
347 
352 void Compiler::generateWidgetMacro(const string& pathname, Tree fulllabel, Tree varname, Tree sig)
353 {
354  Tree path, c, x, y, z;
355  string label;
356  map<string, set<string> > metadata;
357 
358  extractMetadata(tree2str(fulllabel), label, metadata);
359 
360  //string pathlabel = pathname+unquote(label);
361  string pathlabel = pathname+label;
362 
363 
364  if ( isSigButton(sig, path) ) {
365  fClass->addUIMacro(subst("FAUST_ADDBUTTON(\"$0\", $1);", pathlabel, tree2str(varname)));
366 
367  } else if ( isSigCheckbox(sig, path) ) {
368  fClass->addUIMacro(subst("FAUST_ADDCHECKBOX(\"$0\", $1);", pathlabel, tree2str(varname)));
369 
370  } else if ( isSigVSlider(sig, path,c,x,y,z) ) {
371  fClass->addUIMacro(subst("FAUST_ADDVERTICALSLIDER(\"$0\", $1, $2, $3, $4, $5);",
372  pathlabel,
373  tree2str(varname),
374  T(tree2float(c)),
375  T(tree2float(x)),
376  T(tree2float(y)),
377  T(tree2float(z))));
378 
379  } else if ( isSigHSlider(sig, path,c,x,y,z) ) {
380  fClass->addUIMacro(subst("FAUST_ADDHORIZONTALSLIDER(\"$0\", $1, $2, $3, $4, $5);",
381  pathlabel,
382  tree2str(varname),
383  T(tree2float(c)),
384  T(tree2float(x)),
385  T(tree2float(y)),
386  T(tree2float(z))));
387 
388  } else if ( isSigNumEntry(sig, path,c,x,y,z) ) {
389  fClass->addUIMacro(subst("FAUST_ADDNUMENTRY(\"$0\", $1, $2, $3, $4, $5);",
390  pathlabel,
391  tree2str(varname),
392  T(tree2float(c)),
393  T(tree2float(x)),
394  T(tree2float(y)),
395  T(tree2float(z))));
396 
397  } else if ( isSigVBargraph(sig, path,x,y,z) ) {
398  fClass->addUIMacro(subst("FAUST_ADDVERTICALBARGRAPH(\"$0\", $1, $2, $3);",
399  pathlabel,
400  tree2str(varname),
401  T(tree2float(x)),
402  T(tree2float(y))));
403 
404  } else if ( isSigHBargraph(sig, path,x,y,z) ) {
405  fClass->addUIMacro(subst("FAUST_ADDHORIZONTALBARGRAPH(\"$0\", $1, $2, $3);",
406  pathlabel,
407  tree2str(varname),
408  T(tree2float(x)),
409  T(tree2float(y))));
410 
411  } else {
412  fprintf(stderr, "Error in generating widget code\n");
413  exit(1);
414  }
415 }
bool isSigHSlider(Tree s)
Definition: signals.cpp:217
bool isSigCheckbox(Tree s)
Definition: signals.cpp:205
void generateWidgetCode(Tree fulllabel, Tree varname, Tree sig)
Generate buildUserInterface C++ lines of code corresponding to user interface widget t...
Definition: compile.cpp:229
int gDetailsSwitch
Definition: main.cpp:114
bool isSigNumEntry(Tree s)
Definition: signals.cpp:257
Klass * fClass
Definition: compile.hh:53
void addUIWidget(Tree path, Tree widget)
Add a widget with a certain path to the user interface tree.
Definition: compile.cpp:123
Tree cons(Tree a, Tree b)
Definition: list.hh:124
Tree left(Tree t)
Definition: list.hh:170
int tree2int(Tree t)
if t has a node of type int, return it otherwise error
Definition: tree.cpp:230
Tree prepareUserInterfaceTree(Tree t)
Remove fake root folder if not needed (that is if the UI is completely enclosed in one folder...
Definition: compile.cpp:133
void generateUserInterfaceTree(Tree t)
Generate buildUserInterface C++ lines of code corresponding to user interface element t...
Definition: compile.cpp:164
A CTree = (Node x [CTree]) is a Node associated with a list of subtrees called branches.
Definition: tree.hh:109
Tree hd(Tree l)
Definition: list.hh:133
bool fNeedToDeleteClass
Definition: compile.hh:54
Tree right(Tree t)
Definition: list.hh:171
bool isSigVBargraph(Tree s)
Definition: signals.cpp:285
bool isSigVSlider(Tree s)
Definition: signals.cpp:237
Tree fUIRoot
Definition: compile.hh:55
static string wdel(const string &s)
Removes enclosing whitespaces : ' toto ' -> 'toto'.
Definition: compile.cpp:148
void addUIMacro(const string &str)
Definition: klass.hh:159
bool isNil(Tree l)
Definition: list.hh:137
Compiler(const string &name, const string &super, int numInputs, int numOutputs, bool vec)
Definition: compile.cpp:94
Tree uiFolder(Tree label, Tree elements)
Definition: uitree.cpp:135
void generateMacroInterfaceTree(const string &pathname, Tree t)
Generate user interface macros corresponding to user interface element t.
Definition: compile.cpp:312
string subst(const string &model, const vector< string > &args)
Text substitution.
Definition: Text.cpp:47
bool isSigHBargraph(Tree s)
Definition: signals.cpp:279
Definition: klass.hh:55
bool isList(Tree l)
Definition: list.hh:138
virtual ~Compiler()
Definition: compile.cpp:109
string T(char *c)
Definition: Text.cpp:158
void extractMetadata(const string &fulllabel, string &label, map< string, set< string > > &metadata)
Extracts metdata from a label : 'vol [unit: dB]' -> 'vol' + metadata.
Definition: description.cpp:14
bool isUiWidget(Tree t, Tree &label, Tree &varname, Tree &sig)
Definition: uitree.cpp:141
const char * name(Symbol *sym)
Returns the name of a symbol.
Definition: symbol.hh:98
void generateUserInterfaceElements(Tree elements)
Iterate generateUserInterfaceTree on a list of user interface elements.
Definition: compile.cpp:217
Tree tree(const Node &n)
Definition: tree.hh:186
void incUIPassiveCount()
Definition: klass.hh:162
void addUICode(const string &str)
Definition: klass.hh:157
string gMasterName
Definition: main.cpp:106
void generateMacroInterfaceElements(const string &pathname, Tree elements)
Iterate generateMacroInterfaceTree on a list of user interface elements.
Definition: compile.cpp:339
Tree putSubFolder(Tree folder, Tree path, Tree item)
Definition: uitree.cpp:186
API to the typing system of signals.
bool isUiFolder(Tree t)
Definition: uitree.cpp:136
double tree2float(Tree t)
if t has a node of type float, return it otherwise error
Definition: tree.cpp:246
void generateWidgetMacro(const string &pathname, Tree fulllabel, Tree varname, Tree sig)
Generate user interface macros corresponding to a user interface widget.
Definition: compile.cpp:352
void incUIActiveCount()
Definition: klass.hh:161
Tree tl(Tree l)
Definition: list.hh:134
const char * tree2str(Tree t)
if t has a node of type symbol, return its name otherwise error
Definition: tree.cpp:278
bool isSigButton(Tree s)
Definition: signals.cpp:199