This patch attempts to solve two issues made this code hard to follow
for me.
The first issue was that a lot of what these visitors do is mutate the
AST. The visitor pattern is not particularly good for that because by
the time you have performed the dynamic type dispatch, it's too late to
go back to the parent node, and change its pointer. The previous code
dealt with that relatively elegantly, but it still meant that one had to
perform manual type checks, which is what the visitor pattern is
supposed to avoid.
The second issue was not being able to return values from the Visit
functions, which meant that one had to store function results in member
variables (a common problem with visitor patterns).
Here, I try to solve both problems by making the visitor a CRTP
template. This allows one to parameterize the visitor based on the
return type and pass function results as function results. The mutation
is fascilitated by having each Visit function take two arguments -- a
reference to the object itself (with the correct dynamic type), and a
reference to the parent's pointer to this object.
Although this wasn't my explicit goal here, the fact that we're not
using virtual dispatch anymore (not possible due to return type
templatization) allows us to make the AST nodes trivially destructible,
which is a good thing, since we were not destroying them anyway.
I actually preferred symbol for this parameter name. node is very generic. At this point, we know the node is a symbol, so using the more specific name would be more consistent.