以编程方式更改Elixir代码

时间:2016-07-01 21:00:13

标签: metaprogramming elixir

我需要在mix.exs文件中加载,更改和编写代码。我希望能够加载文件,编写依赖项并编写文件。

我从:

开始
defmodule Elixir_2ndTest.Mixfile do
  use Mix.Project

  def project do
    [app: :elixir_2nd_test,
     version: "0.0.1",
     elixir: "~> 1.2",
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     description: description(),
     deps: deps]
  end

  def application do
    [applications: [:logger]]
  end

  defp deps do
    []
  end
end

我最终需要(唯一的区别在于乐趣):

defmodule Elixir_2ndTest.Mixfile do
  use Mix.Project

  def project do
    [app: :elixir_2nd_test,
     version: "0.0.1",
     elixir: "~> 1.2",
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     description: description(),
     deps: deps]
  end

  def application do
    [applications: [:logger]]
  end

  defp deps do
    [{:httpoison, "~> 0.8.3"}]
  end
end

依赖项来自不同的构建系统(我不能直接使用十六进制形成公共互联网,因此我在离线模式下使用它并删除依赖项.hex /

我知道在deps函数中插入它们需要什么样的版本以及版本是什么(在本例中为httpoison 0.8.3)。

如果我的理解是正确的,可以通过加载文件,引用,更改,取消引用来实现。

这是我到目前为止所做的事情:

{:ok, body} = File.read("mix.exs")
{:ok, ast} = Code.string_to_quoted(body)

任何关于如何改变ast并将其写回的指针都将不胜感激。

2 个答案:

答案 0 :(得分:1)

它看起来不完全相同,但您可以使用Macro.to_string将ast转换为elixir代码。

我正在使用我的库PhStTransform来修改ast并将其转换回代码。这是PhStTransform测试库中一个非常简单的例子。

test "transform quote do output" do
  data = quote do: Enum.map(1..3, fn(x) -> x*x end)
  data_transform = quote do: Enum.map(1..3, fn(y) -> y*y end)
  replace_x = fn(a, _d ) ->
    case a do
      :x -> :y
      atom -> atom
    end
  end
  potion = %{ Atom => replace_x }
  assert PhStTransform.transform(data, potion) == data_transform
end

这样做是将所有引用转换为:ast中的x为:y。你需要为PhStTransform编写药水更聪明,但我认为它应该是可能的。 PhStTransform是hex.pm.

https://hex.pm/packages/phst_transform

答案 1 :(得分:1)

我不是Elixir专家,但我知道转换源代码;看我的生物。

如果您可以访问AST作为数据结构,您可以随时编写程序代码来克服它并破解您想要的不同之处。我假设如果Elixir会给你AST,它将为你提供访问/修改程序。这是编译器101.

这通常不是编写或维护的漂亮代码。并且,这可能还不够:您经常需要的不仅仅是AST来进行认真的分析和转换。请参阅我在Life After Parsing l上的文章。可以将其视为编译器102。

第一个绊脚石是从AST重新生成文本。以下是关于如何对AST进行漂亮打印以及为什么它比看起来更难的讨论:https://stackoverflow.com/a/5834775/120163

(听起来像弗雷德魔术奇迹狗不认为Elixir提供的东西就足够了,并且正在发明他自己的扩展以使这更容易。)。