I’m facing a weird problem that is making me nuts.
I’m trying to build a DSL like this:
amazon_query do
list "Items", "//Items/Items" do
field :asin, "./ASIN/text()", :string
field :detail_page, "./DetailPage/text()", :string
end
end
I’m following a similar example of the book Metaprogramming Elixir by @chrismccord, which makes a DSL to parse HTML tags. The example uses an AgentServer
to save State.
So my current macros are:
defmacro amazon_query(do: inner) do
quote do
{:ok, var!(buffer, __MODULE__)} = start_buffer([])
unquote(inner)
result = get_result(var!(buffer, __MODULE__))
stop_buffer(var!(buffer, __MODULE__))
result
end
end
defmacro list(name, xpath, do: inner) do
quote do
unquote(inner)
element_sigil = unquote(xpath)
element_name = unquote(name)
element =[{String.to_atom(element_name), ~x(#{element_sigil})l}]
put_buffer var!(buffer, __MODULE__), element
end
end
defmacro field(name, xpath, :string) when is_atom(name) do
quote do
element = { unquote(name), ~x(#{unquote(xpath)})s }
put_buffer(var!(buffer, __MODULE__), element) # This line raises the error
end
end
And I have this test:
test "Field and element are processed" do
query =
amazon_query do
list "Items", "//Items/Items" do
field(:asin, "./ASIN/text()", :string)
field(:detail_page, "./DetailPage/text()", :string)
end
end
assert query == []
end
And this is the error I’m receiving:
== Compilation error in file test/get_amazon_query_generator_test.exs ==
** (CompileError) test/get_amazon_query_generator_test.exs:45: expected "buffer" (context GetAmazon.Xml.QueryGeneratorTests) to expand to an existing variable or be part of a match
(elixir) expanding macro: Kernel.var!/2
test/get_amazon_query_generator_test.exs:45: GetAmazon.Xml.QueryGeneratorTests."test Field is processed"/1
(get_amazon) expanding macro: GetAmazon.Xml.QueryGenerator.field/3
test/get_amazon_query_generator_test.exs:45: GetAmazon.Xml.QueryGeneratorTests."test Field is processed"/1
(elixir) lib/code.ex:677: Code.require_file/2
(elixir) lib/kernel/parallel_compiler.ex:201: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/6
What am I doing wrong? Any help will be appreciated