Chain-Load: work out DSL for generating DOT scripts

...using a pre-established example as starting point

It seems that building up this kind of generator code
from a set of free functions in a secluded namespace
is the way most suitable to the nature of the C++ language
This commit is contained in:
Fischlurch 2023-11-16 01:18:56 +01:00
parent 1c392eeae3
commit 65fa16b626
4 changed files with 214 additions and 95 deletions

View file

@ -157,8 +157,8 @@ namespace test{
}
typedef PolymorphicValue<Interface, MAX_SIZ> PolyVal;
typedef std::vector<PolyVal> TestList;
using PolyVal = PolymorphicValue<Interface, MAX_SIZ>;
using TestList = std::vector<PolyVal> ;
@ -235,10 +235,10 @@ namespace test{
verifyCreation_and_Copy<PolyVal, MaximumSizedImp>();
// Special case: client objects expose extension point for copy support
typedef polyvalue::CopySupport<Interface> CopySupportAPI; // Copy support API declared as sub-interface
typedef Imp<MAX_ELM,CopySupportAPI> CopySupportingImp; // insert this sub-interface between public API and Implementation
typedef PolymorphicValue<Interface, MAX_SIZ, CopySupportAPI> OptimalPolyVal; // Make the Holder use this special attachment point
CHECK (sizeof(OptimalPolyVal) < sizeof(PolyVal)); // results in smaller Holder and less implementation overhead
using CopySupportAPI = polyvalue::CopySupport<Interface>; // Copy support API declared as sub-interface
using CopySupportingImp = Imp<MAX_ELM,CopySupportAPI>; // insert this sub-interface between public API and Implementation
using OptimalPolyVal = PolymorphicValue<Interface, MAX_SIZ, CopySupportAPI>; // Make the Holder use this special attachment point
CHECK (sizeof(OptimalPolyVal) < sizeof(PolyVal)); // results in smaller Holder and less implementation overhead
verifyCreation_and_Copy<OptimalPolyVal, CopySupportingImp>();
}
@ -248,9 +248,9 @@ namespace test{
void
verifyCreation_and_Copy()
{
typedef PV Holder;
typedef IMP ImpType;
typedef typename PV::Interface Api;
using Holder = PV;
using ImpType = IMP;
using Api = typename PV::Interface ;
long prevSum = _checkSum;
uint prevCnt = _created;
@ -260,13 +260,13 @@ namespace test{
CHECK (prevCnt+1 <= _created); // Note: usually, the compiler optimises
CHECK (prevCnt+2 >= _created); // and skips the spurious copy-operation
CHECK (sizeof(Holder) >= sizeof(ImpType));
Api& embedded = val;
CHECK (isSameObject(embedded,val));
CHECK (INSTANCEOF(ImpType, &embedded));
Api& api = val;
CHECK (isSameObject(api,val));
CHECK (INSTANCEOF(ImpType, &api));
prevCnt = _created;
Holder val2(val); // invoke copy ctor without knowing the implementation type
embedded.apiFunc();
api.apiFunc();
CHECK (val != val2); // invoking the API function had an sideeffect on the state
val = val2; // assignment of copy back to the original...
CHECK (val == val2); // cancels the side effect

View file

@ -176,13 +176,14 @@ namespace test {
CHECK (0 == graph.getSeed());
CHECK (0 == graph.getHash());
///////////////////////////////////////////////////////////////////////TODO : what follows is WIP to test the DOT graph generator....
using N = TestChainLoad<>::Node;
std::array<N,7> n;
n[1].addPred(n[0]);
n[2].addPred(n[0]);
n[3].addPred(n[1]);
n[3].addPred(n[2]);
n[4].addPred(n[1]);
n[5].addPred(n[1]);
n[6].addPred(n[3]);
n[6].addPred(n[4]);
n[6].addPred(n[5]);
@ -199,7 +200,7 @@ namespace test {
Code TOP {"shape=box, style=rounded"};
Code DEFAULT{};
auto nNr = [&](N& nn){ return size_t(&nn - &n[0]); };
auto nNr = [&](N& nn){ return size_t(&nn - &n[0]); };
for (N& nn : n)
{
size_t i = nNr(nn);
@ -210,10 +211,10 @@ namespace test {
for (N* suc : nn.succ)
topology += connect(i, nNr(*suc));
}
layers += scope(0) + Node(0) + rankMIN();
layers += scope(1) + Node(1) + Node(2);
layers += scope(2) + Node(3) + Node(4) + Node(5);
layers += scope(3) + Node(6);
layers += Scope(0).rank("min ").add(Node(0));
layers += Scope(1).rank("same").add(Node(1)).add(Node(2));
layers += Scope(2).rank("same").add(Node(3)).add(Node(4)).add(Node(5));
layers += Scope(3).rank("same").add(Node(6));
cout << digraph(nodes,layers,topology) <<endl;
}

View file

@ -82,18 +82,18 @@
//#include "lib/meta/variadic-helper.hpp"
//#include "lib/meta/function.hpp"
//#include "lib/wrapper.hpp"
//#include "lib/format-util.hpp"
//#include "lib/util.hpp"
#include "lib/format-util.hpp" /////////////////TODO used only for dot generation
#include "lib/util.hpp" /////////////////TODO used only for dot generation
#include <boost/functional/hash.hpp>
#include <functional>
#include <utility>
//#include <string>
//#include <deque>
//#include <vector>
#include <sstream>
#include <string>
#include <memory>
#include <sstream> /////////////////TODO used only for dot generation
#include <string>
#include <vector> /////////////////TODO used only for dot generation
#include <array>
@ -108,7 +108,8 @@ namespace test {
// using lib::time::FSecs;
// using lib::time::Offset;
// using lib::meta::RebindVariadic;
// using util::isnil;
using util::toString; /////////////////TODO used only for dot generation
using util::isnil; /////////////////TODO used only for dot generation
using util::max;
using util::unConst;
// using std::forward;
@ -130,6 +131,29 @@ namespace test {
namespace dot {
struct Code : string
{
using string::string;
Code(string const& c) : string{c} { }
Code(string && c) : string{move(c)}{ }
};
struct Section
{
std::vector<string> lines;
Section (string name)
: lines{"// "+name}
{ }
Section&&
operator+= (Code&& code)
{
lines.emplace_back(move (code));
return move(*this);
}
};
/**
* Helper to generate DOT-Graphviz rendering of topology
*/
@ -137,84 +161,120 @@ namespace test {
{
std::ostringstream buff_;
static uint const IDENT_STEP = 2;
public:
operator string() const { return buff_.str(); }
};
struct Code
{
Code (string code ="")
void
putLine (string line, uint indent=0)
{
if (indent)
buff_ << string(indent,' ');
buff_ << line
<< '\n';
}
Code&&
operator+= (Code&& c)
void
put (Code const& code)
{
buff_ << code;
}
Code&&
operator+ (Code&& c)
void
put (Section const& sect)
{
for (string const& line : sect.lines)
putLine (line, IDENT_STEP);
}
};
struct Section : Code
{
Section(string name)
template<class P, class...PS>
void
put (P const& part, PS const& ...parts)
{
put (part);
putLine ("");
put (parts...);
}
/** retrieve complete code generated thus far */
operator string() const
{
return buff_.str();
}
};
struct Node : Code
{
Node (size_t id)
{
}
: Code{"N"+toString(id)}
{ }
Node&&
label(size_t i)
addAttrib (string def)
{
if (back() != ']')
append ("[");
else
{
resize (length()-2);
append (", ");
}
append (def+" ]");
return move(*this);
}
Node&&
style(Code code)
label (size_t i)
{
return addAttrib ("label="+toString(i));
}
Node&&
style (Code const& code)
{
if (not isnil(code))
addAttrib (code);
return move(*this);
}
};
inline Code
scope (size_t id)
{
}
inline Code
rankMIN()
{
}
struct Scope : Code
{
Scope (size_t id)
: Code{"{ /*"+toString(id)+"*/ }"}
{ }
Scope&&
add (Code const& code)
{
resize(length()-1);
append (code+" }");
return move(*this);
}
Scope&&
rank (string rankSetting)
{
return add(Code{"rank="+rankSetting});
}
};
inline Code
connect (size_t src, size_t dest)
{
return Code{Node(src) +" -> "+ Node(dest)};
}
template<class...COD>
inline DotOut
digraph (COD ...parts)
{
DotOut script;
script.putLine (Code{"digraph {"});
script.put (parts...);
script.putLine (Code{"}"});
return script;
}
////////////////////////////////////////////
////////////////////////////////////////////
}

View file

@ -95850,6 +95850,20 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node CREATED="1700100288256" ID="ID_844700164" MODIFIED="1700100289765" TEXT="control_Topology">
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700100290904" ID="ID_1991398605" MODIFIED="1700100351351" TEXT="brauche Hilfsmittel zur Visualisierung">
<arrowlink COLOR="#62819c" DESTINATION="ID_1464042796" ENDARROW="Default" ENDINCLINATION="21;-256;" ID="Arrow_ID_596151514" STARTARROW="None" STARTINCLINATION="787;55;"/>
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1700100356900" HGAP="45" ID="ID_216360062" LINK="#ID_764096140" MODIFIED="1700100481583" TEXT="erst mal einfaches Referenz-Skript (re)-generieren" VSHIFT="-5">
<icon BUILTIN="button_ok"/>
<node CREATED="1700100394556" ID="ID_587545230" MODIFIED="1700100416123" TEXT="die entsprechende Node-Struktur fest verdrahtet aufbauen"/>
<node CREATED="1700100416777" ID="ID_1280977723" MODIFIED="1700100426249" TEXT="Code-Schema zur Generierung daran entwickeln"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700100453954" HGAP="138" ID="ID_645441127" MODIFIED="1700100479215" TEXT="auf komplexere Topologien ausweiten" VSHIFT="-12">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1699746799143" ID="ID_1824939661" MODIFIED="1699746805576" TEXT="Implementierung">
@ -95999,7 +96013,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1699971822836" ID="ID_1118263931" MODIFIED="1699971831481" TEXT="Diagnostik">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1699972014017" ID="ID_1464042796" MODIFIED="1699972021504" TEXT="Topologie sichtbar machen">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1699972014017" ID="ID_1464042796" MODIFIED="1700100343215" TEXT="Topologie sichtbar machen">
<linktarget COLOR="#62819c" DESTINATION="ID_1464042796" ENDARROW="Default" ENDINCLINATION="21;-256;" ID="Arrow_ID_596151514" SOURCE="ID_1991398605" STARTARROW="None" STARTINCLINATION="787;55;"/>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1699972026007" ID="ID_551004748" MODIFIED="1699984490886" TEXT="Idee: DOT generieren (Graphviz)">
<arrowlink COLOR="#435fb4" DESTINATION="ID_1402372766" ENDARROW="Default" ENDINCLINATION="-1358;124;" ID="Arrow_ID_1189460163" STARTARROW="None" STARTINCLINATION="-1697;146;"/>
@ -96026,8 +96041,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</li>
</ul>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1699983274744" ID="ID_1122794529" MODIFIED="1699983281544" TEXT="Darstellungsfeatures bereitstellen">
<icon BUILTIN="flag-yellow"/>
@ -96120,8 +96134,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font face="Monospaced" size="2">} </font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1699989949319" ID="ID_1160779868" MODIFIED="1699989973277" STYLE="fork" TEXT="wichtig">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1699989975909" ID="ID_1742749035" MODIFIED="1699990064728">
@ -96132,8 +96145,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font face="Monospaced"><b>rank</b></font>&#160;mu&#223; explizit in jedem Layer definiert sein
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node CREATED="1699990010639" ID="ID_701982398" MODIFIED="1699990037868" TEXT="Reihenfolge der Node-Definition aufsteigend"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1699990086867" ID="ID_390644422" MODIFIED="1699990147855" TEXT="vertr&#xe4;gt keine non-breaking-Spaces">
@ -96144,8 +96156,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
...und das zeigt sich in schwer verst&#228;ndlichem Fehlverhalten; er macht dann Nodes mehrfach...
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="clanbomber"/>
</node>
</node>
@ -96185,8 +96196,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font color="#622b1e" face="Monospaced" size="2">&#160;&#160;&#160;&#160;&#160;.end();</font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node CREATED="1699998672279" ID="ID_991942735" MODIFIED="1699998684313" TEXT="M&#xf6;glichkeit-2 : freie Funktionen">
@ -96213,8 +96223,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font color="#622b1e" face="Monospaced" size="2">&#160;&#160;&#160;&#160;&#160;&#160;term(&quot;x&quot;))))</font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node CREATED="1699998685710" ID="ID_682930244" MODIFIED="1699998710074" TEXT="M&#xf6;glichkeit-3 : Member-Funktionen">
@ -96241,8 +96250,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font color="#622b1e" face="Monospaced" size="2">&#160;&#160;&#160;&#160;&#160;&#160;dsl.term(&quot;x&quot;))))</font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
<node CREATED="1699998710994" ID="ID_59980294" MODIFIED="1699998742082" TEXT="M&#xf6;glichkeit-3b : DSL in Subklasse definieren">
@ -96290,16 +96298,17 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<font color="#622b1e" face="Monospaced" size="2">&#160;&#160;process(myContext);</font>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
</node>
</node>
<node CREATED="1700006097450" ID="ID_1104460387" MODIFIED="1700006112357" TEXT="die freien Funktionen kommmen dem Ideal am n&#xe4;chsten">
<node COLOR="#435e98" CREATED="1700006097450" ID="ID_1104460387" MODIFIED="1700100092035" TEXT="die freien Funktionen kommmen dem Ideal am n&#xe4;chsten">
<icon BUILTIN="yes"/>
<node CREATED="1700006117615" ID="ID_612462517" MODIFIED="1700006130721" TEXT="wenn nicht das Probem mit der Namespace-Verschmutzung w&#xe4;re"/>
<node CREATED="1700006318148" ID="ID_1612245200" MODIFIED="1700006346250" TEXT="using namespace dot_builder;">
<node COLOR="#435e98" CREATED="1700006318148" ID="ID_1612245200" MODIFIED="1700100086660" TEXT="using namespace dot_builder;">
<icon BUILTIN="idea"/>
<node CREATED="1700100036667" ID="ID_599996089" MODIFIED="1700100053045" TEXT="nach einiger &#xdc;berlegung &#x27f9; das ist die saubere L&#xf6;sung"/>
<node CREATED="1700100053622" ID="ID_679228415" MODIFIED="1700100077788" TEXT="und anscheinend der Ansatz, der am besten zu C++ pa&#xdf;t"/>
</node>
<node CREATED="1700006706624" ID="ID_1393063108" MODIFIED="1700006721154" TEXT="allerdings m&#xfc;ssen wir iterativ verarbeiten">
<icon BUILTIN="messagebox_warning"/>
@ -96307,6 +96316,10 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node CREATED="1700007186503" ID="ID_183574797" MODIFIED="1700007195954" TEXT="also zu einem Objekt etwas hinzuf&#xfc;gen"/>
<node CREATED="1700007202829" ID="ID_1882812619" MODIFIED="1700007214173" TEXT="oder ein sukzessives Strom-Mapping"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1700100099643" ID="ID_574030129" MODIFIED="1700100156066" TEXT="und das Thema &#xbb;Code-Baukasten&#xab; ist jetzt erst mal vertagt">
<arrowlink COLOR="#7e76c6" DESTINATION="ID_194005144" ENDARROW="Default" ENDINCLINATION="182;0;" ID="Arrow_ID_1165713806" STARTARROW="None" STARTINCLINATION="391;18;"/>
<icon BUILTIN="yes"/>
</node>
</node>
<node COLOR="#435e98" CREATED="1700008334295" ID="ID_1960936169" MODIFIED="1700008755885" TEXT="Abw&#xe4;gung: was pa&#xdf;t hier">
<arrowlink COLOR="#4085ad" DESTINATION="ID_1742063716" ENDARROW="Default" ENDINCLINATION="-293;23;" ID="Arrow_ID_1472521519" STARTARROW="None" STARTINCLINATION="13;20;"/>
@ -96334,8 +96347,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
nur <i>bodenst&#228;ndige </i>Performance....
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700008657602" ID="ID_1742063716" MODIFIED="1700008740876" TEXT="KISS + YAGNI &#x27f9; da geht&apos;s lang">
<linktarget COLOR="#4085ad" DESTINATION="ID_1742063716" ENDARROW="Default" ENDINCLINATION="-293;23;" ID="Arrow_ID_1472521519" SOURCE="ID_1960936169" STARTARROW="None" STARTINCLINATION="13;20;"/>
@ -96344,15 +96356,62 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1699983402423" ID="ID_1029913754" MODIFIED="1699983415079" TEXT="brauche also mehrere tempor&#xe4;re Akkumulatoren">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1699983437699" ID="ID_343470388" MODIFIED="1699983477322" TEXT="hierf&#xfc;r ist std::vector angemessen"/>
<node CREATED="1699983559651" ID="ID_1201642524" MODIFIED="1699983571861" TEXT="sinnvollerweise lediglich die Node* aufsammeln"/>
<node COLOR="#338800" CREATED="1699983402423" ID="ID_1029913754" MODIFIED="1700099128783" TEXT="brauche also mehrere tempor&#xe4;re Akkumulatoren">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1699983437699" ID="ID_343470388" MODIFIED="1700099130024" TEXT="hierf&#xfc;r ist std::vector angemessen">
<icon BUILTIN="yes"/>
</node>
<node COLOR="#5b280f" CREATED="1699983559651" ID="ID_1201642524" MODIFIED="1700099114581" TEXT="sinnvollerweise lediglich die Node* aufsammeln">
<icon BUILTIN="button_cancel"/>
</node>
<node COLOR="#435e98" CREATED="1700099088803" ID="ID_1519009073" MODIFIED="1700099117814" TEXT="oder besser: direkt in den Abschnitten vom generierten DOT-Skript aufsammeln">
<icon BUILTIN="idea"/>
</node>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1699983576099" ID="ID_1099057461" MODIFIED="1700100170389" TEXT="einfachen Basis-Renderer f&#xfc;r DOT anlegen (ausbauf&#xe4;hig)">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1699984818923" ID="ID_1140148647" MODIFIED="1700099172943" TEXT="Generator-Funktionen f&#xfc;r Standard-Codebausteine">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1699984825249" FOLDED="true" ID="ID_956768902" MODIFIED="1700100162397" TEXT="Funktionen f&#xfc;r verschachtelte Strukturen">
<icon BUILTIN="stop-sign"/>
<icon BUILTIN="hourglass"/>
<node CREATED="1700099196455" ID="ID_822136804" MODIFIED="1700099203136" TEXT="ja... eigentlich will ich da hin"/>
<node CREATED="1700099203747" ID="ID_1336926297" MODIFIED="1700099213863">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
...aber sage erst mal <b>YAGNI</b>
</p>
</body>
</html>
</richcontent>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1700099220184" ID="ID_98826849" MODIFIED="1700099995491" TEXT="das w&#xe4;re n&#xe4;mlich nicht trivial in C++">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1700099714957" ID="ID_506786149" MODIFIED="1700099730400" TEXT="ich br&#xe4;uchte daf&#xfc;r Polymorphismus in den Code-Bausteinen"/>
<node CREATED="1700099738665" ID="ID_1962131725" MODIFIED="1700099754847" TEXT="und das widerspricht der einfachen Value-Semantik der Kombinator-Notation"/>
<node CREATED="1700099786789" ID="ID_194005144" MODIFIED="1700100137987" TEXT="&#x201e;im Prinzip ja...&#x201c;">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...man k&#246;nnte z.B. meinen PolymorphicValue verwenden (wenn ich mich nur
nicht so f&#252;r den verworrenen Implementierungs-Code sch&#228;men m&#252;&#223;te... &#55358;&#56370;
Ticket #<b>1197</b>)
</p>
</body>
</html></richcontent>
<linktarget COLOR="#7e76c6" DESTINATION="ID_194005144" ENDARROW="Default" ENDINCLINATION="182;0;" ID="Arrow_ID_1165713806" SOURCE="ID_574030129" STARTARROW="None" STARTINCLINATION="391;18;"/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1700099246157" ID="ID_1900601354" MODIFIED="1700099274850" TEXT="besser: nur Kurznotation f&#xfc;r zeilenweise Code-Generierung">
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1699983576099" ID="ID_1099057461" MODIFIED="1699983654260" TEXT="einfachen Basis-Renderer f&#xfc;r DOT anlegen (ausbauf&#xe4;hig)">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1699984818923" ID="ID_1140148647" MODIFIED="1699984824608" TEXT="Standard-Format-Templates"/>
<node CREATED="1699984825249" ID="ID_956768902" MODIFIED="1699984874481" TEXT="Funktionen f&#xfc;r verschachtelte Strukturen"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1699983654942" ID="ID_1968810638" MODIFIED="1699983679568" TEXT="lokale Spezialisierung hiervon im Arbeits-Scope">
<icon BUILTIN="flag-yellow"/>
@ -103755,8 +103814,7 @@ class Something
<i>bottom to top</i>
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<node CREATED="1699976617314" ID="ID_323734404" MODIFIED="1699976636197" TEXT="Graph-Attribut: rankdir=&quot;BT&quot;"/>
<node CREATED="1699976833605" ID="ID_794413824" MODIFIED="1699976878627" TEXT="einzelne Pfeile umdrehen: A -&gt; B[ dir = back ]"/>
<node CREATED="1699976880510" ID="ID_501888592" MODIFIED="1699976955506" TEXT="oder im scope: { edge[dir = back] A-&gt;B C-&gt;D }"/>