I need some help with macros.
I have a directed graph that is represented by a collection of Pairs where each Pair represents an arc of the graph.
I want to perform some transformations on the graph. Each transformation function will be called on each :first of each Pair, perform some tests (querying the graph in the process), and, if none of those tests fail, will return two collections of Pairs. The first collection is of arcs that should be added to the graph, and the second of arcs to be removed.
To simplify the writing of these transformation functions, I want a macro that provides three operations:
-
check(condition): to evaluate a condition and return from the function if the condition is not met;
-
add(arc): add an arc to the first return value (arcs to be added to the graph);
-
remove(arc): add an arc to the second return value (arcs to be removed from the graph).
add and remove can be implemented as internal functions, but I don’t think check can since it needs to return from an outer context.
When I try to define the check macro within the macro that provides this DSL to the body of a transformation function though. I get an error::
using Markdown
import MacroTools
macro graphTransformerBody(bodyblock)
quote
let
addset = Set()
removeset = Set()
add(x) = push!(addset, x)
remove(x) = push!(removeset, x)
macro check(condition)
quote
#=
if ! $condition
return addset, removeset
end
=#
end
end
$bodyblock
return addset, removeset
end
end
end
show(MacroTools.prewalk(MacroTools.rmlines,
@macroexpand( @graphTransformerBody(let
@check(foobar)
add(x)
end)
)))
produces
quote
let
var"#1#addset" = Main.Set()
var"#2#removeset" = Main.Set()
var"#3#add"(var"#9#x") = begin
Main.push!(var"#1#addset", var"#9#x")
end
var"#4#remove"(var"#10#x") = begin
Main.push!(var"#2#removeset", var"#10#x")
end
macro Main.check(var"#11#condition")
$(Expr(:copyast, :($(QuoteNode(quote
#= c:\Users\Mark Nahabedian\.julia\dev\PanelCutting\src\macrotest.jl:19 =#
end)))))
end
let
var"#3#add"(Main.x)
end
return (var"#1#addset", var"#2#removeset")
end
end
as I expect.
If I uncomment the invocation of '@check` thouh, I get
the error
ERROR: LoadError: LoadError: UndefVarError: @check not defined
Any suggestions for how I can get this to wokr?
Thanks.