Компилировать формы с включенными заголовочными файлами - PullRequest
4 голосов
/ 06 января 2010

Я пытаюсь скомпилировать модуль из форм с включенными заголовочными файлами. Во-первых, если у меня есть модуль в исходном файле, все работает нормально.

user.hrl

-record(user, {name :: string()}).

zed.erl

-module(zed).
-export([f/1]).
-include("user.hrl").

f(User) ->
   User#user.name.

ракушка

1> compile:file(zed, [return]). 
{ok,zed,[]}
2> rr("user.hrl").
[user]
3> zed:f(#user{name = "Zed"}).
"Zed"

Если я пытаюсь скомпилировать тот же модуль из форм, я получаю неопределенную ошибку записи. Игра с {i, Dir} и другими опциями не помогает.

ракушка

1> Forms = [{attribute,1,module,zed},
1>  {attribute,1,export,[{f,1}]},
1>  {attribute,1,include,"user.hrl"},
1>  {function,1,f,1,
1>      [{clause,1,
1>           [{var,1,'User'}], [],
1>           [{record_field,1,
1>                {var,1,'User'},
1>                user,
1>                {atom,1,name}}]}]}].
  ....
2> compile:forms(Forms, [return]).
{error,[{".",[{1,erl_lint,{undefined_record,user}}]}],[]}

Что я делаю не так?

Ответы [ 2 ]

4 голосов
/ 07 января 2010

Включаемые файлы и макросы обрабатываются epp, препроцессором erlang. Функция compile: forms / 1 предполагает, что вся предварительная обработка уже выполнена, поэтому она будет обрабатывать {attribute,1,include,...} как для него неизвестный атрибут. То же самое с макросами.

Сегодня нет способа запустить препроцессор в списке форм. Вам придется явно включить файл и выполнить обработку макросов. Также может показаться немного странным брать некоторые данные из форм, а некоторые из файлов.

0 голосов
/ 12 января 2010

Мы сделали это для проекта только для записей, но для этого требуется пара вещей:

  1. У вас должен быть загружен модуль во время выполнения, в котором есть необходимые .hrl-файлы (луч для этого модуля также должен быть доступен в пути).
  2. Модуль должен быть скомпилирован с отладочной информацией (+debug_info для компилятора или с [debug_info] в качестве аргумента опции для c/2).
  3. Вы должны вставить определения .hrl-record в свои формы самостоятельно.

Вот как это сделать:

Сначала создайте модуль, который включает .hrl-файл:

-module(my_hrl).

-include("my_hrl.hrl").

-export([records/0]).

records() ->
    {_Module, _Beam, FilePath} = code:get_object_code(?MODULE),
    {ok, {_, [{abstract_code, {_, AC}}]}} =
        beam_lib:chunks(FilePath, [abstract_code]),
    [R || {attribute, _, record, _} = R <- AC].

Это даст вам модуль, функция которого include/0 даст вам список абстрактного кода для всех записей в этом модуле (исходя из .hrl-файлов, которые там включены).

Этот способ может, конечно, использоваться и для других атрибутов, кроме атрибута записи (или даже для функций в .hrl-файлах).

Получив список атрибутов записи, вы просто добавляете их в свои формы:

Forms = [{attribute,1,module,zed},
         {attribute,1,export,[{f,1}]}]

        ++ my_hrl:records() ++

        [{function,1,f,1,
          [{clause,1,
            [{var,1,'User'}], [],
            [{record_field,1,
              {var,1,'User'},
              user,
              {atom,1,name}}]}]}].
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...