From af1e0396fda62efb6c0817134b419b166b110d09 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 1 Dec 2015 12:45:03 +0100 Subject: erts: Remove CDATA from The Abstract Format document --- erts/doc/src/absform.xml | 579 +++++++++++++++++++++++------------------------ 1 file changed, 288 insertions(+), 291 deletions(-) (limited to 'erts') diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml index 8584898a9d..ca06794a53 100644 --- a/erts/doc/src/absform.xml +++ b/erts/doc/src/absform.xml @@ -11,7 +11,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software @@ -19,7 +19,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - + The Abstract Format @@ -35,24 +35,24 @@

This document describes the standard representation of parse trees for Erlang programs as Erlang terms. This representation is known as the abstract format. - Functions dealing with such parse trees are + Functions dealing with such parse trees are compile:forms/[1,2] and functions in the modules - , - , - , - , - , + epp, + erl_eval, + erl_lint, + erl_pp, + erl_parse, and - . + io. They are also used as input and output for parse transforms (see the module - ).

-

We use the function to denote the mapping from an Erlang source - construct to its abstract format representation , and write - . + compile).

+

We use the function Rep to denote the mapping from an Erlang source + construct C to its abstract format representation R, and write + R = Rep(C).

-

The word below represents an integer, and denotes the +

The word LINE below represents an integer, and denotes the number of the line in the source file where the construction occurred. - Several instances of in the same construction may denote + Several instances of LINE in the same construction may denote different lines.

Since operators are not terms in their own right, when operators are mentioned below, the representation of an operator should be taken to @@ -66,24 +66,24 @@ function declarations or attributes.

If D is a module declaration consisting of the forms - , ..., , then - Rep(D) = . - If F is an attribute , then - Rep(F) = . - If F is an attribute , then - Rep(F) = . - If F is an attribute , then - Rep(F) = . - If F is an attribute , then - Rep(F) = . - If F is an attribute , then - Rep(F) = . - If F is an attribute , then - Rep(F) = . - If F is an attribute , then - Rep(F) = . - If F is an attribute , then - Rep(F) = . + 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 -behavior(Behavior), then + Rep(F) = {attribute,LINE,behavior,Behavior}. + If F is an attribute -behaviour(Behaviour), then + Rep(F) = {attribute,LINE,behaviour,Behaviour}. + 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 -export_type([Type_1/A_1, ..., Type_k/A_k]), then + Rep(F) = {attribute,LINE,export_type,[{Type_1,A_1}, ..., {Type_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)]}}. @@ -109,8 +109,8 @@ Arity, then Rep(F) = {attribute,Line,spec,{{Mod,Name,Arity},[Rep(Ft_1), ..., Rep(Ft_k)]}}. - If F is a wild attribute , then - Rep(F) = . + 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, @@ -126,11 +126,11 @@ explicit default initializer expression, as well as an optional type.

- If V is , then - Rep(V) = . - If V is , + If V is A, then + Rep(V) = {record_field,LINE,Rep(A)}. + If V is A = E, where E is an expression, then - Rep(V) = . + Rep(V) = {record_field,LINE,Rep(A),Rep(E)}. If V is A :: T, where T is a type and it does not contain undefined syntactically, then Rep(V) = @@ -163,14 +163,14 @@ same way in patterns, expressions and guards:

If L is an integer or character literal, then - Rep(L) = . + Rep(L) = {integer,LINE,L}.
If L is a float literal, then - Rep(L) = . + Rep(L) = {float,LINE,L}.
If L is a string literal consisting of the characters - , ..., , then - Rep(L) = . + C_1, ..., C_k, then + Rep(L) = {string,LINE,[C_1, ..., C_k]}.
If L is an atom literal, then - Rep(L) = . + Rep(L) = {atom,LINE,L}.

Note that negative integer and float literals do not occur as such; they are parsed as an application of the unary negation operator.

@@ -178,46 +178,46 @@
Patterns -

If is a sequence of patterns , then - Rep(Ps) = . Such sequences occur as the +

If Ps is a sequence of patterns P_1, ..., P_k, then + Rep(Ps) = [Rep(P_1), ..., Rep(P_k)]. Such sequences occur as the list of arguments to a function or fun.

Individual patterns are represented as follows:

If P is an atomic literal L, then Rep(P) = Rep(L). - If P is a compound pattern , then - Rep(P) = . - If P is a variable pattern , then - Rep(P) = , + If P is a compound pattern P_1 = P_2, then + Rep(P) = {match,LINE,Rep(P_1),Rep(P_2)}. + If P is a variable pattern V, then + Rep(P) = {var,LINE,A}, where A is an atom with a printname consisting of the same characters as - . - If P is a universal pattern , then - Rep(P) = . - If P is a tuple pattern , then - Rep(P) = . - If P is a nil pattern , then - Rep(P) = . - If P is a cons pattern , then - Rep(P) = . - If E is a binary pattern >]]>, then - Rep(E) = . + V. + If P is a universal pattern _, then + Rep(P) = {var,LINE,'_'}. + If P is a tuple pattern {P_1, ..., P_k}, then + Rep(P) = {tuple,LINE,[Rep(P_1), ..., Rep(P_k)]}. + If P is a nil pattern [], then + Rep(P) = {nil,LINE}. + If P is a cons pattern [P_h | P_t], then + Rep(P) = {cons,LINE,Rep(P_h),Rep(P_t)}. + If E is a binary pattern <<P_1:Size_1/TSL_1, ..., P_k:Size_k/TSL_k>>, then + Rep(E) = {bin,LINE,[{bin_element,LINE,Rep(P_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(P_k),Rep(Size_k),Rep(TSL_k)}]}. For Rep(TSL), see below. - An omitted is represented by . An omitted - (type specifier list) is represented by . - If P is , where is a binary operator (this - is either an occurrence of applied to a literal string or character + An omitted Size is represented by default. An omitted TSL + (type specifier list) is represented by default. + If P is P_1 Op P_2, where Op is a binary operator (this + is either an occurrence of ++ applied to a literal string or character list, or an occurrence of an expression that can be evaluated to a number at compile time), - then Rep(P) = . - If P is , where is a unary operator (this is an + then Rep(P) = {op,LINE,Op,Rep(P_1),Rep(P_2)}. + If P is Op P_0, where Op is a unary operator (this is an occurrence of an expression that can be evaluated to a number at compile - time), then Rep(P) = . - If P is a record pattern , + time), then Rep(P) = {op,LINE,Op,Rep(P_0)}. + If P is a record pattern #Name{Field_1=P_1, ..., Field_k=P_k}, then Rep(P) = - . - If P is , then - Rep(P) = . - If P is , then - Rep(P) = , + {record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(P_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(P_k)}]}. + If P is #Name.Field, then + Rep(P) = {record_index,LINE,Name,Rep(Field)}. + If P is ( P_0 ), then + Rep(P) = Rep(P_0), that is, patterns cannot be distinguished from their bodies.

Note that every pattern has the same source form as some expression, and is @@ -226,159 +226,153 @@

Expressions -

A body B is a sequence of expressions , and - Rep(B) = .

+

A body B is a sequence of expressions E_1, ..., E_k, and + Rep(B) = [Rep(E_1), ..., Rep(E_k)].

An expression E is one of the following alternatives:

- If P is an atomic literal , then - Rep(P) = Rep(L). - If E is , then - Rep(E) = . - If E is a variable , then - Rep(E) = , - where is an atom with a printname consisting of the same - characters as . - If E is a tuple skeleton , then - Rep(E) = . - If E is , then - Rep(E) = . - If E is a cons skeleton , then - Rep(E) = . - If E is a binary constructor >]]>, then - Rep(E) = . + If P is an atomic literal L, then Rep(P) = Rep(L). + If E is P = E_0, then + Rep(E) = {match,LINE,Rep(P),Rep(E_0)}. + If E is a variable V, then Rep(E) = {var,LINE,A}, + where A is an atom with a printname consisting of the same + characters as V. + If E is a tuple skeleton {E_1, ..., E_k}, then + Rep(E) = {tuple,LINE,[Rep(E_1), ..., Rep(E_k)]}. + If E is [], then + Rep(E) = {nil,LINE}. + If E is a cons skeleton [E_h | E_t], then + Rep(E) = {cons,LINE,Rep(E_h),Rep(E_t)}. + If E is a binary constructor <<V_1:Size_1/TSL_1, ..., V_k:Size_k/TSL_k>>, then Rep(E) = + {bin,LINE,[{bin_element,LINE,Rep(V_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(V_k),Rep(Size_k),Rep(TSL_k)}]}. For Rep(TSL), see below. - An omitted is represented by . An omitted - (type specifier list) is represented by . - If E is , where is a binary operator, - then Rep(E) = . - If E is , where is a unary operator, then - Rep(E) = . - If E is , then - Rep(E) = - . - If E is , then - Rep(E) = - . - If E is , then - Rep(E) = . - If E is , then - Rep(E) = . - If E is where each - is a map assoc or exact field, then Rep(E) = - . For Rep(W), see - below. - If E is where - is a map assoc or exact field, then Rep(E) = - . For - Rep(W), see below. - If E is , then - Rep(E) = . - If E is , then - Rep(E) = . - If E is , then + An omitted Size is represented by default. An omitted TSL + (type specifier list) is represented by default. + If E is E_1 Op E_2, where Op is a binary operator, + then Rep(E) = {op,LINE,Op,Rep(E_1),Rep(E_2)}. + If E is Op E_0, where Op is a unary operator, then + Rep(E) = {op,LINE,Op,Rep(E_0)}. + If E is #Name{Field_1=E_1, ..., Field_k=E_k}, + then Rep(E) = + {record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}. + If E is E_0#Name{Field_1=E_1, ..., Field_k=E_k}, then Rep(E) = - . - If E is a list comprehension , - where each is a generator or a filter, then - Rep(E) = . For Rep(W), see + {record,LINE,Rep(E_0),Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}. + If E is #Name.Field, then + Rep(E) = {record_index,LINE,Name,Rep(Field)}. + If E is E_0#Name.Field, then + Rep(E) = {record_field,LINE,Rep(E_0),Name,Rep(Field)}. + If E is #{W_1, ..., W_k} where each + W_i is a map assoc or exact field, then Rep(E) = + {map,LINE,[Rep(W_1), ..., Rep(W_k)]}. For Rep(W), see below. - If E is a binary comprehension >]]>, - where each is a generator or a filter, then - Rep(E) = . For Rep(W), see + If E is E_0#{W_1, ..., W_k} where + W_i is a map assoc or exact field, then Rep(E) = + {map,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}. + For Rep(W), see below. + If E is catch E_0, then + Rep(E) = {'catch',LINE,Rep(E_0)}. + If E is E_0(E_1, ..., E_k), then + Rep(E) = {call,LINE,Rep(E_0),[Rep(E_1), ..., Rep(E_k)]}. + If E is E_m:E_0(E_1, ..., E_k), then Rep(E) = + {call,LINE,{remote,LINE,Rep(E_m),Rep(E_0)},[Rep(E_1), ..., Rep(E_k)]}. + + If E is a list comprehension [E_0 || W_1, ..., W_k], + where each W_i is a generator or a filter, then Rep(E) = + {lc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}. For Rep(W), see below. - If E is , where is a body, then - Rep(E) = . - If E is , - where each is an if clause then - Rep(E) = - . - If E is , - where is an expression and each is a - case clause then - Rep(E) = - . - If E is , - where is a body and each is a catch clause then + If E is a binary comprehension + <<E_0 || W_1, ..., W_k>>, + where each W_i is a generator or a filter, then + Rep(E) = {bc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}. + For Rep(W), see below. + If E is begin B end, where B is a body, then + Rep(E) = {block,LINE,Rep(B)}. + If E is if Ic_1 ; ... ; Ic_k end, + where each Ic_i is an if clause then Rep(E) = + {'if',LINE,[Rep(Ic_1), ..., Rep(Ic_k)]}. + If E is case E_0 of Cc_1 ; ... ; Cc_k end, + where E_0 is an expression and each Cc_i is a + case clause then Rep(E) = + {'case',LINE,Rep(E_0),[Rep(Cc_1), ..., Rep(Cc_k)]}. + If E is try B catch Tc_1 ; ... ; Tc_k end, + where B is a body and each Tc_i is a catch clause then Rep(E) = - . - If E is , - where is a body, - each is a case clause and - each is a catch clause then + {'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],[]}. + If E is try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n end, + where B is a body, + each Cc_i is a case clause and + each Tc_j is a catch clause then Rep(E) = + {'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],[]}. + If E is try B after A end, + where B and A are bodies then Rep(E) = + {'try',LINE,Rep(B),[],[],Rep(A)}. + If E is try B of Cc_1 ; ... ; Cc_k after A end, + where B and A are a bodies and + each Cc_i is a case clause then Rep(E) = + {'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[],Rep(A)}. + If E is try B catch Tc_1 ; ... ; Tc_k after A end, + where B and A are bodies and + each Tc_i is a catch clause then Rep(E) = + {'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],Rep(A)}. + If E is try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n after A end, + where B and A are a bodies, + each Cc_i is a case clause and + each Tc_j is a catch clause then Rep(E) = - . - If E is , - where and are bodies then - Rep(E) = - . - If E is , - where and are a bodies and - each is a case clause then - Rep(E) = - . - If E is , - where and are bodies and - each is a catch clause then - Rep(E) = - . - If E is , - where and are a bodies, - each is a case clause and - each is a catch clause then - Rep(E) = - . - If E is , - where each is a case clause then - Rep(E) = - . - If E is B_t end]]>, - where each is a case clause, - is an expression and is a body, then - Rep(E) = - . - If E is , then - Rep(E) = . - If E is , then - Rep(E) = . - (Before the R15 release: Rep(E) = .) - If E is - where each is a function clause then Rep(E) = - . - If E is - where is a variable and each - is a function clause then Rep(E) = - . + {'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],Rep(A)}. + If E is receive Cc_1 ; ... ; Cc_k end, + where each Cc_i is a case clause then Rep(E) = + {'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)]}. + If E is receive Cc_1 ; ... ; Cc_k after E_0 -> B_t end, + where each Cc_i is a case clause, + E_0 is an expression and B_t is a body, then Rep(E) = + {'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)],Rep(E_0),Rep(B_t)}. + If E is fun Name / Arity, then + Rep(E) = {'fun',LINE,{function,Name,Arity}}. + If E is fun Module:Name/Arity, then Rep(E) = + {'fun',LINE,{function,Rep(Module),Rep(Name),Rep(Arity)}}. + (Before the R15 release: Rep(E) = + {'fun',LINE,{function,Module,Name,Arity}}.) + If E is fun Fc_1 ; ... ; Fc_k end + where each Fc_i is a function clause then Rep(E) = + {'fun',LINE,{clauses,[Rep(Fc_1), ..., Rep(Fc_k)]}}. + If E is fun Name Fc_1 ; ... ; Name Fc_k end + where Name is a variable and each + Fc_i is a function clause then Rep(E) = + {named_fun,LINE,Name,[Rep(Fc_1), ..., Rep(Fc_k)]}. - If E is , then + If E is ( E_0 ), then Rep(E) = Rep(E_0), that is, parenthesized expressions cannot be distinguished from their bodies.
Generators and Filters -

When W is a generator or a filter (in the body of a list or binary comprehension), then:

+

When W is a generator or a filter (in the body of a list or + binary comprehension), then:

- If W is a generator , where is a pattern and - is an expression, then - Rep(W) = . - If W is a generator , where is a pattern and - is an expression, then - Rep(W) = . - If W is a filter , which is an expression, then - Rep(W) = . + If W is a generator P <- E, where P is + a pattern and E is an expression, then + Rep(W) = {generate,LINE,Rep(P),Rep(E)}. + If W is a generator P <= E, where P is + a pattern and E is an expression, then + Rep(W) = {b_generate,LINE,Rep(P),Rep(E)}. + If W is a filter E, which is an expression, then + Rep(W) = Rep(E).
Binary Element Type Specifiers

A type specifier list TSL for a binary element is a sequence of type - specifiers . - Rep(TSL) = .

+ specifiers TS_1 - ... - TS_k. + Rep(TSL) = [Rep(TS_1), ..., Rep(TS_k)].

When TS is a type specifier for a binary element, then:

- If TS is an atom , then Rep(TS) = . - If TS is a couple where is an atom and - is an integer, then Rep(TS) = {A,Value}. + If TS is an atom A, then Rep(TS) = A. + If TS is a couple A:Value where A is an atom + and Value is an integer, then Rep(TS) = + {A,Value}.
@@ -386,13 +380,13 @@ Map Assoc and Exact Fields

When W is an assoc or exact field (in the body of a map), then:

- If W is an assoc field V]]>, where - and are both expressions, - then Rep(W) = . + If W is an assoc field K => V, where + K and V are both expressions, + then Rep(W) = {map_field_assoc,LINE,Rep(K),Rep(V)}. - If W is an exact field , where - and are both expressions, - then Rep(W) = . + If W is an exact field K := V, where + K and V are both expressions, + then Rep(W) = {map_field_exact,LINE,Rep(K),Rep(V)}.
@@ -400,92 +394,95 @@
Clauses -

There are function clauses, if clauses, case clauses +

There are function clauses, if clauses, case clauses and catch clauses.

-

A clause is one of the following alternatives:

+

A clause C is one of the following alternatives:

- If C is a function clause B]]> - where is a pattern sequence and is a body, then - Rep(C) = . - If C is a function clause B]]> - where is a pattern sequence, - is a guard sequence and is a body, then - Rep(C) = . - If C is an if clause B]]> - where is a guard sequence and is a body, then - Rep(C) = . - If C is a case clause B]]> - where is a pattern and is a body, then - Rep(C) = . - If C is a case clause B]]> - where is a pattern, - is a guard sequence and is a body, then - Rep(C) = . - If C is a catch clause B]]> - where is a pattern and is a body, then - Rep(C) = . - If C is a catch clause B]]> - where is an atomic literal or a variable pattern, - is a pattern and is a body, then - Rep(C) = . - If C is a catch clause B]]> - where is a pattern, is a guard sequence - and is a body, then - Rep(C) = . - If C is a catch clause B]]> - where is an atomic literal or a variable pattern, - is a pattern, is a guard sequence - and is a body, then - Rep(C) = . + If C is a function clause ( Ps ) -> B + where Ps is a pattern sequence and B is a body, then + Rep(C) = {clause,LINE,Rep(Ps),[],Rep(B)}. + If C is a function clause ( Ps ) when Gs -> B + where Ps is a pattern sequence, + Gs is a guard sequence and B is a body, then + Rep(C) = {clause,LINE,Rep(Ps),Rep(Gs),Rep(B)}. + If C is an if clause Gs -> B + where Gs is a guard sequence and B is a body, then + Rep(C) = {clause,LINE,[],Rep(Gs),Rep(B)}. + If C is a case clause P -> B + where P is a pattern and B is a body, then + Rep(C) = {clause,LINE,[Rep(P)],[],Rep(B)}. + If C is a case clause P when Gs -> B + where P is a pattern, + Gs is a guard sequence and B is a body, then + Rep(C) = {clause,LINE,[Rep(P)],Rep(Gs),Rep(B)}. + If C is a catch clause P -> B + where P is a pattern and B is a body, then + Rep(C) = {clause,LINE,[Rep({throw,P,_})],[],Rep(B)}. + If C is a catch clause X : P -> B + where X is an atomic literal or a variable pattern, + P is a pattern and B is a body, then + Rep(C) = {clause,LINE,[Rep({X,P,_})],[],Rep(B)}. + If C is a catch clause P when Gs -> B + where P is a pattern, Gs is a guard sequence + and B is a body, then + Rep(C) = {clause,LINE,[Rep({throw,P,_})],Rep(Gs),Rep(B)}. + If C is a catch clause X : P when Gs -> B + where X is an atomic literal or a variable pattern, + P is a pattern, Gs is a guard sequence + and B is a body, then + Rep(C) = {clause,LINE,[Rep({X,P,_})],Rep(Gs),Rep(B)}.
Guards -

A guard sequence Gs is a sequence of guards , and - Rep(Gs) = . If the guard sequence is - empty, Rep(Gs) = .

-

A guard G is a nonempty sequence of guard tests , and - Rep(G) = .

-

A guard test is one of the following alternatives:

+

A guard sequence Gs is a sequence of guards G_1; ...; G_k, and + Rep(Gs) = [Rep(G_1), ..., Rep(G_k)]. If the guard sequence is + empty, Rep(Gs) = [].

+

A guard G is a nonempty sequence of guard tests + Gt_1, ..., Gt_k, and Rep(G) = + [Rep(Gt_1), ..., Rep(Gt_k)].

+

A guard test Gt is one of the following alternatives:

If Gt is an atomic literal L, then Rep(Gt) = Rep(L). - If Gt is a variable pattern , then - Rep(Gt) = , - where A is an atom with a printname consisting of the same characters as - . - If Gt is a tuple skeleton , then - Rep(Gt) = . - If Gt is , then - Rep(Gt) = . - If Gt is a cons skeleton , then - Rep(Gt) = . - If Gt is a binary constructor >]]>, then - Rep(Gt) = . + If Gt is a variable pattern V, then + Rep(Gt) = {var,LINE,A}, where A is an atom with + a printname consisting of the same characters as V. + If Gt is a tuple skeleton {Gt_1, ..., Gt_k}, then + Rep(Gt) = {tuple,LINE,[Rep(Gt_1), ..., Rep(Gt_k)]}. + If Gt is [], then Rep(Gt) = {nil,LINE}. + If Gt is a cons skeleton [Gt_h | Gt_t], then + Rep(Gt) = {cons,LINE,Rep(Gt_h),Rep(Gt_t)}. + If Gt is a binary constructor + <<Gt_1:Size_1/TSL_1, ..., Gt_k:Size_k/TSL_k>>, then + Rep(Gt) = {bin,LINE,[{bin_element,LINE,Rep(Gt_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(Gt_k),Rep(Size_k),Rep(TSL_k)}]}. For Rep(TSL), see above. - An omitted is represented by . An omitted - (type specifier list) is represented by . - If Gt is , where - is a binary operator, then Rep(Gt) = . - If Gt is , where is a unary operator, then - Rep(Gt) = . - If Gt is , then + An omitted Size is represented by default. + An omitted TSL (type specifier list) is represented + by default. + If Gt is Gt_1 Op Gt_2, where Op + is a binary operator, then Rep(Gt) = + {op,LINE,Op,Rep(Gt_1),Rep(Gt_2)}. + If Gt is Op Gt_0, where Op is a unary operator, then + Rep(Gt) = {op,LINE,Op,Rep(Gt_0)}. + If Gt is #Name{Field_1=Gt_1, ..., Field_k=Gt_k}, then Rep(E) = - . - If Gt is , then - Rep(Gt) = . - If Gt is , then - Rep(Gt) = . - If Gt is , where is an atom, then - Rep(Gt) = . - If Gt is , where is - the atom and is an atom or an operator, then - Rep(Gt) = . - If Gt is , where is - the atom and is an atom or an operator, then - Rep(Gt) = . - If Gt is , then - Rep(Gt) = , that is, parenthesized + {record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(Gt_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(Gt_k)}]}. + If Gt is #Name.Field, then + Rep(Gt) = {record_index,LINE,Name,Rep(Field)}. + If Gt is Gt_0#Name.Field, then + Rep(Gt) = {record_field,LINE,Rep(Gt_0),Name,Rep(Field)}. + If Gt is A(Gt_1, ..., Gt_k), where A is an atom, then + Rep(Gt) = {call,LINE,Rep(A),[Rep(Gt_1), ..., Rep(Gt_k)]}. + If Gt is A_m:A(Gt_1, ..., Gt_k), where A_m is + the atom erlang and A is an atom or an operator, then + Rep(Gt) = {call,LINE,{remote,LINE,Rep(A_m),Rep(A)},[Rep(Gt_1), ..., Rep(Gt_k)]}. + If Gt is {A_m,A}(Gt_1, ..., Gt_k), where A_m is + the atom erlang and A is an atom or an operator, then + Rep(Gt) = {call,LINE,Rep({A_m,A}),[Rep(Gt_1), ..., Rep(Gt_k)]}. + + If Gt is ( Gt_0 ), then + Rep(Gt) = Rep(Gt_0), that is, parenthesized guard tests cannot be distinguished from their bodies.

Note that every guard test has the same source form as some expression, @@ -599,18 +596,18 @@

The Abstract Format After Preprocessing -

The compilation option can be given to the - compiler to have the abstract code stored in - the chunk in the BEAM file +

The compilation option debug_info can be given to the + compiler to have the abstract code stored in + the abstract_code chunk in the BEAM file (for debugging purposes).

-

In OTP R9C and later, the chunk will +

In OTP R9C and later, the abstract_code chunk will contain

-

-

where is the abstract code as described +

{raw_abstract_v1,AbstractCode}

+

where AbstractCode is the abstract code as described in this document.

In releases of OTP prior to R9C, the abstract code after some more processing was stored in the BEAM file. The first element of the - tuple would be either (R7B) or + tuple would be either abstract_v1 (R7B) or abstract_v2 (R8B).

-- cgit v1.2.3