From 34e02fed50bbaa2af7b1828968b6ec02a54e98c8 Mon Sep 17 00:00:00 2001
From: Hans Bolinder
Date: Wed, 20 Jan 2016 09:54:00 +0100
Subject: erts: Improve the documentation of the abstract format
---
erts/doc/src/absform.xml | 240 ++++++++++++++++++++++++++---------------------
1 file changed, 131 insertions(+), 109 deletions(-)
(limited to 'erts/doc')
diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml
index 1c0c3e1319..3f47b3061b 100644
--- a/erts/doc/src/absform.xml
+++ b/erts/doc/src/absform.xml
@@ -4,7 +4,7 @@
- 20012015
+ 20012016
Ericsson AB. All Rights Reserved.
@@ -80,12 +80,15 @@
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 -optional_callbacks([Fun_1/A_1, ..., Fun_k/A_k]), then
+ Rep(F) = {attribute,LINE,optional_callbacks,[{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) =
+ -record(Name,{V_1, ..., V_k}),
+ where each V_i is a record field, then Rep(F) =
{attribute,LINE,record,{Name,[Rep(V_1), ..., Rep(V_k)]}}.
For Rep(V), see below.
- If F is a type declaration
@@ -173,12 +176,12 @@
Patterns
-
If Ps is a sequence of patterns P_1, ..., P_k, then
+
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 an atomic literal L, then Rep(P) = Rep(L).
- 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
@@ -211,6 +214,10 @@
{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 a map pattern #{A_1, ..., A_k}, where each
+ A_i is an association P_i_1 := P_i_2, then Rep(P) =
+ {map,LINE,[Rep(A_1), ..., Rep(A_k)]}. For Rep(A), see
+ below.
- If P is ( P_0 ), then
Rep(P) = Rep(P_0),
that is, patterns cannot be distinguished from their bodies.
@@ -221,11 +228,11 @@
Expressions
- A body B is a sequence of expressions E_1, ..., E_k, and
- Rep(B) = [Rep(E_1), ..., Rep(E_k)].
+ A body B is a nonempty 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 L, then Rep(P) = Rep(L).
+ - If E is an atomic literal L, then Rep(E) = 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},
@@ -256,14 +263,16 @@
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
+
- If E is a map creation #{A_1, ..., A_k},
+ where each A_i is an association E_i_1 => E_i_2
+ or E_i_1 := E_i_2, then Rep(E) =
+ {map,LINE,[Rep(A_1), ..., Rep(A_k)]}. For Rep(A), see
below.
- - 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 a map update E_0#{A_1, ..., A_k},
+ where each A_i is an association E_i_1 => E_i_2
+ or E_i_1 := E_i_2, then Rep(E) =
+ {map,LINE,Rep(E_0),[Rep(A_1), ..., Rep(A_k)]}.
+ For Rep(A), 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
@@ -271,15 +280,15 @@
- 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
+
- If E is a list comprehension [E_0 || Q_1, ..., Q_k],
+ where each Q_i is a qualifier, then Rep(E) =
+ {lc,LINE,Rep(E_0),[Rep(Q_1), ..., Rep(Q_k)]}. For Rep(Q), see
below.
- 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.
+ <<E_0 || Q_1, ..., Q_k>>,
+ where each Q_i is a qualifier, then
+ Rep(E) = {bc,LINE,Rep(E_0),[Rep(Q_1), ..., Rep(Q_k)]}.
+ For Rep(Q), 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,
@@ -311,7 +320,7 @@
{'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 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)],Rep(A)}.
@@ -328,10 +337,10 @@
{'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
+
- 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
+
- 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)]}.
@@ -342,46 +351,43 @@
- Generators and Filters
- When W is a generator or a filter (in the body of a list or
- binary comprehension), then:
+ Qualifiers
+ A qualifier Q is one of the following alternatives:
- - If W is a generator P <- E, where P is
+
- If Q 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
+ Rep(Q) = {generate,LINE,Rep(P),Rep(E)}.
+ - If Q 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).
+ Rep(Q) = {b_generate,LINE,Rep(P),Rep(E)}.
+ - If Q is a filter E, where E is an expression, then
+ Rep(Q) = Rep(E).
Binary Element Type Specifiers
A type specifier list TSL for a binary element is a sequence of type
- specifiers TS_1 - ... - TS_k.
+ specifiers TS_1 - ... - TS_k, and
Rep(TSL) = [Rep(TS_1), ..., Rep(TS_k)].
- When TS is a type specifier for a binary element, then:
- - 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}.
+ - If TS is a type specifier A, where A is an atom,
+ then Rep(TS) = A.
+ - If TS is a type specifier A:Value,
+ where A is an atom and Value is an integer,
+ then Rep(TS) = {A,Value}.
- Map Assoc and Exact Fields
- When W is an assoc or exact field (in the body of a map), then:
+ Associations
+ An association A is one of the following alternatives:
- - 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 A is an association K => V,
+ then Rep(A) = {map_field_assoc,LINE,Rep(K),Rep(V)}.
- - 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)}.
+
- If A is an association K := V,
+ then Rep(A) = {map_field_exact,LINE,Rep(K),Rep(V)}.
@@ -393,37 +399,37 @@
and catch clauses.
A clause C is one of the following alternatives:
- - If C is a function clause ( Ps ) -> B
+
- 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
+
- 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
+
- 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
+
- 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
+
- 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
+
- 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
+
- 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
+ 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
+
- 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
+
- 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
+ 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)}.
@@ -439,7 +445,7 @@
[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 an atomic literal L, then Rep(Gt) = Rep(L).
- 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.
@@ -467,15 +473,21 @@
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 map creation #{A_1, ..., A_k},
+ where each A_i is an association Gt_i_1 => Gt_i_2
+ or Gt_i_1 := Gt_i_2, then Rep(Gt) =
+ {map,LINE,[Rep(A_1), ..., Rep(A_k)]}. For Rep(A), see
+ above.
+ - If Gt is a map update Gt_0#{A_1, ..., A_k}, where each
+ A_i is an association Gt_i_1 => Gt_i_2
+ or Gt_i_1 := Gt_i_2, then Rep(Gt) =
+ {map,LINE,Rep(Gt_0),[Rep(A_1), ..., Rep(A_k)]}.
+ For Rep(A), see above.
- 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.
@@ -487,21 +499,20 @@
Types
- - If T is an annotated type Anno :: Type,
- where Anno is a variable and
- Type is a type, then Rep(T) =
- {ann_type,LINE,[Rep(Anno),Rep(Type)]}.
+ - If T is an annotated type A :: T_0,
+ where A is a variable, then Rep(T) =
+ {ann_type,LINE,[Rep(A),Rep(T_0)]}.
- If T is an atom or integer literal L, then Rep(T) = Rep(L).
- - If T is L Op R,
- where Op is a binary operator and L and R
- are types (this is an occurrence of an expression that can be
- evaluated to an integer at compile time), then
- Rep(T) = {op,LINE,Op,Rep(L),Rep(R)}.
- - If T is Op A, where Op is a
- unary operator and A is a type (this is an occurrence of
+
- If T is an operator type T_1 Op T_2,
+ where Op is a binary operator (this is an occurrence of
+ an expression that can be evaluated to an integer at compile
+ time), then
+ Rep(T) = {op,LINE,Op,Rep(T_1),Rep(T_2)}.
+ - If T is an operator type Op T_0, where Op is a
+ unary operator (this is an occurrence of
an expression that can be evaluated to an integer at compile time),
- then Rep(T) = {op,LINE,Op,Rep(A)}.
+ then Rep(T) = {op,LINE,Op,Rep(T_0)}.
- If T is a bitstring type <<_:M,_:_*N>>,
where M and N are singleton integer types, then Rep(T) =
{type,LINE,binary,[Rep(M),Rep(N)]}.
@@ -509,53 +520,44 @@
{type,Line,nil,[]}.
- If T is a fun type fun(), then Rep(T) =
{type,LINE,'fun',[]}.
- - If T is a fun type fun((...) -> B),
- where B is a type, then
- Rep(T) = {type,LINE,'fun',[{type,LINE,any},Rep(B)]}.
+
- If T is a fun type fun((...) -> T_0), then
+ Rep(T) = {type,LINE,'fun',[{type,LINE,any},Rep(T_0)]}.
- If T is a fun type fun(Ft), where
Ft is a function type,
- then Rep(T) = Rep(Ft).
+ then Rep(T) = Rep(Ft). For Rep(Ft), see below.
- If T is an integer range type L .. H,
where L and H are singleton integer types, then
Rep(T) = {type,LINE,range,[Rep(L),Rep(H)]}.
- If T is a map type map(), then Rep(T) =
{type,LINE,map,any}.
- - If T is a map type #{P_1, ..., P_k}, where each
- P_i is a map pair type, then Rep(T) =
- {type,LINE,map,[Rep(P_1), ..., Rep(P_k)]}.
- - If T is a map pair type K => V, where
- K and V are types, then Rep(T) =
- {type,LINE,map_field_assoc,[Rep(K),Rep(V)]}.
- - If T is a predefined (or built-in) type N(A_1, ..., A_k),
- where each A_i is a type, then Rep(T) =
- {type,LINE,N,[Rep(A_1), ..., Rep(A_k)]}.
+ - If T is a map type #{A_1, ..., A_k}, where each
+ A_i is an association type, then Rep(T) =
+ {type,LINE,map,[Rep(A_1), ..., Rep(A_k)]}.
+ For Rep(A), see below.
+ - If T is a predefined (or built-in) type N(T_1, ..., T_k),
+ then Rep(T) =
+ {type,LINE,N,[Rep(T_1), ..., Rep(T_k)]}.
- If T is a record type #Name{F_1, ..., F_k},
where each F_i is a record field type, then Rep(T) =
{type,LINE,record,[Rep(Name),Rep(F_1), ..., Rep(F_k)]}.
-
- - If T is a record field type Name :: Type,
- where Type is a type, then Rep(T) =
- {type,LINE,field_type,[Rep(Name),Rep(Type)]}.
- - If T is a remote type M:N(A_1, ..., A_k), where
- each A_i is a type, then Rep(T) =
- {remote_type,LINE,[Rep(M),Rep(N),[Rep(A_1), ..., Rep(A_k)]]}.
+ For Rep(F), see below.
+ - If T is a remote type M:N(T_1, ..., T_k), then Rep(T) =
+ {remote_type,LINE,[Rep(M),Rep(N),[Rep(T_1), ..., Rep(T_k)]]}.
- If T is a tuple type tuple(), then Rep(T) =
{type,LINE,tuple,any}.
- - If T is a tuple type {A_1, ..., A_k}, where
- each A_i is a type, then Rep(T) =
- {type,LINE,tuple,[Rep(A_1), ..., Rep(A_k)]}.
- - If T is a type union T_1 | ... | T_k,
- where each T_i is a type, then Rep(T) =
+
- If T is a tuple type {T_1, ..., T_k}, then Rep(T) =
+ {type,LINE,tuple,[Rep(T_1), ..., Rep(T_k)]}.
+ - If T is a type union T_1 | ... | T_k, then Rep(T) =
{type,LINE,union,[Rep(T_1), ..., Rep(T_k)]}.
- If T is a type variable V, then Rep(T) =
{var,LINE,A}, where A is an atom with a printname
consisting of the same characters as V. A type variable
is any variable except underscore (_).
- - If T is a user-defined type N(A_1, ..., A_k),
- where each A_i is a type, then Rep(T) =
- {user_type,LINE,N,[Rep(A_1), ..., Rep(A_k)]}.
+ - If T is a user-defined type N(T_1, ..., T_k),
+ then Rep(T) =
+ {user_type,LINE,N,[Rep(T_1), ..., Rep(T_k)]}.
- If T is ( T_0 ), then Rep(T) = Rep(T_0),
that is, parenthesized types cannot be distinguished from their
bodies.
@@ -563,15 +565,17 @@
Function Types
+ A function type Ft is one of the following alternatives:
- If Ft is a constrained function type Ft_1 when Fc,
where Ft_1 is a function type and
Fc is a function constraint, then Rep(T) =
- {type,LINE,bounded_fun,[Rep(Ft_1),Rep(Fc)]}.
- - If Ft is a function type (A_1, ..., A_n) -> B,
- where each A_i and B are types, then
- Rep(Ft) = {type,LINE,'fun',[{type,LINE,product,[Rep(A_1),
- ..., Rep(A_n)]},Rep(B)]}.
+ {type,LINE,bounded_fun,[Rep(Ft_1),Rep(Fc)]}.
+ For Rep(Fc), see below.
+ - If Ft is a function type (T_1, ..., T_n) -> T_0,
+ where each T_i is a type, then
+ Rep(Ft) = {type,LINE,'fun',[{type,LINE,product,[Rep(T_1),
+ ..., Rep(T_n)]},Rep(T_0)]}.
@@ -587,6 +591,24 @@
+
+
+ Association Types
+
+ - If A is an association type K => V, where
+ K and V are types, then Rep(A) =
+ {type,LINE,map_field_assoc,[Rep(K),Rep(V)]}.
+
+
+
+
+ Record Field Types
+
+ - If F is a record field type Name :: Type,
+ where Type is a type, then Rep(F) =
+ {type,LINE,field_type,[Rep(Name),Rep(Type)]}.
+
+