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 "compile.hh" 00041 #include "sigtype.hh" 00042 00043 #include <stdio.h> 00044 //#include <iostream> 00045 00046 #include "sigprint.hh" 00047 #include "sigtyperules.hh" 00048 #include "simplify.hh" 00049 #include "privatise.hh" 00050 //#include "factorize.hh" 00051 00052 //#include "grouper.hh" 00053 //#include "sigvisitor.hh" 00054 00055 00056 00057 00058 /***************************************************************************** 00059 ****************************************************************************** 00060 00061 API 00062 00063 ****************************************************************************** 00064 *****************************************************************************/ 00065 00066 extern int gDetailsSwitch; 00067 00068 //map<string, int> Compiler::fIDCounters; 00069 /* 00070 void compileSignals (const string& name, const string& super, int numInputs, int numOutputs, Tree lsig) 00071 { 00072 Compiler C(name, super, numInputs, numOutputs); 00073 //C.getClass()->println(1); 00074 //C.getClass()->addIncludeFile("math.h"); 00075 C.compileMultiSignal(lsig); 00076 C.getClass()->printIncludeFile(); 00077 C.getClass()->println(1); 00078 } 00079 */ 00080 00081 00082 00083 00084 /***************************************************************************** 00085 ****************************************************************************** 00086 00087 GENERAL COMPILER METHODS 00088 00089 ****************************************************************************** 00090 *****************************************************************************/ 00091 00092 00093 00094 00095 00096 00097 00098 /***************************************************************************** 00099 constructor 00100 *****************************************************************************/ 00101 00102 Compiler::Compiler(const string& name, const string& super, int numInputs, int numOutputs, bool vec) 00103 : fClass(new Klass(name, super, numInputs, numOutputs, vec)), 00104 fUIRoot(uiFolder(cons(tree(0), tree("\"faust\"")))), 00105 fDescription(0) 00106 {} 00107 00108 Compiler::Compiler(Klass* k) 00109 : fClass(k), 00110 fUIRoot(uiFolder(cons(tree(0), tree("\"faust\"")))), 00111 fDescription(0) 00112 {} 00113 00114 00115 Compiler::~Compiler() 00116 {} 00117 00118 /***************************************************************************** 00119 compileMultiSignal 00120 *****************************************************************************/ 00121 /* 00122 void Compiler::compileMultiSignal (Tree L) 00123 { 00124 L = prepare(L); // optimize, share and annotate expression 00125 for (int i = 0; i < fClass->inputs(); i++) { 00126 fClass->addSlowCode(subst("float* input$0 = input[$0];", T(i))); 00127 } 00128 for (int i = 0; i < fClass->outputs(); i++) { 00129 fClass->addSlowCode(subst("float* output$0 = output[$0];", T(i))); 00130 } 00131 for (int i = 0; isList(L); L = tl(L), i++) { 00132 Tree sig = hd(L); 00133 fClass->addExecCode(subst("output$0[i] = $1;", T(i), CS(NULLENV, sig))); 00134 } 00135 generateUserInterfaceTree(fUIRoot); 00136 } 00137 */ 00138 00139 /***************************************************************************** 00140 compileSingleSignal 00141 *****************************************************************************/ 00142 /* 00143 void Compiler::compileSingleSignal (Tree sig) 00144 { 00145 sig = prepare2(sig); // optimize and annotate expression 00146 fClass->addExecCode(subst("output[i] = $0;", CS(NULLENV, sig))); 00147 //fClass->addIncludeFile("bidon"); 00148 generateUserInterfaceTree(fUIRoot); 00149 } 00150 */ 00151 00152 /***************************************************************************** 00153 Prepare signal for compilation 00154 *****************************************************************************/ 00155 00156 Tree Compiler::prepare (Tree L0) 00157 { 00158 // fprintf(stderr, "L0 = "); printSignal(L0, stderr); fputs("\n", stderr); 00159 Tree L1 = simplify(L0); // simplify by executing every computable operation 00160 //fprintf(stderr, "L1 = "); printSignal(L1, stderr); fputs("\n", stderr); 00161 Tree L2a = deBruijn2Sym(L1); 00162 Tree L2 = simplify(L2a); // simplify by executing every computable operation 00163 //Tree L2 = 00164 //factorizeAddTerms(L2); 00165 00166 //fprintf(stderr, "L2 = "); printSignal(L2, stderr); fputs("\n", stderr); 00167 Tree L3 = privatise(L2); // Un-share tables with multiple writers 00168 updateAperture(L3); 00169 typeAnnotation(L3); 00170 00171 // calcul du parallelisme 00172 //fullvisitor fv; 00173 //fv.visit(L3); 00174 00175 //grouper mygrouper; 00176 //mygrouper.visit(L3); 00177 //for (Tree zz= L3; !isNil(zz); zz = tl(zz)) mygrouper.dispatchInGroups(hd(zz)); 00178 //cerr << mygrouper << endl; 00179 00180 //sharingAnalysis(L3); // annotate L3 with sharing count 00181 // fprintf(stderr, "L3 = "); printSignal(L3, stderr); fputs("\n", stderr); 00182 00183 00184 // Type tp = getSigType(L3, NULLENV ); 00185 // if (gDetailsSwitch) { cout << "signal type details: " << tp << endl;} 00186 00187 // fCompileKey = makeCompileKey(L2); etrange !!!!! 00188 //fCompileKey = makeCompileKey(L3); 00189 return L3; 00190 } 00191 00192 Tree Compiler::prepare2 (Tree L0) 00193 { 00194 // fprintf(stderr, "L0 = "); printSignal(L0, stderr); fputs("\n", stderr); 00195 // Tree L1 = simplify(L0); // simplify by executing every computable operation 00196 // Tree L2 = deBruijn2Sym(L1); 00197 // Tree L3 = privatise(L2); // Un-share tables with multiple writers 00198 // updateAperture(L3); 00199 Tree L3 = L0; 00200 //typeAnnotation(L3); 00201 //sharingAnalysis(L3); // annotate L3 with sharing count 00202 // fprintf(stderr, "L3 = "); printSignal(L3, stderr); fputs("\n", stderr); 00203 00204 00205 // Type tp = getSigType(L3);//, NULLENV ); 00206 // if (gDetailsSwitch) { cout << "signal type details: " << tp << endl;} 00207 00208 //fCompileKey = makeCompileKey(L3); 00209 return L3; 00210 } 00211 00212 00213 00214 /***************************************************************************** 00215 CS : compile a signal 00216 *****************************************************************************/ 00223 /* 00224 string Compiler::CS (Tree env, Tree sig) 00225 { 00226 Tree t; 00227 #if 0 00228 fprintf(stderr, "CALL CS("); 00229 print(env, stderr); 00230 fprintf(stderr, ", "); 00231 printSignal(sig, stderr); 00232 fprintf(stderr, ")\n"); 00233 #endif 00234 00235 if (getProperty(sig, fCompileKey, t)) { 00236 // terme deja visité 00237 00238 #if 0 00239 fprintf(stderr, "RETURN of CS("); 00240 print(env, stderr); 00241 fprintf(stderr, ", "); 00242 printSignal(sig, stderr); 00243 fprintf(stderr, ") -found-> "); print(t, stderr); fputc('\n', stderr); 00244 #endif 00245 return name(t->node().getSym()); 00246 00247 } else { 00248 00249 string s = generateCode(env, sig); 00250 const char * r = s.c_str(); 00251 setProperty(sig, fCompileKey, tree(r)); 00252 00253 #if 0 00254 fprintf(stderr, "RETURN of CS("); 00255 print(env, stderr); 00256 fprintf(stderr, ", "); 00257 printSignal(sig, stderr); 00258 fprintf(stderr, ") -computed-> %s \n", r); 00259 #endif 00260 return s; 00261 } 00262 } 00263 */ 00264 00265 00266 /***************************************************************************** 00267 generateCode : dispatch according to signal 00268 *****************************************************************************/ 00275 /* 00276 string Compiler::generateCode (Tree env, Tree sig) 00277 { 00278 #if 0 00279 fprintf(stderr, "CALL generateCode("); 00280 print(env, stderr); 00281 fprintf(stderr, ", "); 00282 printSignal(sig, stderr); 00283 fprintf(stderr, ")\n"); 00284 #endif 00285 00286 int i; 00287 float r; 00288 //const char *ct, *vn; 00289 Tree c, sel, x, y, z, var, le, label, id, ff, largs; 00290 00291 //printf("compilation of %p : ", sig); print(sig); printf("\n"); 00292 00293 if ( isSigInt(sig, &i) ) { return T(i); } 00294 else if ( isSigReal(sig, &r) ) { return T(r); } 00295 else if ( isSigInput(sig, &i) ) { return generateInput (env, sig, T(i)); } 00296 else if ( isSigOutput(sig, &i, x) ) { return generateOutput (env, sig, T(i), CS(env,x));} 00297 00298 else if ( isSigDelay1(sig, x) ) { return generateDelay1 (env, sig, x); } 00299 00300 else if ( isSigBinOp(sig, &i, x, y) ) { return generateBinOp (env, sig, i, x, y); } 00301 else if ( isSigFFun(sig, ff, largs) ) { return generateFFun (env, sig, ff, largs); } 00302 00303 else if ( isSigTable(sig, id, x, y) ) { return generateTable (env, sig, x, y); } 00304 else if ( isSigWRTbl(sig, id, x, y, z) ) { return generateWRTbl (env, sig, x, y, z); } 00305 else if ( isSigRDTbl(sig, x, y) ) { return generateRDTbl (env, sig, x, y); } 00306 00307 else if ( isSigSelect2(sig, sel, x, y) ) { return generateSelect2 (env, sig, sel, x, y); } 00308 else if ( isSigSelect3(sig, sel, x, y, z) ) { return generateSelect3 (env, sig, sel, x, y, z); } 00309 00310 else if ( isSigGen(sig, x) ) { return generateSigGen (env, sig, x); } 00311 00312 else if ( isProj(sig, &i, x) ) { return generateRecProj (env, sig, CS(env,x), i); } 00313 else if ( isRec(sig, var, le)) { return generateRecGroup (env, sig, var, le); } 00314 //else if ( isRef(sig, var) ) { return CS(env,var); } //compiled in enclosing rec 00315 00316 else if ( isSigIntCast(sig, x) ) { return generateIntCast (env, sig, x); } 00317 else if ( isSigFloatCast(sig, x) ) { return generateFloatCast (env, sig, x); } 00318 00319 else if ( isSigButton(sig, label) ) { return generateButton (env, sig, label); } 00320 else if ( isSigCheckbox(sig, label) ) { return generateCheckbox (env, sig, label); } 00321 else if ( isSigVSlider(sig, label,c,x,y,z) ) { return generateVSlider (env, sig, label, c,x,y,z); } 00322 else if ( isSigHSlider(sig, label,c,x,y,z) ) { return generateHSlider (env, sig, label, c,x,y,z); } 00323 else if ( isSigNumEntry(sig, label,c,x,y,z) ) { return generateNumEntry (env, sig, label, c,x,y,z); } 00324 00325 else { 00326 printf("Error in compiling signal :"); 00327 print(sig); 00328 printf("\n"); 00329 exit(1); 00330 } 00331 return "error in generate code"; 00332 } 00333 */ 00334 00335 00336 00337 /***************************************************************************** 00338 getFreshID 00339 *****************************************************************************/ 00340 /* 00341 string Compiler::getFreshID(const char* prefix) 00342 { 00343 char c[64]; 00344 00345 if (fIDCounters.find(prefix) == fIDCounters.end()) { 00346 fIDCounters[prefix]=0;; 00347 } 00348 int n = fIDCounters[prefix]; 00349 fIDCounters[prefix] = n+1; 00350 00351 snprintf(c, 63, "%s%d", prefix, n); 00352 return string(c); 00353 } 00354 */ 00355 00356 00357 /***************************************************************************** 00358 makeCompileKey 00359 *****************************************************************************/ 00360 /* 00361 Tree Compiler::makeCompileKey(Tree t) 00362 { 00363 char name[256]; 00364 snprintf(name, 256, "COMPILED IN %p : ", (CTree*)t); 00365 return tree(unique(name)); 00366 } 00367 00368 */ 00369 00370 00371 00372 /***************************************************************************** 00373 user interface elements 00374 *****************************************************************************/ 00375 00376 void Compiler::addUIWidget(Tree path, Tree widget) 00377 { 00378 fUIRoot = putSubFolder(fUIRoot, path, widget); 00379 } 00380 00381 void Compiler::generateWidgetCode(Tree label, Tree varname, Tree sig) 00382 { 00383 Tree path, c, x, y, z; 00384 00385 if ( isSigButton(sig, path) ) { 00386 fClass->addUICode(subst("interface->addButton($0, &$1);", tree2str(label), tree2str(varname))); 00387 00388 } else if ( isSigCheckbox(sig, path) ) { 00389 fClass->addUICode(subst("interface->addCheckButton($0, &$1);", tree2str(label), tree2str(varname))); 00390 00391 } else if ( isSigVSlider(sig, path,c,x,y,z) ) { 00392 fClass->addUICode(subst("interface->addVerticalSlider($0, &$1, $2, $3, $4, $5);", 00393 tree2str(label), 00394 tree2str(varname), 00395 T(tree2float(c)), 00396 T(tree2float(x)), 00397 T(tree2float(y)), 00398 T(tree2float(z)))); 00399 00400 } else if ( isSigHSlider(sig, path,c,x,y,z) ) { 00401 fClass->addUICode(subst("interface->addHorizontalSlider($0, &$1, $2, $3, $4, $5);", 00402 tree2str(label), 00403 tree2str(varname), 00404 T(tree2float(c)), 00405 T(tree2float(x)), 00406 T(tree2float(y)), 00407 T(tree2float(z)))); 00408 00409 } else if ( isSigNumEntry(sig, path,c,x,y,z) ) { 00410 fClass->addUICode(subst("interface->addNumEntry($0, &$1, $2, $3, $4, $5);", 00411 tree2str(label), 00412 tree2str(varname), 00413 T(tree2float(c)), 00414 T(tree2float(x)), 00415 T(tree2float(y)), 00416 T(tree2float(z)))); 00417 00418 } else if ( isSigVBargraph(sig, path,x,y,z) ) { 00419 fClass->addUICode(subst("interface->addVerticalBargraph($0, &$1, $2, $3);", 00420 tree2str(label), 00421 tree2str(varname), 00422 T(tree2float(x)), 00423 T(tree2float(y)))); 00424 00425 } else if ( isSigHBargraph(sig, path,x,y,z) ) { 00426 fClass->addUICode(subst("interface->addHorizontalBargraph($0, &$1, $2, $3);", 00427 tree2str(label), 00428 tree2str(varname), 00429 T(tree2float(x)), 00430 T(tree2float(y)))); 00431 00432 } else { 00433 fprintf(stderr, "Error in generating widget code\n"); 00434 exit(1); 00435 } 00436 } 00437 00438 00439 // Remove fake root folder if not needed (that is if the UI 00440 // is completely enclosed in one folder 00441 Tree Compiler::prepareUserInterfaceTree(Tree t) 00442 { 00443 Tree root, elems; 00444 if (isUiFolder(t, root, elems) && isList(elems) && isNil(tl(elems)) ) { 00445 Tree folder = right(hd(elems)); 00446 return (isUiFolder(folder)) ? folder : t; 00447 } 00448 return t; 00449 } 00450 00451 void Compiler::generateUserInterfaceTree(Tree t) 00452 { 00453 Tree label, elements, varname, sig; 00454 00455 if (isUiFolder(t, label, elements)) { 00456 const int orient = tree2int(left(label)); 00457 const char * str = tree2str(right(label)); 00458 const char * model; 00459 00460 switch (orient) { 00461 case 0 : model = "interface->openVerticalBox($0);"; break; 00462 case 1 : model = "interface->openHorizontalBox($0);"; break; 00463 case 2 : model = "interface->openTabBox($0);"; break; 00464 default : 00465 fprintf(stderr, "error in user interface generation 1\n"); 00466 exit(1); 00467 } 00468 fClass->addUICode(subst(model, str)); 00469 generateUserInterfaceElements(elements); 00470 fClass->addUICode("interface->closeBox();"); 00471 00472 } else if (isUiWidget(t, label, varname, sig)) { 00473 00474 generateWidgetCode(label, varname, sig); 00475 00476 } else { 00477 00478 fprintf(stderr, "error in user interface generation 2\n"); 00479 exit(1); 00480 00481 } 00482 } 00483 00484 void Compiler::generateUserInterfaceElements(Tree elements) 00485 { 00486 while (!isNil(elements)) { 00487 generateUserInterfaceTree(right(hd(elements))); 00488 elements = tl(elements); 00489 } 00490 }