Groovy for Domain-specific Languages - Second Edition

(nextflipdebug2) #1
Chapter 8

[ 197 ]

Global AST transformations


Next, we will look at a global AST transformation. Unlike the local transformations
we have just encountered, which are targeted at a specific part of the Groovy code, a
global transformation is invoked for all AST nodes in the compiled code. Let's take a
look at a fully worked global AST transformation example.


A finite state machine DSL


We will be a bit brave with this transformation. In fact, the transformed AST code
for this transformation will look nothing like the original compiled code. The goal of
this AST transformation is to provide a mini DSL for defining finite state machines.
The syntax we are aiming for takes its queue from Spock and uses labels and string
literals to be part of the DSL syntax.


Let's start with a simple state machine example, a light controlled by a toggle switch.
If the light is off and the switch is pressed, the light turns on and vice versa. Let's first
of all express this in pseudo code:


state: "OFF"
state: "ON"
event: "toggle"
when: "ON"
next = "OFF"
when: "OFF"
next = "ON"

The preceding pseudo code adequately expresses the state machine for a toggle
switch. There are two states, ON and OFF, and we can respond to one event, toggle.
The interesting thing about this pseudo code is that it is also valid Groovy syntax.
It's composed of some labels (state:, event:, when:), some literal strings ("ON",
"OFF", "toggle"), and some assignments to a variable (next = "ON").


As pure Groovy the preceding code is useless. Try pasting the preceding code into
groovyConsole and see what it does. It will run without error, but the only thing it
will report is that the result is "ON", which is the evaluated result of the last line of
code (next = "ON").


Let's dissect the code a little further. Labels such as state: can be placed before any
statement in Groovy. The only real use for a label in regular Groovy is as a means of
breaking and continuing nested loops. We won't go into that here, it's a feature that
is inherited from the Java language that allows you to build clever, but very difficult-
to-debug loops. The useful thing about it, from our point of view, is that as a result
of this syntax, we can usually stick a label next to almost any statement and then
reinterpret the syntax in an AST transformation.

Free download pdf