1 /************************************************************************ 2 ************************************************************************ 3 FAUST compiler 4 Copyright (C) 2003-2019 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 #ifndef _SOUL_INSTRUCTIONS_H 23 #define _SOUL_INSTRUCTIONS_H 24 25 #include <sstream> 26 #include <string> 27 #include <vector> 28 #include <utility> 29 #include <cctype> 30 31 #include "text_instructions.hh" 32 #include "faust/gui/PathBuilder.h" 33 34 using namespace std; 35 36 struct SOULInstUIVisitor : public DispatchVisitor, public PathBuilder { 37 std::stringstream fOut; 38 SOULStringTypeManager fTypeManager; 39 int fTab; 40 bool fHasBargraph; // Whether the DSP code has some Bargraphs 41 42 std::vector<std::pair <std::string, std::string> > fMetaAux; 43 44 using DispatchVisitor::visit; 45 SOULInstUIVisitorSOULInstUIVisitor46 SOULInstUIVisitor(int tab = 1) : fTypeManager(xfloat(), "*"), fTab(tab), fHasBargraph(false) {} 47 addMetaSOULInstUIVisitor48 void addMeta() 49 { 50 if (fMetaAux.size() > 0) { 51 for (size_t i = 0; i < fMetaAux.size(); i++) { 52 if (!std::isdigit(fMetaAux[i].first[0])) { 53 fOut << ", " << "meta_" + gGlobal->getFreshID(fMetaAux[i].first) << ": " << quote(fMetaAux[i].second); 54 } 55 } 56 } 57 fMetaAux.clear(); 58 } 59 getSoulMatadataSOULInstUIVisitor60 std::string getSoulMatadata() 61 { 62 if (fMetaAux.size() > 0) { 63 for (size_t i = 0; i < fMetaAux.size(); i++) { 64 if (fMetaAux[i].first == "soul") return fMetaAux[i].second; 65 } 66 } 67 return ""; 68 } 69 visitSOULInstUIVisitor70 virtual void visit(AddMetaDeclareInst* inst) 71 { 72 fMetaAux.push_back(std::make_pair(inst->fKey, inst->fValue)); 73 } 74 visitSOULInstUIVisitor75 virtual void visit(AddButtonInst* inst) 76 { 77 if (gGlobal->gOutputLang == "soul-poly") { 78 vector<char> rep = {' ', '(', ')', '/', '\\', '.', '-'}; 79 fOut << "input event " << fTypeManager.fTypeDirectTable[itfloat()] 80 << " event_" << replaceCharList(inst->fLabel, rep, '_') 81 << " [[ name: " << quote(inst->fLabel) 82 << ", group: " << quote(buildPath(inst->fLabel)); 83 if (inst->fType != AddButtonInst::kDefaultButton) { 84 fOut << ", latching"; 85 } 86 fOut<< ", text: \"off|on\"" 87 << ", boolean"; 88 addMeta(); 89 fOut << " ]];"; 90 } else if (gGlobal->gOutputLang == "soul-hybrid") { 91 string soul_meta = getSoulMatadata(); 92 vector<char> rep = {' ', '(', ')', '/', '\\', '.', '-'}; 93 fOut << "input event " << fTypeManager.fTypeDirectTable[itfloat()] 94 << " " << ((soul_meta != "") ? soul_meta : replaceCharList(inst->fLabel, rep, '_')) 95 << " [[ name: " << quote(inst->fLabel) 96 << ", group: " << quote(buildPath(inst->fLabel)); 97 if (inst->fType != AddButtonInst::kDefaultButton) { 98 fOut << ", latching"; 99 } 100 fOut << ", text: \"off|on\"" 101 << ", boolean"; 102 addMeta(); 103 fOut << " ]];"; 104 } else { 105 fOut << "input event " << fTypeManager.fTypeDirectTable[itfloat()] 106 << " event" << inst->fZone 107 << " [[ name: " << quote(inst->fLabel) 108 << ", group: " << quote(buildPath(inst->fLabel)); 109 if (inst->fType != AddButtonInst::kDefaultButton) { 110 fOut << ", latching"; 111 } 112 fOut << ", text: \"off|on\"" 113 << ", boolean"; 114 addMeta(); 115 fOut << " ]];"; 116 } 117 tab(fTab, fOut); 118 } 119 visitSOULInstUIVisitor120 virtual void visit(AddSliderInst* inst) 121 { 122 if (gGlobal->gOutputLang == "soul-poly") { 123 vector<char> rep = {' ', '(', ')', '/', '\\', '.', '-'}; 124 fOut << "input event " << fTypeManager.fTypeDirectTable[itfloat()] 125 << " event_" << replaceCharList(inst->fLabel, rep, '_') 126 << " [[ name: " << quote(inst->fLabel) 127 << ", group: " << quote(buildPath(inst->fLabel)) 128 << ", min: " << checkReal(inst->fMin) 129 << ", max: " << checkReal(inst->fMax) 130 << ", init: " << checkReal(inst->fInit) 131 << ", step: " << checkReal(inst->fStep); 132 addMeta(); 133 fOut << " ]];"; 134 } else if (gGlobal->gOutputLang == "soul-hybrid") { 135 string soul_meta = getSoulMatadata(); 136 vector<char> rep = {' ', '(', ')', '/', '\\', '.'}; 137 fOut << "input event " << fTypeManager.fTypeDirectTable[itfloat()] 138 << " " << ((soul_meta != "") ? soul_meta : replaceCharList(inst->fLabel, rep, '_')) 139 << " [[ name: " << quote(inst->fLabel) 140 << ", group: " << quote(buildPath(inst->fLabel)) 141 << ", min: " << checkReal(inst->fMin) 142 << ", max: " << checkReal(inst->fMax) 143 << ", init: " << checkReal(inst->fInit) 144 << ", step: " << checkReal(inst->fStep); 145 addMeta(); 146 fOut << " ]];"; 147 } else { 148 fOut << "input event " << fTypeManager.fTypeDirectTable[itfloat()] 149 << " event" << inst->fZone 150 << " [[ name: " << quote(inst->fLabel) 151 << ", group: " << quote(buildPath(inst->fLabel)) 152 << ", min: " << checkReal(inst->fMin) 153 << ", max: " << checkReal(inst->fMax) 154 << ", init: " << checkReal(inst->fInit) 155 << ", step: " << checkReal(inst->fStep); 156 addMeta(); 157 fOut << " ]];"; 158 } 159 tab(fTab, fOut); 160 } 161 visitSOULInstUIVisitor162 virtual void visit(AddBargraphInst* inst) 163 { 164 // We have bargraphs 165 fHasBargraph = true; 166 167 if (gGlobal->gOutputLang == "soul-poly") { 168 vector<char> rep = {' ', '(', ')', '/', '\\', '.', '-'}; 169 fOut << "output event " << fTypeManager.fTypeDirectTable[itfloat()] 170 << " event_" << quote(replaceCharList(inst->fLabel, rep, '_')) 171 << " [[ name: " << quote(inst->fLabel) 172 << ", group: " << quote(buildPath(inst->fLabel)) 173 << ", min: " << checkReal(inst->fMin) 174 << ", max: " << checkReal(inst->fMax); 175 addMeta(); 176 fOut << " ]];"; 177 } else if (gGlobal->gOutputLang == "soul-hybrid") { 178 string soul_meta = getSoulMatadata(); 179 vector<char> rep = {' ', '(', ')', '/', '\\', '.', '-'}; 180 fOut << "output event " << fTypeManager.fTypeDirectTable[itfloat()] 181 << " " << ((soul_meta != "") ? soul_meta : replaceCharList(inst->fLabel, rep, '_')) 182 << " [[ name: " << quote(inst->fLabel) 183 << ", group: " << quote(buildPath(inst->fLabel)) 184 << ", min: " << checkReal(inst->fMin) 185 << ", max: " << checkReal(inst->fMax); 186 addMeta(); 187 fOut << " ]];"; 188 } else { 189 fOut << "output event " << fTypeManager.fTypeDirectTable[itfloat()] 190 << " event" << inst->fZone 191 << " [[ name: " << quote(inst->fLabel) 192 << ", group: " << quote(buildPath(inst->fLabel)) 193 << ", min: " << checkReal(inst->fMin) 194 << ", max: " << checkReal(inst->fMax); 195 addMeta(); 196 fOut << " ]];"; 197 } 198 tab(fTab, fOut); 199 } 200 visitSOULInstUIVisitor201 virtual void visit(OpenboxInst* inst) 202 { 203 switch (inst->fOrient) { 204 case OpenboxInst::kVerticalBox: 205 pushLabel("v:" + inst->fName); 206 break; 207 case OpenboxInst::kHorizontalBox: 208 pushLabel("h:" + inst->fName); 209 break; 210 case OpenboxInst::kTabBox: 211 pushLabel("t:" + inst->fName); 212 break; 213 } 214 fMetaAux.clear(); 215 } 216 visitSOULInstUIVisitor217 virtual void visit(CloseboxInst* inst) 218 { 219 popLabel(); 220 fMetaAux.clear(); 221 } 222 223 }; 224 225 class SOULInstVisitor : public TextInstVisitor { 226 private: 227 // Polymorphic math functions 228 map<string, string> gPolyMathLibTable; 229 230 // Whether to consider an 'int' as a 'boolean' later on in code generation 231 bool fIntAsBool; 232 233 std::vector<std::pair <std::string, std::string> > fMetaAux; 234 checkFloat(float val)235 inline string checkFloat(float val) 236 { 237 return (std::isinf(val)) ? "inf" : T(val); 238 } checkDouble(double val)239 inline string checkDouble(double val) 240 { 241 return (std::isinf(val)) ? "inf" : T(val); 242 } 243 getSoulMatadata()244 std::string getSoulMatadata() 245 { 246 if (fMetaAux.size() > 0) { 247 for (size_t i = 0; i < fMetaAux.size(); i++) { 248 if (fMetaAux[i].first == "soul") return fMetaAux[i].second; 249 } 250 } 251 return ""; 252 } 253 254 public: SOULInstVisitor(std::ostream * out,int tab=0)255 SOULInstVisitor(std::ostream* out, int tab = 0) 256 : TextInstVisitor(out, ".", new SOULStringTypeManager(xfloat(), ""), tab) 257 { 258 // Polymath mapping int version 259 gPolyMathLibTable["abs"] = "abs"; 260 gPolyMathLibTable["max_i"] = "max"; 261 gPolyMathLibTable["min_i"] = "min"; 262 263 // Polymath mapping float version 264 gPolyMathLibTable["max_f"] = "max"; 265 gPolyMathLibTable["min_f"] = "min"; 266 267 gPolyMathLibTable["fabsf"] = "abs"; 268 gPolyMathLibTable["acosf"] = "acos"; 269 gPolyMathLibTable["asinf"] = "asin"; 270 gPolyMathLibTable["atanf"] = "atan"; 271 gPolyMathLibTable["atan2f"] = "atan2"; 272 gPolyMathLibTable["ceilf"] = "ceil"; 273 gPolyMathLibTable["cosf"] = "cos"; 274 gPolyMathLibTable["expf"] = "exp"; 275 gPolyMathLibTable["exp2f"] = "exp2"; 276 gPolyMathLibTable["exp10f"] = "exp10f"; 277 gPolyMathLibTable["floorf"] = "floor"; 278 gPolyMathLibTable["fmodf"] = "fmod"; 279 gPolyMathLibTable["logf"] = "log"; 280 gPolyMathLibTable["log2f"] = "log2"; 281 gPolyMathLibTable["log10f"] = "log10"; 282 gPolyMathLibTable["powf"] = "pow"; 283 gPolyMathLibTable["remainderf"] = "remainder"; 284 gPolyMathLibTable["rintf"] = "roundToInt"; 285 gPolyMathLibTable["roundf"] = "round"; 286 gPolyMathLibTable["sinf"] = "sin"; 287 gPolyMathLibTable["sqrtf"] = "sqrt"; 288 gPolyMathLibTable["tanf"] = "tan"; 289 290 // Additional hyperbolic math functions are included in SOUL 291 gPolyMathLibTable["acoshf"] = "acosh"; 292 gPolyMathLibTable["asinhf"] = "asinh"; 293 gPolyMathLibTable["atanhf"] = "atanh"; 294 gPolyMathLibTable["coshf"] = "cosh"; 295 gPolyMathLibTable["sinhf"] = "sinh"; 296 gPolyMathLibTable["tanhf"] = "tanh"; 297 298 gPolyMathLibTable["isnanf"] = "isnan"; 299 gPolyMathLibTable["isinff"] = "isinf"; 300 // Manually implemented 301 gPolyMathLibTable["copysignf"] = "copysign"; 302 303 // Polymath mapping double version 304 gPolyMathLibTable["max_"] = "max"; 305 gPolyMathLibTable["min_"] = "min"; 306 307 gPolyMathLibTable["fabs"] = "abs"; 308 gPolyMathLibTable["acos"] = "acos"; 309 gPolyMathLibTable["asin"] = "asin"; 310 gPolyMathLibTable["atan"] = "atan"; 311 gPolyMathLibTable["atan2"] = "atan2"; 312 gPolyMathLibTable["ceil"] = "ceil"; 313 gPolyMathLibTable["cos"] = "cos"; 314 gPolyMathLibTable["exp"] = "exp"; 315 gPolyMathLibTable["exp2"] = "exp2"; 316 gPolyMathLibTable["exp10"] = "exp10"; 317 gPolyMathLibTable["floor"] = "floor"; 318 gPolyMathLibTable["fmod"] = "fmod"; 319 gPolyMathLibTable["log"] = "log"; 320 gPolyMathLibTable["log2"] = "log2"; 321 gPolyMathLibTable["log10"] = "log10"; 322 gPolyMathLibTable["pow"] = "pow"; 323 gPolyMathLibTable["remainder"] = "remainder"; 324 gPolyMathLibTable["rint"] = "roundToInt"; 325 gPolyMathLibTable["round"] = "round"; 326 gPolyMathLibTable["sin"] = "sin"; 327 gPolyMathLibTable["sqrt"] = "sqrt"; 328 gPolyMathLibTable["tan"] = "tan"; 329 330 // Additional hyperbolic math functions are included in SOUL 331 gPolyMathLibTable["acosh"] = "acosh"; 332 gPolyMathLibTable["asinh"] = "asinh"; 333 gPolyMathLibTable["atanh"] = "atanh"; 334 gPolyMathLibTable["cosh"] = "cosh"; 335 gPolyMathLibTable["sinh"] = "sinh"; 336 gPolyMathLibTable["tanh"] = "tanh"; 337 338 gPolyMathLibTable["isnan"] = "isnan"; 339 gPolyMathLibTable["isinf"] = "isinf"; 340 // Manually implemented 341 gPolyMathLibTable["copysignf"] = "copysign"; 342 343 fIntAsBool = false; 344 } 345 ~SOULInstVisitor()346 virtual ~SOULInstVisitor() {} 347 visit(AddMetaDeclareInst * inst)348 virtual void visit(AddMetaDeclareInst* inst) 349 { 350 fMetaAux.push_back(std::make_pair(inst->fKey, inst->fValue)); 351 } 352 visit(OpenboxInst * inst)353 virtual void visit(OpenboxInst* inst) 354 { 355 fMetaAux.clear(); 356 } 357 visit(CloseboxInst * inst)358 virtual void visit(CloseboxInst* inst) 359 { 360 fMetaAux.clear(); 361 } 362 visit(AddButtonInst * inst)363 virtual void visit(AddButtonInst* inst) 364 { 365 *fOut << "// " << inst->fLabel; 366 EndLine(' '); 367 if (gGlobal->gOutputLang == "soul-poly") { 368 vector<char> rep = {' ', '(', ')', '/', '\\', '.', '-'}; 369 *fOut << "event event_" << replaceCharList(inst->fLabel, rep, '_') << " (" 370 << fTypeManager->fTypeDirectTable[itfloat()] << " val) { " << inst->fZone 371 << " = val; fUpdated = true; }"; 372 } else if (gGlobal->gOutputLang == "soul-hybrid") { 373 string soul_meta = getSoulMatadata(); 374 vector<char> rep = {' ', '(', ')', '/', '\\', '.', '-'}; 375 *fOut << "event " << ((soul_meta != "") ? soul_meta : replaceCharList(inst->fLabel, rep, '_')) 376 << " (" << fTypeManager->fTypeDirectTable[itfloat()] << " val) { " 377 << inst->fZone << " = val; fUpdated = true; }"; 378 fMetaAux.clear(); 379 } else { 380 *fOut << "event event" << inst->fZone << " (" << fTypeManager->fTypeDirectTable[itfloat()] << " val) { " 381 << inst->fZone << " = val; fUpdated = true; }"; 382 } 383 EndLine(' '); 384 } 385 visit(AddSliderInst * inst)386 virtual void visit(AddSliderInst* inst) 387 { 388 *fOut << "// " << inst->fLabel << " [init = " << checkReal(inst->fInit) 389 << ", min = " << checkReal(inst->fMin) << ", max = " << checkReal(inst->fMax) 390 << ", step = " << checkReal(inst->fStep) << "]"; 391 EndLine(' '); 392 if (gGlobal->gOutputLang == "soul-poly") { 393 vector<char> rep = {' ', '(', ')', '/', '\\', '.', '-'}; 394 *fOut << "event event_" << replaceCharList(inst->fLabel, rep, '_') << " (" 395 << fTypeManager->fTypeDirectTable[itfloat()] << " val) { " << inst->fZone 396 << " = val; fUpdated = true; }"; 397 } else if (gGlobal->gOutputLang == "soul-hybrid") { 398 string soul_meta = getSoulMatadata(); 399 vector<char> rep = {' ', '(', ')', '/', '\\', '.', '-'}; 400 *fOut << "event " << ((soul_meta != "") ? soul_meta : replaceCharList(inst->fLabel, rep, '_')) 401 << " (" << fTypeManager->fTypeDirectTable[itfloat()] << " val) { " 402 << inst->fZone << " = val; fUpdated = true; }"; 403 fMetaAux.clear(); 404 } else { 405 *fOut << "event event" << inst->fZone << " (" << fTypeManager->fTypeDirectTable[itfloat()] << " val) { " 406 << inst->fZone << " = val; fUpdated = true; }"; 407 } 408 EndLine(' '); 409 } 410 visit(AddBargraphInst * inst)411 virtual void visit(AddBargraphInst* inst) 412 { 413 *fOut << "// " << inst->fLabel << " [min = " << checkReal(inst->fMin) << ", max = " << checkReal(inst->fMax) 414 << "]"; 415 EndLine(' '); 416 } 417 visit(AddSoundfileInst * inst)418 virtual void visit(AddSoundfileInst* inst) 419 { 420 // Not supported for now 421 throw faustexception("ERROR : 'soundfile' primitive not yet supported for SOUL\n"); 422 } 423 visit(DeclareVarInst * inst)424 virtual void visit(DeclareVarInst* inst) 425 { 426 string name = inst->fAddress->getName(); 427 428 // special case for input/output considered as 'streams' 429 if (startWith(name, "input")) { 430 *fOut << "input stream " << fTypeManager->fTypeDirectTable[itfloat()] << " " << name; 431 } else if (startWith(name, "output")) { 432 *fOut << "output stream " << fTypeManager->fTypeDirectTable[itfloat()] << " " << name; 433 } else { 434 if (inst->fAddress->getAccess() & Address::kConst) { 435 *fOut << "const "; 436 } 437 *fOut << fTypeManager->generateType(inst->fType, name); 438 if (inst->fValue) { 439 *fOut << " = "; 440 inst->fValue->accept(this); 441 } 442 } 443 EndLine(); 444 } 445 visit(DeclareFunInst * inst)446 virtual void visit(DeclareFunInst* inst) {} 447 448 /* 449 Indexed adresses can actually be values in an array or fields in a struct type 450 */ visit(IndexedAddress * indexed)451 virtual void visit(IndexedAddress* indexed) 452 { 453 indexed->fAddress->accept(this); 454 DeclareStructTypeInst* struct_type = isStructType(indexed->getName()); 455 if (struct_type) { 456 Int32NumInst* field_index = static_cast<Int32NumInst*>(indexed->fIndex); 457 *fOut << "." << struct_type->fType->getName(field_index->fNum); 458 } else { 459 if (dynamic_cast<Int32NumInst*>(indexed->fIndex)) { 460 *fOut << "["; 461 indexed->fIndex->accept(this); 462 *fOut << "]"; 463 } else { 464 // wrap code is automatically added by the SOUL compiler (and the same if [idex] syntax is used) 465 *fOut << ".at ("; 466 indexed->fIndex->accept(this); 467 *fOut << ")"; 468 } 469 } 470 } 471 visit(StoreVarInst * inst)472 virtual void visit(StoreVarInst* inst) 473 { 474 // special case for 'output' considered as a 'stream' 475 if (startWith(inst->fAddress->getName(), "output")) { 476 inst->fAddress->accept(this); 477 *fOut << " << "; 478 inst->fValue->accept(this); 479 EndLine(); 480 // special case for 'bargraph' considered as an 'output event' 481 } else if (startWith(inst->fAddress->getName(), "fHbargraph") || 482 startWith(inst->fAddress->getName(), "fVbargraph")) { 483 484 // value is stored in the bargraph variable 485 { 486 inst->fAddress->accept(this); 487 *fOut << " = "; 488 inst->fValue->accept(this); 489 EndLine(); 490 } 491 492 // and the bargraph variable is sent using the 'output' event handler 493 { 494 *fOut << "if (fControlSlice == 0) { "; 495 *fOut << "event"; 496 inst->fAddress->accept(this); 497 *fOut << " << "; 498 inst->fAddress->accept(this); 499 *fOut << "; }"; 500 tab(fTab, *fOut); 501 } 502 503 } else { 504 inst->fAddress->accept(this); 505 *fOut << " = "; 506 inst->fValue->accept(this); 507 EndLine(); 508 } 509 } 510 visit(FloatNumInst * inst)511 virtual void visit(FloatNumInst* inst) { *fOut << checkFloat(inst->fNum); } 512 visit(FloatArrayNumInst * inst)513 virtual void visit(FloatArrayNumInst* inst) 514 { 515 char sep = '('; 516 for (size_t i = 0; i < inst->fNumTable.size(); i++) { 517 *fOut << sep << checkFloat(inst->fNumTable[i]); 518 sep = ','; 519 } 520 *fOut << ')'; 521 } 522 visit(Int32ArrayNumInst * inst)523 virtual void visit(Int32ArrayNumInst* inst) 524 { 525 char sep = '('; 526 for (size_t i = 0; i < inst->fNumTable.size(); i++) { 527 *fOut << sep << inst->fNumTable[i]; 528 sep = ','; 529 } 530 *fOut << ')'; 531 } 532 visit(Int64NumInst * inst)533 virtual void visit(Int64NumInst* inst) { *fOut << inst->fNum << "L"; } 534 visit(DoubleNumInst * inst)535 virtual void visit(DoubleNumInst* inst) { *fOut << checkDouble(inst->fNum); } 536 visit(DoubleArrayNumInst * inst)537 virtual void visit(DoubleArrayNumInst* inst) 538 { 539 char sep = '('; 540 for (size_t i = 0; i < inst->fNumTable.size(); i++) { 541 *fOut << sep << checkDouble(inst->fNumTable[i]); 542 sep = ','; 543 } 544 *fOut << ')'; 545 } 546 visit(::CastInst * inst)547 virtual void visit(::CastInst* inst) 548 { 549 string type = fTypeManager->generateType(inst->fType); 550 *fOut << type << " ("; 551 inst->fInst->accept(this); 552 *fOut << ")"; 553 } 554 visit(BitcastInst * inst)555 virtual void visit(BitcastInst* inst) { faustassert(false); } 556 visit(Select2Inst * inst)557 virtual void visit(Select2Inst* inst) 558 { 559 *fOut << "(bool ("; 560 fIntAsBool = true; 561 inst->fCond->accept(this); 562 fIntAsBool = false; 563 *fOut << ") ? "; 564 inst->fThen->accept(this); 565 *fOut << " : "; 566 inst->fElse->accept(this); 567 *fOut << ")"; 568 } 569 visit(IfInst * inst)570 virtual void visit(IfInst* inst) 571 { 572 *fOut << "if "; 573 *fOut << "(bool ("; 574 fIntAsBool = true; 575 visitCond(inst->fCond); 576 fIntAsBool = false; 577 *fOut << "))"; 578 *fOut << " {"; 579 fTab++; 580 tab(fTab, *fOut); 581 inst->fThen->accept(this); 582 fTab--; 583 back(1, *fOut); 584 if (inst->fElse->fCode.size() > 0) { 585 *fOut << "} else {"; 586 fTab++; 587 tab(fTab, *fOut); 588 inst->fElse->accept(this); 589 fTab--; 590 back(1, *fOut); 591 *fOut << "}"; 592 } else { 593 *fOut << "}"; 594 } 595 tab(fTab, *fOut); 596 } 597 visit(BinopInst * inst)598 virtual void visit(BinopInst* inst) 599 { 600 bool int_as_bool = fIntAsBool; 601 if (isBoolOpcode(inst->fOpcode) && !int_as_bool) { 602 *fOut << "int ("; 603 } 604 *fOut << "("; 605 606 // Hack to make it work again with 'soul' version 0.0.6 607 if (isLogicalOpcode(inst->fOpcode)) { 608 TypingVisitor typing; 609 inst->fInst1->accept(&typing); 610 if (isInt64Type(typing.fCurType)) { 611 *fOut << "int64 ("; 612 } else if (isInt32Type(typing.fCurType) || isBoolType(typing.fCurType)) { 613 *fOut << "int32 ("; 614 } else { 615 faustassert(false); 616 } 617 } 618 619 inst->fInst1->accept(this); 620 621 // Hack to make it work again with 'soul' version 0.0.6 622 if (isLogicalOpcode(inst->fOpcode)) { 623 *fOut << ")"; 624 } 625 626 *fOut << " "; 627 *fOut << gBinOpTable[inst->fOpcode]->fName; 628 *fOut << " "; 629 630 // Hack to make it work again with 'soul' version 0.0.6 631 if (isLogicalOpcode(inst->fOpcode)) { 632 TypingVisitor typing; 633 inst->fInst2->accept(&typing); 634 if (isInt64Type(typing.fCurType)) { 635 *fOut << "int64 ("; 636 } else if (isInt32Type(typing.fCurType) || isBoolType(typing.fCurType)) { 637 *fOut << "int32 ("; 638 } else { 639 faustassert(false); 640 } 641 } 642 643 inst->fInst2->accept(this); 644 645 // Hack to make it work again with 'soul' version 0.0.6 646 if (isLogicalOpcode(inst->fOpcode)) { 647 *fOut << ")"; 648 } 649 650 *fOut << ")"; 651 if (isBoolOpcode(inst->fOpcode) && !int_as_bool) { 652 *fOut << ")"; 653 } 654 } 655 visit(FunCallInst * inst)656 virtual void visit(FunCallInst* inst) 657 { 658 string name; 659 if (gPolyMathLibTable.find(inst->fName) != gPolyMathLibTable.end()) { 660 name = gPolyMathLibTable[inst->fName]; 661 } else { 662 name = inst->fName; 663 } 664 665 *fOut << gGlobal->getMathFunction(name) << ((inst->fArgs.size() > 0) ? " (" : "("); 666 667 // Compile parameters 668 generateFunCallArgs(inst->fArgs.begin(), inst->fArgs.end(), inst->fArgs.size()); 669 *fOut << ")"; 670 } 671 visit(ForLoopInst * inst)672 virtual void visit(ForLoopInst* inst) 673 { 674 // Don't generate empty loops... 675 if (inst->fCode->size() == 0) return; 676 677 *fOut << "for ("; 678 679 fFinishLine = false; 680 inst->fInit->accept(this); 681 *fOut << "; "; 682 683 fIntAsBool = true; 684 inst->fEnd->accept(this); 685 fIntAsBool = false; 686 *fOut << "; "; 687 688 inst->fIncrement->accept(this); 689 fFinishLine = true; 690 *fOut << ") {"; 691 692 fTab++; 693 tab(fTab, *fOut); 694 inst->fCode->accept(this); 695 fTab--; 696 back(1, *fOut); 697 *fOut << "}"; 698 tab(fTab, *fOut); 699 } 700 getTypeManager()701 StringTypeManager* getTypeManager() { return fTypeManager; } 702 }; 703 704 // For subcontainers: variable access is specific 705 class SOULSubContainerInstVisitor : public SOULInstVisitor { 706 public: SOULSubContainerInstVisitor(std::ostream * out,int tab=0)707 SOULSubContainerInstVisitor(std::ostream* out, int tab = 0) : SOULInstVisitor(out, tab) {} 708 visit(NamedAddress * named)709 virtual void visit(NamedAddress* named) 710 { 711 if (named->getAccess() & Address::kStruct) { 712 *fOut << "this."; 713 } 714 *fOut << named->fName; 715 } 716 }; 717 718 #endif 719