正在研究lager的源码,但是对parse_transform的机制不太了解,查了一些文档,做了下测试,就有了这篇日志。

首先我们要明确erlang中Abstract Format的概念,这个我就不重复了,大家可以直接http://erlang.org/doc/apps/erts/absform.html

根据Asf你可以具有类似lisp的s-expression那种强大的元编程能力,提供一些语法糖等等……

parse_transform 机制在我看来,就是一个的暴露出来的钩子,允许你在erlang代码编译之前,根据Asf的解析,进行注入修改等操作。

 

下面做个简单的代码修改的例子:

parse_transform_source.erl

-module(parse_transform_source).

-vsn(1).

-author(xxx).

然后进行编译,打印出当前的module的asf

然后可以知道parse_transform_source:module_info(attributes)现在为[{vsn,[1]}, {author, [xxx]}]

接下来,我们要考虑用parse_tranform机制来修改vsn和author

 

添加文件parse_transform_test.erl

-module(parse_transform_test).

-export([parse_transform/2]).

parse_transform(Forms, _Options) ->
handle_asf(Forms, []).

handle_asf([], Acc) ->
  lists:reverse(Acc);

handle_asf([{attribute, Line, vsn, _VSN} | Forms], Acc) ->
  handle_asf(Forms, [{attribute, Line, vsn, 2} | Acc]);

handle_asf([{attribute, Line, author, _Author} | Forms], Acc) ->
  handle_asf(Forms, [{attribute, Line, author, star} | Acc]);

handle_asf([HeadForm|Forms], Acc) ->
  handle_asf(Forms, [HeadForm | Acc]).

这段简单的代码表明在解析到vsn和author属性时候,覆盖成新的asf。

最后在parse_transform_source.erl的代码里加上

-compile({parse_transform, parse_transform_test}).

重新编译,运行之后,

查看parse_transform_source:module_info(attributes)得到的结果是

[{vsn,[2]}, {author, [star]}].

 

总体来说,使用方法是非常简单的,而且也很方便,但暴露出这种接口对代码安全会不会有一定影响……

 

测试代码地址:https://gitcafe.com/star/parse_transform_test

正好看看gitcafe和github比起来怎么样= =

 

 

 posted on 2012-12-11 19:00  文武双全大星星  阅读(1380)  评论(0编辑  收藏  举报