a := Node("a")
b := Node("b")
c := Node("c")
d := Node("d")
ab := Edge(a, b)
bc := Edge(b, c)
bd := Edge(b, d)
graph := Graph([a,b,c,d], [ab, bc, bd])
{noformat}
What a lot of code! Let's use some DSL magic:
{noformat}
graph := Graph<|a -> b
b -> c
b -> d|>
{noformat}
The DSL plugin for Graph just parses the code between {{<|}} and {{|>}} (which is accessed via [compiler::DslExpr.src|http://fantom.org/doc/compiler/DslExpr.html#src]) and generates appropriate object creation.
However even such a simple example is quite tricky - to allow our DSL to be used as field initializer, or default parameter value, we need to convert our DSL code to a single expression.
So, before implementing the DSL plugin itself, we need to understand how we can replace our code with a single expression. In this particular example, assuming that {{Node}} and {{Edge}} classes override {{equals}} and {{hash}} correctly, it can be done like this:
{noformat}
Graph(
["a","b","c","d"].map {
Node(it)
},
[
["a","b"],
["b", "c"],
["b", "d"]].map {
Edge(
Node(it.first),
Node(it.last)
)
}
)
{noformat}
The source code of DSL plugin can be found [here|^GraphDsl.fan].
Uh,
So I thought - nice feature, but rarely needed, also the compiler API operates on a quite low-level, so that even simple constructor invocation requires too many code.
h3. Beyond the DSL src