Templates
The BindingSet resulting from a successful pattern match can be used to fill in a template in order to generate new code.
Let's say we want to replace a call to append! with one to vcat. First, we write the pattern and match it with something:
julia> pattern = @pattern append!({vs}...)
Pattern:
[call]
append! :: Identifier
[~rep]
vs:::expr :: ~var
julia> bindings = syntax_match(pattern, parsestmt(SyntaxNode, "append!([1, 2, 3], 4)"))
BindingSet @ 0:0 with 1 entry:
:vs => Binding:
Name: :vs
Bound sources: [(vect 1 2 3) @ 1:9, 4 @ 1:20]
Ellipsis depth: 1
Sub-bindings:
[
BindingSet @ 0:0 with 0 entries,
BindingSet @ 0:0 with 0 entries
]Then, we write the template and expand it using the bindings obtained after matching:
julia> template = @template vcat({vs}...)
SyntaxPatternNode:
[call]
vcat :: Identifier
[~rep]
[~var]
[quote-:]
vs :: Identifier
[quote-:]
expr :: Identifier
julia> expand(template, bindings)
SyntaxNode:
[call]
vcat :: Identifier
[vect]
1 :: Integer
2 :: Integer
3 :: Integer
4 :: IntegerTemplate variables should have the same ellipsis depth as the corresponding pattern variables.
julia> expand((@template vcat({vs})), bindings)
ERROR: template variable vs has inconsistent ellipsis depth
Template variables should have the same depth as the corresponding pattern variables.
...