探索 Erlang Abstract Form--生成和获取
Smerl通过修改Erlang的内部解析树,并重新编译这棵解析树实现metaprogramming。为了理解Smerl,我们首先需要理解Erlang内部解析树的生成、表达形式和获取、修改的方法。
Erlang把解析树称为Abstract Form,要获得某一个模块的AbstractForm有两种方法:
将返回Beam变量所指定的beam文件中包含的abstract_code,也就是我们需要的Abstract Form。当然,除了abstract_code以外,chunks函数还可以用来获得以下的各种调试信息:
首先,我们前面说用atom去引用将获得复合term,如果用字符串去引用,chunks函数返回二进制数据。上面的列表中,每一项你都可以用两种方法去获取(括号外和括号内)。例如可以用
另外,我们说chunks函数用来获得beam文件中的调试信息。这意味着我们必须在编译的时候使用调试选项。
Erlang的compile可以用debug_info选项:
现在,我们尝试一个最简单的模块来验证上面的理解。创建一个空的module simplest,内容如下:
首先,我们没有使用debug_info选项编译:
shell返回的结果中no_abstract_code表示simplest这个beam文件中并没有包含任何abstract code。接着我们用debug_info选项重新编译:
这一次,返回了一个复合的term,也就是我们需要的Abstract Form。
我们先探索到这里,下次,我们将详细分析Erlang Abstract Form的所有组成部分。
Erlang把解析树称为Abstract Form,要获得某一个模块的AbstractForm有两种方法:
- 从已经编译的beam文件中获取Abstract Form
- 直接解析源代码生成Abstract Form
beam_lib
提供了操作beam文件所需要的接口。Erlang的beam文件格式是 "EA IFF 1985"标准的一个变种,它把数据分为多个 chunks. Chunk数据可以是二进制或者复合的term。如果通过名字(erlang的atom)去引用chunk,那么将返回复合term,当然这是我们需要的。
beam_lib:chunks(Beam,[abstract_code])
将返回Beam变量所指定的beam文件中包含的abstract_code,也就是我们需要的Abstract Form。当然,除了abstract_code以外,chunks函数还可以用来获得以下的各种调试信息:
-
abstract_code ("Abst")
-
attributes ("Attr")
-
compile_info ("CInf")
-
exports ("ExpT")
-
labeled_exports ("ExpT")
-
imports ("ImpT")
-
indexed_imports ("ImpT")
-
locals ("LocT")
-
labeled_locals ("LocT")
-
atoms ("Atom")
首先,我们前面说用atom去引用将获得复合term,如果用字符串去引用,chunks函数返回二进制数据。上面的列表中,每一项你都可以用两种方法去获取(括号外和括号内)。例如可以用
abstract_code
这个atom去获得复合term,也可以用括号中的"Abst"去获取二进制数据。另外,我们说chunks函数用来获得beam文件中的调试信息。这意味着我们必须在编译的时候使用调试选项。
Erlang的compile可以用debug_info选项:
debug_info
- Include debug information in the form of abstract code (see The Abstract Format in ERTS User's Guide) in the compiled beam module. Tools such as Debugger, Xref and Cover require the debug information to be included.
Warning: Source code can be reconstructed from the debug information. Use encrypted debug information (see below) to prevent this.
See beam_lib(3) for details.
现在,我们尝试一个最简单的模块来验证上面的理解。创建一个空的module simplest,内容如下:
module(simplest).
%%
%% Include files
%%
%%
%% Exported Functions
%%
-export([]).
首先,我们没有使用debug_info选项编译:
erl
Erlang (BEAM) emulator version 5.5 [source] [async-threads:0]
Eshell V5.5 (abort with ^G)
1> c(simplest).
{ok,simplest}
2> beam_lib:chunks(simplest,[abstract_code]).
{ok,{simplest,[{abstract_code,no_abstract_code}]}}
3>
shell返回的结果中no_abstract_code表示simplest这个beam文件中并没有包含任何abstract code。接着我们用debug_info选项重新编译:
3> c(simplest,[debug_info]).
{ok,simplest}
4> beam_lib:chunks(simplest,[abstract_code]).
{ok,{simplest,[{abstract_code,{raw_abstract_v1,
[{attribute,1,file,{"./simplest.erl",1}},
{attribute,4,module,simplest},
{attribute,13,export,[]},
{eof,25}]}}]}}
这一次,返回了一个复合的term,也就是我们需要的Abstract Form。
我们先探索到这里,下次,我们将详细分析Erlang Abstract Form的所有组成部分。
0 Comments:
发表评论
<< Home