Problem with macros, DSL and var!

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

Hmm…are you setting the value of “buffer” in the right context? It’s a bit hard to tell at the moment from the code, though I could be misreading something. Maybe post a runnable sample code example?