正在研究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比起来怎么样= =