Technically speaking, DSLs are presented as DSL expressions, and it's result type is defined by the anchor type, so that
Therefore, the most obvious way to use DSL expressions is instantiation of some complex objects. For example, imagine we are writing a library for graph manipulation, so we define classes like Graph, Node, and Edge. See Graphs.fan
and we need to instantiate some graphs for our tests, so we write the code like this:
What a lot of code! Let's use some DSL magic:
The DSL plugin for Graph just parses the code between <| and |> (which is accessed via compiler::DslExpr.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:
The complete source code for example above can be found here.
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.