00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
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
00047
00048 #include "sigprint.hh"
00049 #include "ppsig.hh"
00050
00051 #include "sigtyperules.hh"
00052 #include "simplify.hh"
00053 #include "privatise.hh"
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 extern int gDetailsSwitch;
00071 extern string gMasterName;
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
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
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
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
00163 static string rmWhiteSpaces(const string& s)
00164 {
00165 size_t i = s.find_first_not_of(" \t");
00166 size_t j = s.find_last_not_of(" \t");
00167
00168 if ( (i != string::npos) & (j != string::npos) ) {
00169 return s.substr(i, 1+j-i);
00170 } else {
00171 return "";
00172 }
00173 }
00174
00178 static void extractMetadata(const string& fulllabel, string& label, map<string, set<string> >& metadata)
00179 {
00180 enum {kLabel, kEscape1, kEscape2, kEscape3, kKey, kValue};
00181 int state = kLabel; int deep = 0;
00182 string key, value;
00183
00184 for (unsigned int i=0; i < fulllabel.size(); i++) {
00185 char c = fulllabel[i];
00186 switch (state) {
00187 case kLabel :
00188 assert (deep == 0);
00189 switch (c) {
00190 case '\\' : state = kEscape1; break;
00191 case '[' : state = kKey; deep++; break;
00192 default : label += c;
00193 }
00194 break;
00195
00196 case kEscape1 :
00197 label += c;
00198 state = kLabel;
00199 break;
00200
00201 case kEscape2 :
00202 key += c;
00203 state = kKey;
00204 break;
00205
00206 case kEscape3 :
00207 value += c;
00208 state = kValue;
00209 break;
00210
00211 case kKey :
00212 assert (deep > 0);
00213 switch (c) {
00214 case '\\' : state = kEscape2;
00215 break;
00216
00217 case '[' : deep++;
00218 key += c;
00219 break;
00220
00221 case ':' : if (deep == 1) {
00222 state = kValue;
00223 } else {
00224 key += c;
00225 }
00226 break;
00227 case ']' : deep--;
00228 if (deep < 1) {
00229 metadata[rmWhiteSpaces(key)].insert("");
00230 state = kLabel;
00231 key="";
00232 value="";
00233 } else {
00234 key += c;
00235 }
00236 break;
00237 default : key += c;
00238 }
00239 break;
00240
00241 case kValue :
00242 assert (deep > 0);
00243 switch (c) {
00244 case '\\' : state = kEscape3;
00245 break;
00246
00247 case '[' : deep++;
00248 value += c;
00249 break;
00250
00251 case ']' : deep--;
00252 if (deep < 1) {
00253 metadata[rmWhiteSpaces(key)].insert(rmWhiteSpaces(value));
00254 state = kLabel;
00255 key="";
00256 value="";
00257 } else {
00258 value += c;
00259 }
00260 break;
00261 default : value += c;
00262 }
00263 break;
00264
00265 default :
00266 cerr << "ERROR unrecognized state " << state << endl;
00267 }
00268 }
00269 label = rmWhiteSpaces(label);
00270 }
00271
00272
00273
00274
00279 void Compiler::generateUserInterfaceTree(Tree t)
00280 {
00281 Tree label, elements, varname, sig;
00282
00283 if (isUiFolder(t, label, elements)) {
00284 const int orient = tree2int(left(label));
00285 const char * str = tree2str(right(label));
00286 const char * model;
00287
00288 switch (orient) {
00289 case 0 : model = "interface->openVerticalBox(\"$0\");"; break;
00290 case 1 : model = "interface->openHorizontalBox(\"$0\");"; break;
00291 case 2 : model = "interface->openTabBox(\"$0\");"; break;
00292 default :
00293 fprintf(stderr, "error in user interface generation 1\n");
00294 exit(1);
00295 }
00296 fClass->addUICode(subst(model, str));
00297 generateUserInterfaceElements(elements);
00298 fClass->addUICode("interface->closeBox();");
00299
00300 } else if (isUiWidget(t, label, varname, sig)) {
00301
00302 generateWidgetCode(label, varname, sig);
00303
00304 } else {
00305
00306 fprintf(stderr, "error in user interface generation 2\n");
00307 exit(1);
00308
00309 }
00310 }
00311
00315 void Compiler::generateUserInterfaceElements(Tree elements)
00316 {
00317 while (!isNil(elements)) {
00318 generateUserInterfaceTree(right(hd(elements)));
00319 elements = tl(elements);
00320 }
00321 }
00322
00327 void Compiler::generateWidgetCode(Tree fulllabel, Tree varname, Tree sig)
00328 {
00329 Tree path, c, x, y, z;
00330 string label;
00331 map<string, set<string> > metadata;
00332
00333 extractMetadata(tree2str(fulllabel), label, metadata);
00334
00335
00336 for (map<string, set<string> >::iterator i = metadata.begin(); i != metadata.end(); i++) {
00337 const string& key = i->first;
00338 const set<string>& values = i->second;
00339 for (set<string>::iterator j = values.begin(); j != values.end(); j++) {
00340 fClass->addUICode(subst("interface->declare(&$0, \"$1\", \"$2\");", tree2str(varname), wdel(key) ,wdel(*j)));
00341 }
00342 }
00343
00344 if ( isSigButton(sig, path) ) {
00345 fClass->incUIActiveCount();
00346 fClass->addUICode(subst("interface->addButton(\"$0\", &$1);", label, tree2str(varname)));
00347
00348 } else if ( isSigCheckbox(sig, path) ) {
00349 fClass->incUIActiveCount();
00350 fClass->addUICode(subst("interface->addCheckButton(\"$0\", &$1);", label, tree2str(varname)));
00351
00352 } else if ( isSigVSlider(sig, path,c,x,y,z) ) {
00353 fClass->incUIActiveCount();
00354 fClass->addUICode(subst("interface->addVerticalSlider(\"$0\", &$1, $2, $3, $4, $5);",
00355 label,
00356 tree2str(varname),
00357 T(tree2float(c)),
00358 T(tree2float(x)),
00359 T(tree2float(y)),
00360 T(tree2float(z))));
00361
00362 } else if ( isSigHSlider(sig, path,c,x,y,z) ) {
00363 fClass->incUIActiveCount();
00364 fClass->addUICode(subst("interface->addHorizontalSlider(\"$0\", &$1, $2, $3, $4, $5);",
00365 label,
00366 tree2str(varname),
00367 T(tree2float(c)),
00368 T(tree2float(x)),
00369 T(tree2float(y)),
00370 T(tree2float(z))));
00371
00372 } else if ( isSigNumEntry(sig, path,c,x,y,z) ) {
00373 fClass->incUIActiveCount();
00374 fClass->addUICode(subst("interface->addNumEntry(\"$0\", &$1, $2, $3, $4, $5);",
00375 label,
00376 tree2str(varname),
00377 T(tree2float(c)),
00378 T(tree2float(x)),
00379 T(tree2float(y)),
00380 T(tree2float(z))));
00381
00382 } else if ( isSigVBargraph(sig, path,x,y,z) ) {
00383 fClass->incUIPassiveCount();
00384 fClass->addUICode(subst("interface->addVerticalBargraph(\"$0\", &$1, $2, $3);",
00385 label,
00386 tree2str(varname),
00387 T(tree2float(x)),
00388 T(tree2float(y))));
00389
00390 } else if ( isSigHBargraph(sig, path,x,y,z) ) {
00391 fClass->incUIPassiveCount();
00392 fClass->addUICode(subst("interface->addHorizontalBargraph(\"$0\", &$1, $2, $3);",
00393 label,
00394 tree2str(varname),
00395 T(tree2float(x)),
00396 T(tree2float(y))));
00397
00398 } else {
00399 fprintf(stderr, "Error in generating widget code\n");
00400 exit(1);
00401 }
00402 }
00403
00404
00405
00410 void Compiler::generateMacroInterfaceTree(const string& pathname, Tree t)
00411 {
00412 Tree label, elements, varname, sig;
00413
00414 if (isUiFolder(t, label, elements)) {
00415 string pathname2 = pathname;
00416
00417 string str = tree2str(right(label));
00418 if (str.length()>0) pathname2 += str + "/";
00419 generateMacroInterfaceElements(pathname2, elements);
00420
00421 } else if (isUiWidget(t, label, varname, sig)) {
00422
00423 generateWidgetMacro(pathname, label, varname, sig);
00424
00425 } else {
00426
00427 fprintf(stderr, "error in user interface macro generation 2\n");
00428 exit(1);
00429
00430 }
00431 }
00432
00433
00437 void Compiler::generateMacroInterfaceElements(const string& pathname, Tree elements)
00438 {
00439 while (!isNil(elements)) {
00440 generateMacroInterfaceTree(pathname, right(hd(elements)));
00441 elements = tl(elements);
00442 }
00443 }
00444
00445
00450 void Compiler::generateWidgetMacro(const string& pathname, Tree fulllabel, Tree varname, Tree sig)
00451 {
00452 Tree path, c, x, y, z;
00453 string label;
00454 map<string, set<string> > metadata;
00455
00456 extractMetadata(tree2str(fulllabel), label, metadata);
00457
00458
00459 string pathlabel = pathname+label;
00460
00461
00462 if ( isSigButton(sig, path) ) {
00463 fClass->addUIMacro(subst("FAUST_ADDBUTTON(\"$0\", $1);", pathlabel, tree2str(varname)));
00464
00465 } else if ( isSigCheckbox(sig, path) ) {
00466 fClass->addUIMacro(subst("FAUST_ADDCHECKBOX(\"$0\", $1);", pathlabel, tree2str(varname)));
00467
00468 } else if ( isSigVSlider(sig, path,c,x,y,z) ) {
00469 fClass->addUIMacro(subst("FAUST_ADDVERTICALSLIDER(\"$0\", $1, $2, $3, $4, $5);",
00470 pathlabel,
00471 tree2str(varname),
00472 T(tree2float(c)),
00473 T(tree2float(x)),
00474 T(tree2float(y)),
00475 T(tree2float(z))));
00476
00477 } else if ( isSigHSlider(sig, path,c,x,y,z) ) {
00478 fClass->addUIMacro(subst("FAUST_ADDHORIZONTALSLIDER(\"$0\", $1, $2, $3, $4, $5);",
00479 pathlabel,
00480 tree2str(varname),
00481 T(tree2float(c)),
00482 T(tree2float(x)),
00483 T(tree2float(y)),
00484 T(tree2float(z))));
00485
00486 } else if ( isSigNumEntry(sig, path,c,x,y,z) ) {
00487 fClass->addUIMacro(subst("FAUST_ADDNUMENTRY(\"$0\", $1, $2, $3, $4, $5);",
00488 pathlabel,
00489 tree2str(varname),
00490 T(tree2float(c)),
00491 T(tree2float(x)),
00492 T(tree2float(y)),
00493 T(tree2float(z))));
00494
00495 } else if ( isSigVBargraph(sig, path,x,y,z) ) {
00496 fClass->addUIMacro(subst("FAUST_ADDVERTICALBARGRAPH(\"$0\", $1, $2, $3);",
00497 pathlabel,
00498 tree2str(varname),
00499 T(tree2float(x)),
00500 T(tree2float(y))));
00501
00502 } else if ( isSigHBargraph(sig, path,x,y,z) ) {
00503 fClass->addUIMacro(subst("FAUST_ADDHORIZONTALBARGRAPH(\"$0\", $1, $2, $3);",
00504 pathlabel,
00505 tree2str(varname),
00506 T(tree2float(x)),
00507 T(tree2float(y))));
00508
00509 } else {
00510 fprintf(stderr, "Error in generating widget code\n");
00511 exit(1);
00512 }
00513 }