编译Elixir

时间:2018-02-05 18:23:27

标签: macros elixir dsl

我正面临一个让我疯狂的奇怪问题。

我正在尝试构建这样的DSL:

amazon_query do
  list "Items", "//Items/Items" do 
      field :asin, "./ASIN/text()", :string
      field :detail_page, "./DetailPage/text()", :string
    end
end

我正在关注Chris McCord编写的Metaprogramming Elixir一书的类似例子,它使DSL能够解析HTML标签。该示例使用AgentServer来保存状态。

所以我目前的宏是:

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

我有这个测试:

 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

这是我收到的错误:

== 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

我做错了什么?任何帮助将不胜感激

0 个答案:

没有答案