Is there an existing way to compare the result of applying a particular macro by comparing the result with what the macro is supposed to expand it to?
defmacro twice(what) do
quote do what || what end
end
# test:
assert_same_ast my_macro(:foo), :foo || :foo
I have to start:
defmacrop assert_similar_ast(actual, expected) do
actual = Macro.expand_once(actual, __CALLER__)
quote do
assert unquote(actual |> simplify_ast |> Macro.escape) ==
unquote(expected |> simplify_ast |> Macro.escape)
end
end
I’m confused as to why actual == expected doesn’t do what you are after? The difference would be in the metadata I suppose. But those differences might actually matter so would ignoring it give you any guarantees?
Assuming I’ve understood your requirements properly, this may help:
defmodule Mac7 do
defmacro twice(what) do
quote do
unquote(what) || unquote(what)
end
end
def prune_metadata({op, _meta, params}) do
{op, [], params}
end
def prune_metadata(other) do
other
end
end
defmodule Mac7.Test do
import Mac7
defmacro test(actual, expected) do
generated = Macro.expand_once(actual, __CALLER__)
Macro.prewalk(generated, &prune_metadata/1) == Macro.prewalk(expected, &prune_metadata/1)
end
end
The key is to use Macro.prewalk/2 to prune the metadata before comparison.