1 /************************************************************************
2  ************************************************************************
3     FAUST compiler
4     Copyright (C) 2003-2018 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 _CODE_CONTAINER_H
23 #define _CODE_CONTAINER_H
24 
25 #include <string>
26 
27 #include "Text.hh"
28 #include "code_loop.hh"
29 #include "description.hh"
30 #include "dsp_factory.hh"
31 #include "export.hh"
32 #include "floats.hh"
33 #include "garbageable.hh"
34 #include "instructions.hh"
35 #include "json_instructions.hh"
36 #include "property.hh"
37 #include "sigtype.hh"
38 #include "tlib.hh"
39 
40 #ifdef WIN32
41 #pragma warning(disable : 4250)
42 #endif
43 
44 // The name of 'count' parameter
45 #define fFullCount string("count")
46 
47 #define fTableName string("table")
48 
49 class TextInstVisitor;
50 
51 class CodeContainer : public virtual Garbageable {
52    protected:
53     list<CodeContainer*> fSubContainers;
54     CodeContainer* fParentContainer;  ///< Container in which this Container is embedded, null if toplevel Container
55 
56     int fNumInputs;
57     int fNumOutputs;
58 
59     int fNumActives;   ///< number of active controls in the UI (sliders, buttons, etc.)
60     int fNumPassives;  ///< number of passive widgets in the UI (bargraphs, etc.)
61 
62     int  fSubContainerType;
63     bool fGeneratedSR;
64 
65     string fKlassName;
66 
67     // Declaration part
68     BlockInst* fExtGlobalDeclarationInstructions;
69     BlockInst* fGlobalDeclarationInstructions;
70     BlockInst* fDeclarationInstructions;
71 
72     // Init method
73     BlockInst* fInitInstructions;
74     BlockInst* fResetUserInterfaceInstructions;
75     BlockInst* fClearInstructions;
76     BlockInst* fPostInitInstructions;
77 
78     // To be used in allocate method (or constructor)
79     BlockInst* fAllocateInstructions;
80 
81     // To be used in delete method
82     BlockInst* fDestroyInstructions;
83 
84     // Static init method
85     BlockInst* fStaticInitInstructions;
86     BlockInst* fPostStaticInitInstructions;
87 
88     // Static destroy method
89     BlockInst* fStaticDestroyInstructions;
90 
91     // Compute method
92     BlockInst* fComputeBlockInstructions;      // Before DSP loop
93     BlockInst* fPostComputeBlockInstructions;  // After DSP loop
94 
95     // Additional functions generated in -fun mode
96     BlockInst* fComputeFunctions;
97 
98     // User interface
99     BlockInst* fUserInterfaceInstructions;
100 
101     set<string> fIncludeFileSet;
102     set<string> fLibrarySet;
103 
104     // DAG of loops
105     CodeLoop* fCurLoop;
106 
107     property<CodeLoop*> fLoopProperty;  ///< loops used to compute some signals
108 
109     list<string> fUICode;
110     list<string> fUIMacro;
111     list<string> fUIMacroActives;
112     list<string> fUIMacroPassives;
113 
merge(set<string> & dst,set<string> & src)114     void merge(set<string>& dst, set<string>& src)
115     {
116         for (const auto& i : src) dst.insert(i);
117     }
118 
collectIncludeFile(set<string> & S)119     void collectIncludeFile(set<string>& S)
120     {
121         for (const auto& k : fSubContainers) k->collectIncludeFile(S);
122         merge(S, fIncludeFileSet);
123     }
124 
collectLibrary(set<string> & S)125     void collectLibrary(set<string>& S)
126     {
127         for (const auto& k : fSubContainers) k->collectLibrary(S);
128         merge(S, fLibrarySet);
129     }
130 
131     void generateDAGLoopAux(CodeLoop* loop, BlockInst* loop_code, DeclareVarInst* count, int loop_num,
132                             bool omp = false);
133     void generateDAGLoopInternal(CodeLoop* loop, BlockInst* block, DeclareVarInst* count, bool omp);
134 
printHeader(ostream & dst)135     void printHeader(ostream& dst)
136     {
137         // defines the metadata we want to print as comments at the begin of in the file
138         set<Tree> selectedKeys;
139         selectedKeys.insert(tree("name"));
140         selectedKeys.insert(tree("author"));
141         selectedKeys.insert(tree("copyright"));
142         selectedKeys.insert(tree("license"));
143         selectedKeys.insert(tree("version"));
144 
145         dst << "/* ------------------------------------------------------------" << endl;
146         for (const auto& i : gGlobal->gMetaDataSet) {
147             if (selectedKeys.count(i.first)) {
148                 dst << *(i.first);
149                 const char* sep = ": ";
150                 for (const auto& j : i.second) {
151                     dst << sep << *j;
152                     sep = ", ";
153                 }
154                 dst << endl;
155             }
156         }
157 
158         dst << "Code generated with Faust " << FAUSTVERSION << " (https://faust.grame.fr)" << endl;
159         dst << "Compilation options: ";
160         stringstream options;
161         gGlobal->printCompilationOptions(options);
162         dst << options.str();
163         dst << "\n------------------------------------------------------------ */" << endl;
164     }
165 
generateSR()166     virtual void generateSR()
167     {
168         if (!fGeneratedSR) {
169             pushDeclare(InstBuilder::genDecStructVar("fSampleRate", InstBuilder::genInt32Typed()));
170         }
171         pushPreInitMethod(
172             InstBuilder::genStoreStructVar("fSampleRate", InstBuilder::genLoadFunArgsVar("sample_rate")));
173     }
174 
175     BlockInst* inlineSubcontainersFunCalls(BlockInst* block);
176 
177    public:
178     CodeContainer();
179     void initialize(int numInputs, int numOutputs);
180     virtual ~CodeContainer();
181 
182     void printMacros(ostream& fout, int n);
183 
getCurLoop()184     CodeLoop* getCurLoop() { return fCurLoop; }
185 
setParentContainers(CodeContainer * parent)186     void           setParentContainers(CodeContainer* parent) { fParentContainer = parent; }
getParentContainer()187     CodeContainer* getParentContainer() { return fParentContainer; }
getTopParentContainer()188     CodeContainer* getTopParentContainer()
189     {
190         return (fParentContainer != 0) ? fParentContainer->getTopParentContainer() : this;
191     }
192 
193     // Returns the name of the class
getFullClassName()194     string getFullClassName()
195     {
196         return (fParentContainer != 0) ? (fParentContainer->getFullClassName() + "::" + getClassName())
197                                        : getClassName();
198     }
199 
setGeneratedSR()200     void setGeneratedSR() { fGeneratedSR = true; }
201 
202     void openLoop(const string& index_name, int size = 0);
203     void openLoop(Tree recsymbol, const string& index_name, int size = 0);
204     void closeLoop(Tree sig);
205 
inputs()206     int inputs() { return fNumInputs; }
outputs()207     int outputs() { return fNumOutputs; }
208 
setInputs(int inputs)209     void setInputs(int inputs) { fNumInputs = inputs; }
setOutputs(int outputs)210     void setOutputs(int outputs) { fNumOutputs = outputs; }
211 
addSubContainer(CodeContainer * container)212     void addSubContainer(CodeContainer* container) { fSubContainers.push_back(container); }
213 
addIncludeFile(const string & str)214     void addIncludeFile(const string& str) { fIncludeFileSet.insert(str); }
addLibrary(const string & str)215     void addLibrary(const string& str) { fLibrarySet.insert(str); }
216 
217     void printLibrary(ostream& fout);
218     void printIncludeFile(ostream& fout);
219 
220     void setLoopProperty(Tree sig, CodeLoop* l);   ///< Store the loop used to compute a signal
221     bool getLoopProperty(Tree sig, CodeLoop*& l);  ///< Returns the loop used to compute a signal
222     void listAllLoopProperties(Tree sig, set<CodeLoop*>&, set<Tree>& visited);  ///< Returns all the loop used to compute a signal
223 
224     void printGraphDotFormat(ostream& fout);
225 
226     void transformDAG(DispatchVisitor* visitor);
227     void computeForwardDAG(lclgraph dag, int& loop_count, vector<int>& ready_loop);
228     void sortDeepFirstDAG(CodeLoop* l, set<CodeLoop*>& visited, list<CodeLoop*>& result);
229 
230     // Should be implemented in subclasses
generateLocalInputs(BlockInst * loop_code,const string & index)231     virtual void generateLocalInputs(BlockInst* loop_code, const string& index) { faustassert(false); }
generateLocalOutputs(BlockInst * loop_code,const string & index)232     virtual void generateLocalOutputs(BlockInst* loop_code, const string& index) { faustassert(false); }
233 
234     virtual DeclareFunInst* generateAllocate(const string& name, const string& obj, bool ismethod, bool isvirtual);
235     virtual DeclareFunInst* generateDestroy(const string& name, const string& obj, bool ismethod, bool isvirtual);
236 
237     DeclareFunInst* generateGetIO(const string& name, const string& obj, int io, bool ismethod, bool isvirtual);
238     DeclareFunInst* generateGetInputs(const string& name, const string& obj, bool ismethod, bool isvirtual);
239     DeclareFunInst* generateGetOutputs(const string& name, const string& obj, bool ismethod, bool isvirtual);
240 
241     DeclareFunInst* generateGetIORate(const string& name, const string& obj, vector<int>& io, bool ismethod,
242                                       bool isvirtual);
243 
generateClassInit(const string & name)244     virtual DeclareFunInst* generateClassInit(const string& name)
245     {
246         faustassert(false);
247         return nullptr;
248     }
249     virtual DeclareFunInst* generateInstanceClear(const string& name, const string& obj, bool ismethod, bool isvirtual);
250 
251     virtual DeclareFunInst* generateInstanceConstants(const string& name, const string& obj, bool ismethod,
252                                                       bool isvirtual);
253 
generateInstanceResetUserInterface(const string & name,const string & obj,bool ismethod,bool isvirtual)254     virtual DeclareFunInst* generateInstanceResetUserInterface(const string& name, const string& obj, bool ismethod,
255                                                                bool isvirtual)
256     {
257         faustassert(false);
258         return nullptr;
259     }
260 
261     virtual DeclareFunInst* generateComputeFun(const string& name, const string& obj, bool ismethod, bool isvirtual);
262 
generateComputeAux()263     virtual BlockInst* generateComputeAux()
264     {
265         faustassert(false);
266         return nullptr;
267     }
268 
269     virtual DeclareFunInst* generateStaticInitFun(const string& name, bool isstatic);
270     virtual DeclareFunInst* generateInstanceInitFun(const string& name, const string& obj, bool ismethod,
271                                                     bool isvirtual);
272     virtual DeclareFunInst* generateFillFun(const string& name, const string& obj, bool ismethod, bool isvirtual);
273 
274     DeclareFunInst* generateInit(const string& name, const string& obj, bool ismethod, bool isvirtual);
275     DeclareFunInst* generateInstanceInit(const string& name, const string& obj, bool ismethod, bool isvirtual);
276     DeclareFunInst* generateGetSampleRate(const string& name, const string& obj, bool ismethod, bool isvirtual);
277 
278     DeclareFunInst* generateCalloc();
279     DeclareFunInst* generateFree();
280 
281     DeclareFunInst* generateNewDsp(const string& name, int size);
282     DeclareFunInst* generateDeleteDsp(const string& name, const string& obj);
283 
284     void produceInfoFunctions(int tabs, const string& classname, const string& obj, bool ismethod, bool isvirtual,
285                               TextInstVisitor* producer);
286 
287     void generateDAGLoop(BlockInst* loop_code, DeclareVarInst* count);
288 
289     template <typename REAL>
generateMetaData(JSONUIReal<REAL> * json)290     void generateMetaData(JSONUIReal<REAL>* json)
291     {
292         // Add global metadata
293         for (const auto& i : gGlobal->gMetaDataSet) {
294             if (i.first != tree("author")) {
295                 stringstream str1, str2;
296                 str1 << *(i.first);
297                 str2 << **(i.second.begin());
298                 string res1 = str1.str();
299                 string res2 = unquote(str2.str());
300                 json->declare(res1.c_str(), res2.c_str());
301             } else {
302                 for (set<Tree>::iterator j = i.second.begin(); j != i.second.end(); j++) {
303                     if (j == i.second.begin()) {
304                         stringstream str1, str2;
305                         str1 << *(i.first);
306                         str2 << **j;
307                         string res1 = str1.str();
308                         string res2 = unquote(str2.str());
309                         json->declare(res1.c_str(), res2.c_str());
310                     } else {
311                         stringstream str2;
312                         str2 << **j;
313                         string res2 = unquote(str2.str());
314                         json->declare("contributor", res2.c_str());
315                     }
316                 }
317             }
318         }
319     }
320 
321     template <typename REAL>
generateJSONFile()322     void generateJSONFile()
323     {
324         JSONInstVisitor<REAL> json_visitor;
325         generateJSON(&json_visitor);
326         ofstream xout(subst("$0.json", gGlobal->makeDrawPath()).c_str());
327         xout << json_visitor.JSON();
328     }
329 
330     template <typename REAL>
generateJSON(JSONInstVisitor<REAL> * visitor)331     void generateJSON(JSONInstVisitor<REAL>* visitor)
332     {
333         // Prepare compilation options
334         stringstream compile_options;
335         gGlobal->printCompilationOptions(compile_options);
336 
337         // "name", "filename" found in medata
338         visitor->init("", "", fNumInputs, fNumOutputs, -1, "", "", FAUSTVERSION, compile_options.str(),
339                       gGlobal->gReader.listLibraryFiles(), gGlobal->gImportDirList, -1, std::map<std::string, int>());
340 
341         generateUserInterface(visitor);
342         generateMetaData(visitor);
343     }
344 
345     template <typename REAL>
generateJSON()346     string generateJSON()
347     {
348         JSONInstVisitor<REAL> visitor;
349         generateJSON(&visitor);
350         return visitor.JSON(true);
351     }
352 
353     /* Can be overridden by subclasses to transform the FIR before the actual code generation */
354     virtual void processFIR(void);
355 
356     virtual BlockInst* flattenFIR(void);
357 
358     // Fill code for each method
pushDeclare(StatementInst * inst)359     StatementInst* pushDeclare(StatementInst* inst)
360     {
361         fDeclarationInstructions->pushBackInst(inst);
362         // TODO : add inter-loop vectors in current loop
363         return inst;
364     }
365 
pushGlobalDeclare(StatementInst * inst)366     StatementInst* pushGlobalDeclare(StatementInst* inst)
367     {
368         fGlobalDeclarationInstructions->pushBackInst(inst);
369         return inst;
370     }
371 
pushExtGlobalDeclare(StatementInst * inst)372     StatementInst* pushExtGlobalDeclare(StatementInst* inst)
373     {
374         fExtGlobalDeclarationInstructions->pushBackInst(inst);
375         return inst;
376     }
377 
378     ValueInst* pushFunction(const string& name, Typed::VarType result, vector<Typed::VarType>& types,
379                             const list<ValueInst*>& args);
380 
generateExtGlobalDeclarations(InstVisitor * visitor)381     void generateExtGlobalDeclarations(InstVisitor* visitor)
382     {
383         if (fExtGlobalDeclarationInstructions->fCode.size() > 0) {
384             fExtGlobalDeclarationInstructions->accept(visitor);
385         }
386     }
387 
generateGlobalDeclarations(InstVisitor * visitor)388     void generateGlobalDeclarations(InstVisitor* visitor)
389     {
390         if (fGlobalDeclarationInstructions->fCode.size() > 0) {
391             fGlobalDeclarationInstructions->accept(visitor);
392         }
393     }
394 
generateDeclarations(InstVisitor * visitor)395     void generateDeclarations(InstVisitor* visitor)
396     {
397         if (fDeclarationInstructions->fCode.size() > 0) {
398             fDeclarationInstructions->accept(visitor);
399         }
400     }
401 
generateInit(InstVisitor * visitor)402     void generateInit(InstVisitor* visitor)
403     {
404         if (fInitInstructions->fCode.size() > 0) {
405             fInitInstructions->accept(visitor);
406         }
407 
408         if (fPostInitInstructions->fCode.size() > 0) {
409             fPostInitInstructions->accept(visitor);
410         }
411     }
412 
generateResetUserInterface(InstVisitor * visitor)413     void generateResetUserInterface(InstVisitor* visitor)
414     {
415         if (fResetUserInterfaceInstructions->fCode.size() > 0) {
416             fResetUserInterfaceInstructions->accept(visitor);
417         }
418     }
419 
generateClear(InstVisitor * visitor)420     void generateClear(InstVisitor* visitor)
421     {
422         if (fClearInstructions->fCode.size() > 0) {
423             fClearInstructions->accept(visitor);
424         }
425     }
426 
generateStaticInit(InstVisitor * visitor)427     void generateStaticInit(InstVisitor* visitor)
428     {
429         if (fStaticInitInstructions->fCode.size() > 0) {
430             fStaticInitInstructions->accept(visitor);
431         }
432 
433         if (fPostStaticInitInstructions->fCode.size() > 0) {
434             fPostStaticInitInstructions->accept(visitor);
435         }
436     }
437 
generateStaticDestroy(InstVisitor * visitor)438     void generateStaticDestroy(InstVisitor* visitor)
439     {
440         if (fStaticDestroyInstructions->fCode.size() > 0) {
441             fStaticDestroyInstructions->accept(visitor);
442         }
443     }
444 
generateUserInterface(InstVisitor * visitor)445     void generateUserInterface(InstVisitor* visitor)
446     {
447         if (fUserInterfaceInstructions->fCode.size() > 0) {
448             fUserInterfaceInstructions->accept(visitor);
449         }
450     }
451 
generateComputeFunctions(InstVisitor * visitor)452     void generateComputeFunctions(InstVisitor* visitor)
453     {
454         if (fComputeFunctions->fCode.size() > 0) {
455             fComputeFunctions->accept(visitor);
456         }
457     }
458 
generateComputeBlock(InstVisitor * visitor)459     void generateComputeBlock(InstVisitor* visitor)
460     {
461         if (fComputeBlockInstructions->fCode.size() > 0) {
462             fComputeBlockInstructions->accept(visitor);
463         }
464     }
465 
generatePostComputeBlock(InstVisitor * visitor)466     void generatePostComputeBlock(InstVisitor* visitor)
467     {
468         if (fPostComputeBlockInstructions->fCode.size() > 0) {
469             fPostComputeBlockInstructions->accept(visitor);
470         }
471     }
472 
generateAllocate(InstVisitor * visitor)473     void generateAllocate(InstVisitor* visitor)
474     {
475         if (fAllocateInstructions->fCode.size() > 0) {
476             fAllocateInstructions->accept(visitor);
477         }
478     }
479 
generateDestroy(InstVisitor * visitor)480     void generateDestroy(InstVisitor* visitor)
481     {
482         if (fDestroyInstructions->fCode.size() > 0) {
483             fDestroyInstructions->accept(visitor);
484         }
485     }
486 
pushInitMethod(StatementInst * inst)487     StatementInst* pushInitMethod(StatementInst* inst)
488     {
489         fInitInstructions->pushBackInst(inst);
490         return inst;
491     }
pushClearMethod(StatementInst * inst)492     StatementInst* pushClearMethod(StatementInst* inst)
493     {
494         fClearInstructions->pushBackInst(inst);
495         return inst;
496     }
pushResetUIInstructions(StatementInst * inst)497     StatementInst* pushResetUIInstructions(StatementInst* inst)
498     {
499         fResetUserInterfaceInstructions->pushBackInst(inst);
500         return inst;
501     }
pushPostInitMethod(StatementInst * inst)502     StatementInst* pushPostInitMethod(StatementInst* inst)
503     {
504         fPostInitInstructions->pushBackInst(inst);
505         return inst;
506     }
pushPreInitMethod(StatementInst * inst)507     StatementInst* pushPreInitMethod(StatementInst* inst)
508     {
509         fInitInstructions->pushFrontInst(inst);
510         return inst;
511     }
512 
pushUserInterfaceMethod(StatementInst * inst)513     StatementInst* pushUserInterfaceMethod(StatementInst* inst)
514     {
515         fUserInterfaceInstructions->pushBackInst(inst);
516         return inst;
517     }
518 
pushAllocateMethod(StatementInst * inst)519     StatementInst* pushAllocateMethod(StatementInst* inst)
520     {
521         fAllocateInstructions->pushBackInst(inst);
522         return inst;
523     }
pushDestroyMethod(StatementInst * inst)524     StatementInst* pushDestroyMethod(StatementInst* inst)
525     {
526         fDestroyInstructions->pushBackInst(inst);
527         return inst;
528     }
529 
pushStaticInitMethod(StatementInst * inst)530     StatementInst* pushStaticInitMethod(StatementInst* inst)
531     {
532         fStaticInitInstructions->pushBackInst(inst);
533         return inst;
534     }
pushStaticDestroyMethod(StatementInst * inst)535     StatementInst* pushStaticDestroyMethod(StatementInst* inst)
536     {
537         fStaticDestroyInstructions->pushBackInst(inst);
538         return inst;
539     }
pushPostStaticInitMethod(StatementInst * inst)540     StatementInst* pushPostStaticInitMethod(StatementInst* inst)
541     {
542         fPostStaticInitInstructions->pushBackInst(inst);
543         return inst;
544     }
545 
pushComputeBlockMethod(StatementInst * inst)546     StatementInst* pushComputeBlockMethod(StatementInst* inst)
547     {
548         fComputeBlockInstructions->pushBackInst(inst);
549         return inst;
550     }
pushPostComputeBlockMethod(StatementInst * inst)551     StatementInst* pushPostComputeBlockMethod(StatementInst* inst)
552     {
553         fPostComputeBlockInstructions->pushBackInst(inst);
554         return inst;
555     }
556 
pushOtherComputeMethod(StatementInst * inst)557     StatementInst* pushOtherComputeMethod(StatementInst* inst)
558     {
559         fComputeFunctions->pushBackInst(inst);
560         return inst;
561     }
562 
pushPreComputeDSPMethod(StatementInst * inst)563     StatementInst* pushPreComputeDSPMethod(StatementInst* inst) { return fCurLoop->pushPreComputeDSPMethod(inst); }
pushComputeDSPMethod(StatementInst * inst)564     StatementInst* pushComputeDSPMethod(StatementInst* inst) { return fCurLoop->pushComputeDSPMethod(inst); }
pushPostComputeDSPMethod(StatementInst * inst)565     StatementInst* pushPostComputeDSPMethod(StatementInst* inst) { return fCurLoop->pushPostComputeDSPMethod(inst); }
566 
generateSubContainers()567     void generateSubContainers()
568     {
569         for (const auto& it : fSubContainers) {
570             it->produceInternal();
571         }
572     }
573 
574     // merge declaration part
mergeSubContainers()575     void mergeSubContainers()
576     {
577         for (const auto& it : fSubContainers) {
578             // Merge the subcontainer in the main one
579             fExtGlobalDeclarationInstructions->merge(it->fExtGlobalDeclarationInstructions);
580             fGlobalDeclarationInstructions->merge(it->fGlobalDeclarationInstructions);
581             fDeclarationInstructions->merge(it->fDeclarationInstructions);
582             // Then clear it
583             it->fGlobalDeclarationInstructions->fCode.clear();
584             it->fExtGlobalDeclarationInstructions->fCode.clear();
585             it->fDeclarationInstructions->fCode.clear();
586         }
587     }
588 
getSubContainers()589     size_t getSubContainers() { return fSubContainers.size(); }
590 
getTableName()591     const string getTableName() { return fTableName; }
getClassName()592     const string getClassName() { return fKlassName; }
getFaustPowerName()593     const string getFaustPowerName() { return fKlassName + "_faustpower"; }
594 
595     // UI construction
addUIMacro(const string & str)596     void addUIMacro(const string& str) { fUIMacro.push_back(str); }
addUIMacroActives(const string & str)597     void addUIMacroActives(const string& str) { fUIMacroActives.push_back(str); }
addUIMacroPassives(const string & str)598     void addUIMacroPassives(const string& str) { fUIMacroPassives.push_back(str); }
addUICode(const string & str)599     void addUICode(const string& str) { fUICode.push_back(str); }
600 
601     virtual CodeContainer* createScalarContainer(const string& name, int sub_container_type) = 0;
602 
603     virtual void produceInternal() = 0;
604 
printHeader()605     virtual void printHeader() {}
printFloatDef()606     virtual void printFloatDef() {}
printFooter()607     virtual void printFooter() {}
produceClass()608     virtual void produceClass() {}
609 
dump(ostream * dst)610     virtual void dump(ostream* dst) {}
611 
incUIActiveCount()612     void incUIActiveCount() { fNumActives++; }
incUIPassiveCount()613     void incUIPassiveCount() { fNumPassives++; }
614 
produceFactory()615     virtual dsp_factory_base* produceFactory()
616     {
617         faustassert(false);
618         return nullptr;
619     }
620 
621     int fInt32ControlNum;  // number of 'int32' intermediate control values
622     int fRealControlNum;   // number of 'real' intermediate control values
623 };
624 
isElement(const set<CodeLoop * > & S,CodeLoop * l)625 inline bool isElement(const set<CodeLoop*>& S, CodeLoop* l)
626 {
627     return S.find(l) != S.end();
628 }
629 
630 #endif
631