Erlang Abstract Form–Module聲明和Form

來源:互聯網
上載者:User

前面已經介紹了,ErlyWeb中的Smerl已經具備了和Ruby樣的元組編程,本文將會介紹實現元組編程的基本原理,在Smerl中,主要是用到了Erlang的Abstract Form來實現的,我們將具體考察Erlang Abstract Form的組成。方法很簡單,參考Eralng文檔的Abstract Form一節,用實際的例子加以驗證。

Abstract Form

Abstract Form文檔中,用函數Rep表示從Erlang原始碼C到abstract form形式R的映射。簡單地說,如果原始碼C解析成為Abstract Form R,那麼寫成R = Rep(C)。另外文檔中LINE表示原始碼的行號。下面是module聲明的描述:
    A module declaration consists of a sequence of forms that are either function declarations or attributes.
        * If D is a module declaration consisting of the forms F_1, ..., F_k, then Rep(D) = [Rep(F_1), ..., Rep(F_k)].
        * If F is an attribute -module(Mod), then Rep(F) = {attribute,LINE,module,Mod}.
        * If F is an attribute -export([Fun_1/A_1, ..., Fun_k/A_k]), then Rep(F) = {attribute,LINE,export,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}.
        * If F is an attribute -import(Mod,[Fun_1/A_1, ..., Fun_k/A_k]), then Rep(F) = {attribute,LINE,import,{Mod,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}}.
        * If F is an attribute -compile(Options), then Rep(F) = {attribute,LINE,compile,Options}.
        * If F is an attribute -file(File,Line), then Rep(F) = {attribute,LINE,file,{File,Line}}.
        * If F is a record declaration -record(Name,{V_1, ..., V_k}), then Rep(F) = {attribute,LINE,record,{Name,[Rep(V_1), ..., Rep(V_k)]}}. For Rep(V), see below.
        * If F is a wild attribute -A(T), then Rep(F) = {attribute,LINE,A,T}.
        * If F is a function declaration Name Fc_1 ; ... ; Name Fc_k, where each Fc_i is a function clause with a pattern sequence of the same length Arity, then Rep(F) = {function,LINE,Name,Arity,[Rep(Fc_1), ...,Rep(Fc_k)]}.
模組聲明由一系列Form組成,這些Form要麼是函式宣告,要麼是屬性(attribute)。

Simplest
考察我們最簡單的模組 simplest。

-module(simplest).

我們對它進行編譯,然後擷取它的abstract_code:

Eshell V5.5  (abort with ^G)
1> c(simplest,[debug_info]).
{ok,simplest}
2> beam_lib:chunks(simplest, [abstract_code]).
{ok,{simplest,[{abstract_code,{raw_abstract_v1,
                  [{attribute,1,file,{"./simplest.erl",1}},
                   {attribute,1,module,simplest},
                   {eof,1}]}}]}}

beam_lib:chunks返回的abstract_code定義如下:

    {ChunkName, DataT} =
    {abstract_code, AbstractCode}

    AbstractCode = {AbstVersion, Forms} | no_abstract_code
    AbstVersion = atom()

如果無法在beam檔案中找到abstract form,那麼將返回no_abstract_code。如果找到的話,則是一個tuple, tuple的第一項是版本,即我們上面例子中的raw_abstract_v1,tuple的第2項就是真正的form。因此,最簡單的simplest beam檔案中包含的Form如下:

  [{attribute,1,file,{"./simplest.erl",1}},
 {attribute,1,module,simplest},
 {eof,1}]

Abstract Form關於module聲明Form的第一條說:

    If D is a module declaration consisting of the forms F_1, ..., F_k, then Rep(D) = [Rep(F_1), ..., Rep(F_k)].

這可以解釋Form為什麼是一個列表。

    If F is an attribute -module(Mod), then Rep(F) = {attribute,LINE,module,Mod}.

因此,例子中Form的第2行是:

 {attribute,1,module,simplest}

還有:

    If F is an attribute -file(File,Line), then Rep(F) = {attribute,LINE,file,{File,Line}}.

這也說明了為什麼會出現:

 {attribute,1,file,{"./simplest.erl",1}}

儘管我們沒有在原始碼中編寫-file屬性,但是編譯器還是在abstract code中加入了這個屬性。

最後,由於檔案在第一行結束,因此還包含

 {eof,1}

這是在Abstract Form文檔的其中一節提到的:

    4.1.2 Representation of parse errors and end of file
    In addition to the representations of forms, the list that represents a module declaration (as returned by functions in erl_parse and epp) may contain tuples {error,E}, denoting syntactically incorrect forms, and {eof,LINE}, denoting an end of stream encountered before a complete form had been parsed.

加入一個方法
接下去,我們在simplest.erl加入一個新的函數test,並export:

-module(simplest). %1
-export([test/0]). %2
test() ->  %3
ok.   %4

重新編譯simplest,並擷取abstract code 如下:
5> c(simplest,[debug_info]).      
{ok,simplest}
6> beam_lib:chunks(simplest, [abstract_code]).
{ok,{simplest,[{abstract_code,{raw_abstract_v1,
                       [{attribute,1,file,{"./simplest.erl",1}},
                        {attribute,1,module,simplest},
                        {attribute,2,export,[{test,0}]},
                        {function,
                            3,
                            test,
                            0,
                            [{clause,3,[],[],[{atom,4|...}]}]},
                        {eof,5}]}}]}}

首先,我們看到新增加了export屬性,出現在代碼的第2行,其中包括0個參數的test這個tuple。最主要的變化是一個新的function Form:

    If F is a function declaration Name Fc_1 ; ... ; Name Fc_k, where each Fc_i is a function clause with a pattern sequence of the same length Arity, then Rep(F) = {function,LINE,Name,Arity,[Rep(Fc_1), ...,Rep(Fc_k)]}.

function的Form共有5項,第一項是function這個atom,第二項是行號,第3項是函數的名字,第4項是函數參數的個數。最後一項是一個列表,包含每個子句的Rep。

我們可以深入到function的每一個子句中去,但是探索Erlang Abstract Form的目的是為了能夠理解metaprogramming的原理。而在實際編程時,很少有人會用Form來動態產生一個新的函數。通常使用的方法是提供一個函數的原始碼,或者直接使用函數參數,關於直接對Form更詳細的操縱,我們放到後面再說

 

本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/minyskirt/archive/2009/12/11/4988531.aspx

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.