Rename interpretor to interpreter.
[Faustine.git] / interpreter / preprocessor / faust-0.9.47mr3 / compiler / draw / sigToGraph.cpp
diff --git a/interpreter/preprocessor/faust-0.9.47mr3/compiler/draw/sigToGraph.cpp b/interpreter/preprocessor/faust-0.9.47mr3/compiler/draw/sigToGraph.cpp
new file mode 100644 (file)
index 0000000..fdbeee9
--- /dev/null
@@ -0,0 +1,295 @@
+/************************************************************************
+ ************************************************************************
+    FAUST compiler
+    Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
+    ---------------------------------------------------------------------
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ************************************************************************
+ ************************************************************************/
+
+
+
+#include <stdio.h>
+
+#include <set>
+#include <vector>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include "signals.hh"
+#include "sigtype.hh"
+#include "sigtyperules.hh"
+#include "xtended.hh"
+
+#include "sigToGraph.hh"
+#include "sigraterules.hh"
+#include "Text.hh"
+
+using namespace std;
+
+static void     recdraw(Tree sig, set<Tree>& drawn, ofstream& fout, RateInferrer* R );
+static string   commonattr(Type t);
+static string   nodeattr(Type t);
+static string   edgeattr(Type t, int rate);
+static string   sigLabel(Tree sig);
+
+
+/**
+ * Draw a list of signals as a directed graph using graphviz's dot language
+ */
+void sigToGraph (Tree L, ofstream& fout, RateInferrer* R)
+{
+    set<Tree>   alreadyDrawn;
+
+    fout << "strict digraph loopgraph {\n"
+         << "    rankdir=LR; node [fontsize=10];"
+         << endl;
+    int out = 0;
+    while (isList(L)) {
+        recdraw(hd(L), alreadyDrawn, fout, R);
+
+        fout << "OUTPUT_" << out << "[color=\"red2\" style=\"filled\" fillcolor=\"pink\"];" << endl;
+        fout << 'S' << hd(L) << " -> " << "OUTPUT_" << out++ << "[" << edgeattr(getCertifiedSigType(hd(L)), R->rate(hd(L))) << "];" << endl;
+        L = tl(L);
+    }
+
+    fout << "}" << endl;
+}
+
+
+/******************************* IMPLEMENTATION ***********************************/
+
+
+/**
+ * Draw recursively a signal
+ */
+static void recdraw(Tree sig, set<Tree>& drawn, ofstream& fout, RateInferrer* R )
+{
+    //cerr << ++TABBER << "ENTER REC DRAW OF " << sig << "$" << *sig << endl;
+    vector<Tree>    subsig;
+    int             n;
+
+    if (drawn.count(sig) == 0) {
+        // the signal has never been drawn
+        drawn.insert(sig);                  // remember it
+        if (isList(sig)) {
+            // it's a list of signals : we draw each signal of the list
+            do {
+                recdraw(hd(sig), drawn, fout, R);
+                sig = tl(sig);
+            } while (isList(sig));
+        } else {
+            // it is a regular signal
+            // first draw the node
+            fout    << 'S' << sig << "[label=\"" << sigLabel(sig) << "\""
+                    << nodeattr(getCertifiedSigType(sig)) << "];"
+                    << endl;
+
+            // then draw the subsignals if any
+            n = getSubSignals(sig, subsig);
+            if (n > 0) {
+                Tree id, body;
+                // check special recursion case, recreate a vector of subsignals instead of the
+                // list provided by getSubSignal
+                if (n==1 && isList(subsig[0])) {
+                    assert(isRec(sig,id,body));
+
+                    Tree L = subsig[0];
+                    subsig.clear();
+                    n = 0;
+                    do {
+                        subsig.push_back(hd(L));
+                        L = tl(L);
+                        n += 1;
+                    } while (isList(L));
+                }
+
+                // draw each subsignal
+                for (int i=0; i<n; i++) {
+                    recdraw(subsig[i], drawn, fout, R);
+                    if (isRec(subsig[i],id,body)) {
+                        // special case when source is a recursive group, we don't want a rate
+                        fout    << 'S' << subsig[i] << " -> " << 'S' << sig
+                                << "[style=dashed];"
+                                << endl;
+                    } else {
+                        // special case when source is a recursive group, we don't want a rate
+                        fout    << 'S' << subsig[i] << " -> " << 'S' << sig
+                                << "[" << edgeattr(getCertifiedSigType(subsig[i]), R->rate(subsig[i])) << "];"
+                                << endl;
+                    }
+                }
+            }
+        }
+    }
+    //cerr << --TABBER << "EXIT REC DRAW OF " << sig << endl;
+}
+
+
+/**
+ * Convert a signal type into attributes common to edges and nodes
+ */
+static string commonattr(Type t)
+{
+    string s;
+
+    // nature
+    if (t->nature()==kInt) {
+        s += " color=\"blue\"";
+    } else {
+        s += " color=\"red\"";
+    }
+
+    // vectorability
+    if (t->vectorability()==kVect && t->variability()==kSamp) {
+        s += " style=\"bold\"";
+    }
+
+    return s;
+}
+/**
+ * Convert a signal type into edge attributes
+ */
+    static string edgeattr(Type t, int rate)
+{
+    string      s;
+    vector<int> d;
+    Type        b = t->dimensions(d);
+
+    s = commonattr(t);
+
+    // add rate information as label at the head of the arrow
+    s += " label=\"";
+    for (int i=0; i<d.size(); i++) {
+        s += subst("[$0]", T(d[i]));
+    }
+    s += subst("x$0\" fontsize=8", T(rate));
+
+    return s;
+}
+
+
+/**
+ * Convert a signal type into node attributes
+ */
+static string nodeattr(Type t)
+{
+    string s = commonattr(t);
+
+    // variability
+    if (t->variability()==kKonst) {
+        s += " shape=\"box\"";
+    } else if (t->variability()==kBlock) {
+        s += " shape=\"hexagon\"";
+    } else if (t->variability()==kSamp) {
+        s += " shape=\"ellipse\"";
+    }
+
+    return s;
+}
+
+
+/**
+ * translate signal binary operations into strings
+ */
+static const char* binopname[]= {
+        "+", "-", "*", "/", "%",
+        "<<", ">>",
+        ">", "<", ">=", "<=", "==", "!=",
+        "&", "|", "^"
+};
+
+
+/**
+ * return the label of a signal as a string
+ */
+static string sigLabel(Tree sig)
+{
+    int         i;
+    double      r;
+    Tree        x, y, z, c, type, name, file, ff, largs, id, le, sel, var, label;
+
+    xtended*    p = (xtended*) getUserData(sig);
+
+    stringstream fout;
+
+         if (p)                                     { fout << p->name(); }
+    else if ( isSigInt(sig, &i) )                   { fout << i;       }
+    else if ( isSigReal(sig, &r) )                  { fout << r;       }
+    else if ( isSigInput(sig, &i) )                 { fout << "INPUT_" << i; }
+    else if ( isSigOutput(sig, &i, x) )             { fout << "OUTPUT_" << i; }
+
+    else if ( isSigDelay1(sig, x) )                 { fout << "mem";           }
+    else if ( isSigFixDelay(sig, x, y) )            { fout << "@";          }
+    else if ( isSigPrefix(sig, x, y) )              { fout << "prefix";                }
+    else if ( isSigIota(sig, x) )                   { fout << "iota";       }
+    else if ( isSigBinOp(sig, &i, x, y) )           { fout << binopname[i]; }
+    else if ( isSigFFun(sig, ff, largs) )                      { fout << "ffunction:" << *ff; }
+    else if ( isSigFConst(sig, type, name, file) )  { fout << *name; }
+    else if ( isSigFVar(sig, type, name, file) )    { fout << *name; }
+
+    else if ( isSigTable(sig, id, x, y) )                      { fout << "table:" << id;       }
+    else if ( isSigWRTbl(sig, id, x, y, z) )           { fout << "write:" << id;       }
+    else if ( isSigRDTbl(sig, x, y) )                          { fout << "read";       }
+
+
+
+    else if ( isSigSelect2(sig, sel, x, y) )           { fout << "select2"; }
+    else if ( isSigSelect3(sig, sel, x, y, z) )        { fout << "select3"; }
+
+    else if ( isSigGen(sig, x) )                                       { fout << "generator"; }
+
+    else if ( isProj(sig, &i, x) )                  { fout << "Proj" << i;     }
+    else if ( isRec(sig, var, le) )                 { fout << "REC " << *var; }
+
+    else if ( isSigIntCast(sig, x) )                           { fout << "int"; }
+    else if ( isSigFloatCast(sig, x) )                                 { fout << "float"; }
+#if 0
+    else if ( isSigButton(sig, label) )                        { fout << "button \"" << *label << '"'; }
+    else if ( isSigCheckbox(sig, label) )                      { fout << "checkbox \"" << *label << '"'; }
+    else if ( isSigVSlider(sig, label,c,x,y,z) )       { fout << "vslider \"" << *label << '"';  }
+    else if ( isSigHSlider(sig, label,c,x,y,z) )       { fout << "hslider \"" << *label << '"';  }
+    else if ( isSigNumEntry(sig, label,c,x,y,z) )      { fout << "nentry \"" << *label << '"';  }
+
+    else if ( isSigVBargraph(sig, label,x,y,z) )       { fout << "vbargraph \"" << *label << '"';      }
+    else if ( isSigHBargraph(sig, label,x,y,z) )       { fout << "hbargraph \"" << *label << '"';      }
+#else
+    else if ( isSigButton(sig, label) )                        { fout << "button"; }
+    else if ( isSigCheckbox(sig, label) )                      { fout << "checkbox"; }
+    else if ( isSigVSlider(sig, label,c,x,y,z) )       { fout << "vslider";  }
+    else if ( isSigHSlider(sig, label,c,x,y,z) )       { fout << "hslider";  }
+    else if ( isSigNumEntry(sig, label,c,x,y,z) )      { fout << "nentry";  }
+
+    else if ( isSigVBargraph(sig, label,x,y,z) )       { fout << "vbargraph";  }
+    else if ( isSigHBargraph(sig, label,x,y,z) )       { fout << "hbargraph";  }
+#endif
+    else if ( isSigAttach(sig, x, y) )              { fout << "attach";                }
+
+    else if ( isSigVectorize(sig, x, y) )      { fout << "vectorize";          }
+    else if ( isSigSerialize(sig, x) )         { fout << "serialize";          }
+    else if ( isSigConcat(sig, x, y) )         { fout << "#";          }
+    else if ( isSigVectorAt(sig, x, y) )       { fout << "[]";         }
+
+    else if ( isSigUpSample(sig, x, y) )       { fout << "up";         }
+    else if ( isSigDownSample(sig, x, y) )     { fout << "down";               }
+
+    else {
+        cerr << "ERROR in sigLabel(), unrecognized signal : " << *sig << endl;
+        exit(1);
+    }
+
+    return fout.str();
+}