diff options
50 files changed, 1202 insertions, 711 deletions
diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml index df2553ced3..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. - + </legalnotice> <title>The Abstract Format</title> @@ -35,24 +35,24 @@ <p></p> <p>This document describes the standard representation of parse trees for Erlang programs as Erlang terms. This representation is known as the <em>abstract format</em>. - Functions dealing with such parse trees are <c><![CDATA[compile:forms/[1,2]]]></c> + Functions dealing with such parse trees are <c>compile:forms/[1,2]</c> and functions in the modules - <c><![CDATA[epp]]></c>, - <c><![CDATA[erl_eval]]></c>, - <c><![CDATA[erl_lint]]></c>, - <c><![CDATA[erl_pp]]></c>, - <c><![CDATA[erl_parse]]></c>, + <c>epp</c>, + <c>erl_eval</c>, + <c>erl_lint</c>, + <c>erl_pp</c>, + <c>erl_parse</c>, and - <c><![CDATA[io]]></c>. + <c>io</c>. They are also used as input and output for parse transforms (see the module - <c><![CDATA[compile]]></c>).</p> - <p>We use the function <c><![CDATA[Rep]]></c> to denote the mapping from an Erlang source - construct <c><![CDATA[C]]></c> to its abstract format representation <c><![CDATA[R]]></c>, and write - <c><![CDATA[R = Rep(C)]]></c>. + <c>compile</c>).</p> + <p>We use the function <c>Rep</c> to denote the mapping from an Erlang source + construct <c>C</c> to its abstract format representation <c>R</c>, and write + <c>R = Rep(C)</c>. </p> - <p>The word <c><![CDATA[LINE]]></c> below represents an integer, and denotes the + <p>The word <c>LINE</c> below represents an integer, and denotes the number of the line in the source file where the construction occurred. - Several instances of <c><![CDATA[LINE]]></c> in the same construction may denote + Several instances of <c>LINE</c> in the same construction may denote different lines.</p> <p>Since operators are not terms in their own right, when operators are mentioned below, the representation of an operator should be taken to @@ -61,233 +61,116 @@ </p> <section> - <title>Module declarations and forms</title> + <title>Module Declarations and Forms</title> <p>A module declaration consists of a sequence of forms that are either function declarations or attributes.</p> <list type="bulleted"> <item>If D is a module declaration consisting of the forms - <c><![CDATA[F_1]]></c>, ..., <c><![CDATA[F_k]]></c>, then - Rep(D) = <c><![CDATA[[Rep(F_1), ..., Rep(F_k)]]]></c>.</item> - <item>If F is an attribute <c><![CDATA[-module(Mod)]]></c>, then - Rep(F) = <c><![CDATA[{attribute,LINE,module,Mod}]]></c>.</item> - <item>If F is an attribute <c><![CDATA[-behavior(Behavior)]]></c>, then - Rep(F) = <c><![CDATA[{attribute,LINE,behavior,Behavior}]]></c>.</item> - <item>If F is an attribute <c><![CDATA[-behaviour(Behaviour)]]></c>, then - Rep(F) = <c><![CDATA[{attribute,LINE,behaviour,Behaviour}]]></c>.</item> - <item>If F is an attribute <c><![CDATA[-export([Fun_1/A_1, ..., Fun_k/A_k])]]></c>, then - Rep(F) = <c><![CDATA[{attribute,LINE,export,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}]]></c>.</item> - <item>If F is an attribute <c><![CDATA[-import(Mod,[Fun_1/A_1, ..., Fun_k/A_k])]]></c>, then - Rep(F) = <c><![CDATA[{attribute,LINE,import,{Mod,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}}]]></c>.</item> - <item>If F is an attribute <c><![CDATA[-compile(Options)]]></c>, then - Rep(F) = <c><![CDATA[{attribute,LINE,compile,Options}]]></c>.</item> - <item>If F is an attribute <c><![CDATA[-file(File,Line)]]></c>, then - Rep(F) = <c><![CDATA[{attribute,LINE,file,{File,Line}}]]></c>.</item> - <item>If F is a record declaration <c><![CDATA[-record(Name,{V_1, ..., V_k})]]></c>, then - Rep(F) = - <c><![CDATA[{attribute,LINE,record,{Name,[Rep(V_1), ..., Rep(V_k)]}}]]></c>. For Rep(V), see below.</item> - <item>If F is a type attribute (i.e. <c><![CDATA[opaque]]></c> or - <c><![CDATA[type]]></c>) - <c><![CDATA[-Attr Name(A_1, ..., A_k) :: T]]></c> where each - <c><![CDATA[A_i]]></c> is a variable, then Rep(F) = - <c><![CDATA[{attribute,LINE,Attr,{Name,Rep(T),[Rep(A_1), ..., Rep(A_k)]}}]]></c>. - For Rep(T), see below.</item> - <item>If F is a type spec (i.e. <c><![CDATA[callback]]></c> or - <c><![CDATA[spec]]></c>) - <c><![CDATA[-Attr F Tc_1; ...; Tc_k]]></c>, - where each <c><![CDATA[Tc_i]]></c> is a fun type clause with an - argument sequence of the same length <c><![CDATA[Arity]]></c>, then - Rep(F) = - <c><![CDATA[{Attr,LINE,{{F,Arity},[Rep(Tc_1), ..., Rep(Tc_k)]}}]]></c>. - For Rep(Tc_i), see below.</item> - <item>If F is a type spec (i.e. <c><![CDATA[callback]]></c> or - <c><![CDATA[spec]]></c>) - <c><![CDATA[-Attr Mod:F Tc_1; ...; Tc_k]]></c>, - where each <c><![CDATA[Tc_i]]></c> is a fun type clause with an - argument sequence of the same length <c><![CDATA[Arity]]></c>, then - Rep(F) = - <c><![CDATA[{Attr,LINE,{{Mod,F,Arity},[Rep(Tc_1), ..., Rep(Tc_k)]}}]]></c>. - For Rep(Tc_i), see below.</item> - <item>If F is a wild attribute <c><![CDATA[-A(T)]]></c>, then - Rep(F) = <c><![CDATA[{attribute,LINE,A,T}]]></c>. + <c>F_1</c>, ..., <c>F_k</c>, then + Rep(D) = <c>[Rep(F_1), ..., Rep(F_k)]</c>.</item> + <item>If F is an attribute <c>-module(Mod)</c>, then + Rep(F) = <c>{attribute,LINE,module,Mod}</c>.</item> + <item>If F is an attribute <c>-behavior(Behavior)</c>, then + Rep(F) = <c>{attribute,LINE,behavior,Behavior}</c>.</item> + <item>If F is an attribute <c>-behaviour(Behaviour)</c>, then + Rep(F) = <c>{attribute,LINE,behaviour,Behaviour}</c>.</item> + <item>If F is an attribute <c>-export([Fun_1/A_1, ..., Fun_k/A_k])</c>, then + Rep(F) = <c>{attribute,LINE,export,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}</c>.</item> + <item>If F is an attribute <c>-import(Mod,[Fun_1/A_1, ..., Fun_k/A_k])</c>, then + Rep(F) = <c>{attribute,LINE,import,{Mod,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}}</c>.</item> + <item>If F is an attribute <c>-export_type([Type_1/A_1, ..., Type_k/A_k])</c>, then + Rep(F) = <c>{attribute,LINE,export_type,[{Type_1,A_1}, ..., {Type_k,A_k}]}</c>.</item> + <item>If F is an attribute <c>-compile(Options)</c>, then + Rep(F) = <c>{attribute,LINE,compile,Options}</c>.</item> + <item>If F is an attribute <c>-file(File,Line)</c>, then + Rep(F) = <c>{attribute,LINE,file,{File,Line}}</c>.</item> + <item>If F is a record declaration + <c>-record(Name,{V_1, ..., V_k})</c>, then Rep(F) = + <c>{attribute,LINE,record,{Name,[Rep(V_1), ..., Rep(V_k)]}}</c>. + For Rep(V), see below.</item> + <item>If F is a type declaration + <c>-Type Name(V_1, ..., V_k) :: T</c>, where + <c>Type</c> is either the atom <c>type</c> or the atom <c>opaque</c>, + each <c>V_i</c> is a variable, and <c>T</c> is a type, then Rep(F) = + <c>{attribute,LINE,Type,{Name,Rep(T),[Rep(V_1), ..., Rep(V_k)]}}</c>. + </item> + <item>If F is a function specification + <c>-Spec Name Ft_1; ...; Ft_k</c>, + where <c>Spec</c> is either the atom <c>spec</c> or the atom + <c>callback</c>, and each <c>Ft_i</c> is a possibly constrained + function type with an argument sequence of the same length + <c>Arity</c>, then Rep(F) = + <c>{attribute,Line,Spec,{{Name,Arity},[Rep(Ft_1), ..., Rep(Ft_k)]}}</c>. + </item> + <item>If F is a function specification + <c>-spec Mod:Name Ft_1; ...; Ft_k</c>, + where each <c>Ft_i</c> is a possibly constrained + function type with an argument sequence of the same length + <c>Arity</c>, then Rep(F) = + <c>{attribute,Line,spec,{{Mod,Name,Arity},[Rep(Ft_1), ..., Rep(Ft_k)]}}</c>. + </item> + <item>If F is a wild attribute <c>-A(T)</c>, then + Rep(F) = <c>{attribute,LINE,A,T}</c>. <br></br></item> - <item>If F is a function declaration <c><![CDATA[Name Fc_1 ; ... ; Name Fc_k]]></c>, - where each <c><![CDATA[Fc_i]]></c> is a function clause with a - pattern sequence of the same length <c><![CDATA[Arity]]></c>, then - Rep(F) = <c><![CDATA[{function,LINE,Name,Arity,[Rep(Fc_1), ...,Rep(Fc_k)]}]]></c>.</item> + <item>If F is a function declaration + <c>Name Fc_1 ; ... ; Name Fc_k</c>, + where each <c>Fc_i</c> is a function clause with a + pattern sequence of the same length <c>Arity</c>, then + Rep(F) = <c>{function,LINE,Name,Arity,[Rep(Fc_1), ...,Rep(Fc_k)]}</c>. + </item> </list> <section> - <title>Type clauses</title> - <list type="bulleted"> - <item>If T is a fun type clause - <c><![CDATA[(A_1, ..., A_n) -> Ret]]></c>, where each - <c><![CDATA[A_i]]></c> and <c><![CDATA[Ret]]></c> are types, then - Rep(T) = - <c><![CDATA[{type,LINE,'fun',[{type,LINE,product,[Rep(A_1), ..., Rep(A_n)]},Rep(Ret)]}]]></c>. - </item> - <item>If T is a bounded fun type clause <c><![CDATA[Tc when Tg]]></c>, - where <c><![CDATA[Tc]]></c> is an unbounded fun type clause and - <c><![CDATA[Tg]]></c> is a type guard sequence, then Rep(T) = - <c><![CDATA[{type,LINE,bounded_fun,[Rep(Tc),Rep(Tg)]}]]></c>.</item> - </list> - </section> - - <section> - <title>Type guards</title> - <list type="bulleted"> - <item>If G is a constraint <c><![CDATA[F(A_1, ..., A_k)]]></c>, where - <c><![CDATA[F]]></c> is an atom and each <c><![CDATA[A_i]]></c> is a - type, then Rep(G) = - <c><![CDATA[{type,LINE,constraint,[Rep(F),[Rep(A_1), ..., Rep(A_k)]]}]]></c>. - </item> - <item>If G is a type definition <c><![CDATA[Name :: Type]]></c>, - where <c><![CDATA[Name]]></c> is a variable and - <c><![CDATA[Type]]></c> is a type, then Rep(G) = - <c><![CDATA[{type,LINE,constraint,[{atom,LINE,is_subtype},[Rep(Name),Rep(Type)]]}]]></c>.</item> - </list> - </section> - - <section> - <title>Types</title> + <title>Record Fields</title> + <p>Each field in a record declaration may have an optional + explicit default initializer expression, as well as an + optional type.</p> <list type="bulleted"> - <item>If T is a type definition <c><![CDATA[Name :: Type]]></c>, - where <c><![CDATA[Name]]></c> is a variable and - <c><![CDATA[Type]]></c> is a type, then Rep(T) = - <c><![CDATA[{ann_type,LINE,[Rep(Name),Rep(Type)]}]]></c>.</item> - <item>If T is a type union <c><![CDATA[A_1 | ... | A_k]]></c>, - where each <c><![CDATA[A_i]]></c> is a type, then Rep(T) = - <c><![CDATA[{type,LINE,union,[Rep(A_1), ..., Rep(A_k)]}]]></c>.</item> - <item>If T is a type range <c><![CDATA[L .. R]]></c>, - where <c><![CDATA[L]]></c> and <c><![CDATA[R]]></c> are types, then - Rep(T) = <c><![CDATA[{type,LINE,range,[Rep(L), Rep(R)]}]]></c>.</item> - <item>If T is a binary operation <c><![CDATA[L Op R]]></c>, - where <c><![CDATA[Op]]></c> is an arithmetic or bitwise binary operator - and <c><![CDATA[L]]></c> and <c><![CDATA[R]]></c> are types, then - Rep(T) = <c><![CDATA[{op,LINE,Op,Rep(L),Rep(R)}]]></c>.</item> - <item>If T is <c><![CDATA[Op A]]></c>, where <c><![CDATA[Op]]></c> is an - arithmetic or bitwise unary operator and <c><![CDATA[A]]></c> is a - type, then Rep(T) = <c><![CDATA[{op,LINE,Op,Rep(A)}]]></c>.</item> - <item>If T is a fun type <c><![CDATA[fun()]]></c>, then Rep(T) = - <c><![CDATA[{type,LINE,'fun',[]}]]></c>.</item> - <item>If T is a variable <c><![CDATA[V]]></c>, then Rep(T) = - <c><![CDATA[{var,LINE,A}]]></c>, where <c><![CDATA[A]]></c> is an atom - with a printname consisting of the same characters as - <c><![CDATA[V]]></c>.</item> - <item>If T is an atomic literal L and L is not a string literal, then - Rep(T) = Rep(L).</item> - <item>If T is a tuple or map type <c><![CDATA[F()]]></c> (i.e. - <c><![CDATA[tuple]]></c> or <c><![CDATA[map]]></c>), then Rep(T) = - <c><![CDATA[{type,LINE,F,any}]]></c>.</item> - <item>If T is a type <c><![CDATA[F(A_1, ..., A_k)]]></c>, where each - <c><![CDATA[A_i]]></c> is a type, then Rep(T) = - <c><![CDATA[{user_type,LINE,F,[Rep(A_1), ..., Rep(A_k)]}]]></c>.</item> - <item>If T is a remote type <c><![CDATA[M:F(A_1, ..., A_k)]]></c>, where - each <c><![CDATA[A_i]]></c> is a type and <c><![CDATA[M]]></c> and - <c><![CDATA[F]]></c>, then Rep(T) = - <c><![CDATA[{remote_type,LINE,[Rep(M),Rep(F),[Rep(A_1), ..., Rep(A_k)]]}]]></c>. + <item>If V is <c>A</c>, then + Rep(V) = <c>{record_field,LINE,Rep(A)}</c>.</item> + <item>If V is <c>A = E</c>, + where <c>E</c> is an expression, then + Rep(V) = <c>{record_field,LINE,Rep(A),Rep(E)}</c>.</item> + <item>If V is <c>A :: T</c>, where <c>T</c> is a + type and it does not contain + <c>undefined</c> syntactically, then Rep(V) = + <c>{typed_record_field,{record_field,LINE,Rep(A)},Rep(undefined | T)}</c>. </item> - <item>If T is the nil type <c><![CDATA[[]]]></c>, then Rep(T) = - <c><![CDATA[{type,LINE,nil,[]}]]></c>.</item> - <item>If T is a list type <c><![CDATA[[A]]]></c>, where - <c><![CDATA[A]]></c> is a type, then Rep(T) = - <c><![CDATA[{type,LINE,list,[Rep(A)]}]]></c>.</item> - <item>If T is a non-empty list type <c><![CDATA[[A, ...]]]></c>, where - <c><![CDATA[A]]></c> is a type, then Rep(T) = - <c><![CDATA[{type,LINE,nonempty_list,[Rep(A)]}]]></c>.</item> - <item>If T is a map type <c><![CDATA[#{P_1, ..., P_k}]]></c>, where each - <c><![CDATA[P_i]]></c> is a map pair type, then Rep(T) = - <c><![CDATA[{type,LINE,map,[Rep(P_1), ..., Rep(P_k)]}]]></c>.</item> - <item>If T is a map pair type <c><![CDATA[K => V]]></c>, where - <c><![CDATA[K]]></c> and <c><![CDATA[V]]></c> are types, - then Rep(T) = - <c><![CDATA[{type,LINE,map_field_assoc,[Rep(K),Rep(V)]}]]></c>.</item> - <item>If T is a tuple type <c><![CDATA[{A_1, ..., A_k}]]></c>, where - each <c><![CDATA[A_i]]></c> is a type, then Rep(T) = - <c><![CDATA[{type,LINE,tuple,[Rep(A_1), ..., Rep(A_k)]}]]></c>.</item> - <item>If T is a record type <c><![CDATA[#Name{}]]></c>, where - <c><![CDATA[Name]]></c> is an atom, then Rep(T) = - <c><![CDATA[{type,LINE,record,[Rep(Name)]}]]></c>.</item> - <item>If T is a record type <c><![CDATA[#Name{F_1, ..., F_k}]]></c>, - where <c><![CDATA[Name]]></c> is an atom, then Rep(T) = - <c><![CDATA[{type,LINE,record,[Rep(Name),[Rep(F_1), ..., Rep(F_k)]]}]]></c>. + <item>If V is <c>A :: T</c>, where <c>T</c> is a type, then Rep(V) = + <c>{typed_record_field,{record_field,LINE,Rep(A)},Rep(T)}</c>. + </item> + <item>If V is <c>A = E :: T</c>, where + <c>E</c> is an expression and <c>T</c> is a type, then Rep(V) = + <c>{typed_record_field,{record_field,LINE,Rep(A),Rep(E)},Rep(T)}</c>. </item> - <item>If T is a record field type <c><![CDATA[Name :: Type]]></c>, - where <c><![CDATA[Name]]></c> is an atom, then Rep(T) = - <c><![CDATA[{type,LINE,field_type,[Rep(Name),Rep(Type)]}]]></c>.</item> - <item>If T is a record field type <c><![CDATA[<<>>]]></c>, then Rep(T) = - <c><![CDATA[{type,LINE,binary,[{integer,LINE,0},{integer,LINE,0}]}]]></c>. - </item> - <item>If T is a binary type <c><![CDATA[<< _ : B >>]]></c>, where - <c><![CDATA[B]]></c> is a type, then Rep(T) = - <c><![CDATA[{type,LINE,binary,[Rep(B),{integer,LINE,0}]}]]></c>.</item> - <item>If T is a binary type <c><![CDATA[<< _ : _ * U >>]]></c>, - where <c><![CDATA[U]]></c> is a type, then Rep(T) = - <c><![CDATA[{type,LINE,binary,[{integer,LINE,0},Rep(U)]}]]></c>.</item> - <item>If T is a binary type <c><![CDATA[<< _ : B , _ : _ * U >>]]></c>, - where <c><![CDATA[B]]></c> and <c><![CDATA[U]]></c> is a type, then - Rep(T) = - <c><![CDATA[{type,LINE,binary,[Rep(B),Rep(U)]}]]></c>.</item> - - <item>If T is a fun type <c><![CDATA[fun((...) -> Ret)]]></c>, then - Rep(T) = <c><![CDATA[{type,LINE,'fun',[{type,LINE,product,[]},Rep(Ret)]}]]></c>. - </item> - <item>If T is a fun type <c><![CDATA[fun(Tc)]]></c>, where - <c><![CDATA[Tc]]></c> is an unbounded fun type clause, - then Rep(T) = <c><![CDATA[Rep(Tc)]]></c>.</item> </list> </section> <section> - <title>Record fields</title> - <p>Each field in a record declaration may have an optional - explicit default initializer expression</p> - <list type="bulleted"> - <item>If V is <c><![CDATA[A]]></c>, then - Rep(V) = <c><![CDATA[{record_field,LINE,Rep(A)}]]></c>.</item> - <item>If V is <c><![CDATA[A = E]]></c>, then - Rep(V) = <c><![CDATA[{record_field,LINE,Rep(A),Rep(E)}]]></c>.</item> - <item>If V is <c><![CDATA[A :: T]]></c>, where <c><![CDATA[A]]></c> is - an atom and <c><![CDATA[T]]></c> is a type and it does not contain - <c><![CDATA[undefined]]></c> syntactically, then Rep(V) = - <c><![CDATA[{typed_record_field,{record_field,LINE,Rep(A)},Rep(undefined | T)}]]></c>. - Note that if <![CDATA[T]]> is an annotated type, it will be wrapped in - parentheses.</item> - <item>If V is <c><![CDATA[A :: T]]></c>, where <c><![CDATA[A]]></c> is - an atom and <c><![CDATA[T]]></c> is a type, then Rep(V) = - <c><![CDATA[{typed_record_field,{record_field,LINE,Rep(A)},Rep(T)}]]></c>. - </item> - <item>If V is <c><![CDATA[A = E :: T]]></c>, where <c><![CDATA[A]]></c> - is an atom, <c><![CDATA[E]]></c> is an expression and - <c><![CDATA[T]]></c> is a type, then Rep(V) = - <c><![CDATA[{typed_record_field,{record_field,LINE,Rep(A),Rep(E)},Rep(T)}]]></c>. - </item> - </list> - </section> - - <section> - <title>Representation of parse errors and end of file</title> + <title>Representation of Parse Errors and End-of-file</title> <p>In addition to the representations of forms, the list that represents - a module declaration (as returned by functions in <c><![CDATA[erl_parse]]></c> and - <c><![CDATA[epp]]></c>) may contain tuples <c><![CDATA[{error,E}]]></c> and <c><![CDATA[{warning,W}]]></c>, denoting - syntactically incorrect forms and warnings, and <c><![CDATA[{eof,LINE}]]></c>, denoting an end - of stream encountered before a complete form had been parsed.</p> + a module declaration (as returned by functions in <c>erl_parse</c> and + <c>epp</c>) may contain tuples <c>{error,E}</c> and + <c>{warning,W}</c>, denoting syntactically incorrect forms and + warnings, and <c>{eof,LINE}</c>, denoting an end-of-stream + encountered before a complete form had been parsed.</p> </section> </section> <section> - <title>Atomic literals</title> + <title>Atomic Literals</title> <p>There are five kinds of atomic literals, which are represented in the same way in patterns, expressions and guards:</p> <list type="bulleted"> <item>If L is an integer or character literal, then - Rep(L) = <c><![CDATA[{integer,LINE,L}]]></c>.</item> + Rep(L) = <c>{integer,LINE,L}</c>.</item> <item>If L is a float literal, then - Rep(L) = <c><![CDATA[{float,LINE,L}]]></c>.</item> + Rep(L) = <c>{float,LINE,L}</c>.</item> <item>If L is a string literal consisting of the characters - <c><![CDATA[C_1]]></c>, ..., <c><![CDATA[C_k]]></c>, then - Rep(L) = <c><![CDATA[{string,LINE,[C_1, ..., C_k]}]]></c>.</item> + <c>C_1</c>, ..., <c>C_k</c>, then + Rep(L) = <c>{string,LINE,[C_1, ..., C_k]}</c>.</item> <item>If L is an atom literal, then - Rep(L) = <c><![CDATA[{atom,LINE,L}]]></c>.</item> + Rep(L) = <c>{atom,LINE,L}</c>.</item> </list> <p>Note that negative integer and float literals do not occur as such; they are parsed as an application of the unary negation operator.</p> @@ -295,47 +178,47 @@ <section> <title>Patterns</title> - <p>If <c><![CDATA[Ps]]></c> is a sequence of patterns <c><![CDATA[P_1, ..., P_k]]></c>, then - Rep(Ps) = <c><![CDATA[[Rep(P_1), ..., Rep(P_k)]]]></c>. Such sequences occur as the + <p>If <c>Ps</c> is a sequence of patterns <c>P_1, ..., P_k</c>, then + Rep(Ps) = <c>[Rep(P_1), ..., Rep(P_k)]</c>. Such sequences occur as the list of arguments to a function or fun.</p> <p>Individual patterns are represented as follows:</p> <list type="bulleted"> <item>If P is an atomic literal L, then Rep(P) = Rep(L).</item> - <item>If P is a compound pattern <c><![CDATA[P_1 = P_2]]></c>, then - Rep(P) = <c><![CDATA[{match,LINE,Rep(P_1),Rep(P_2)}]]></c>.</item> - <item>If P is a variable pattern <c><![CDATA[V]]></c>, then - Rep(P) = <c><![CDATA[{var,LINE,A}]]></c>, + <item>If P is a compound pattern <c>P_1 = P_2</c>, then + Rep(P) = <c>{match,LINE,Rep(P_1),Rep(P_2)}</c>.</item> + <item>If P is a variable pattern <c>V</c>, then + Rep(P) = <c>{var,LINE,A}</c>, where A is an atom with a printname consisting of the same characters as - <c><![CDATA[V]]></c>.</item> - <item>If P is a universal pattern <c><![CDATA[_]]></c>, then - Rep(P) = <c><![CDATA[{var,LINE,'_'}]]></c>.</item> - <item>If P is a tuple pattern <c><![CDATA[{P_1, ..., P_k}]]></c>, then - Rep(P) = <c><![CDATA[{tuple,LINE,[Rep(P_1), ..., Rep(P_k)]}]]></c>.</item> - <item>If P is a nil pattern <c><![CDATA[[]]]></c>, then - Rep(P) = <c><![CDATA[{nil,LINE}]]></c>.</item> - <item>If P is a cons pattern <c><![CDATA[[P_h | P_t]]]></c>, then - Rep(P) = <c><![CDATA[{cons,LINE,Rep(P_h),Rep(P_t)}]]></c>.</item> - <item>If E is a binary pattern <c><![CDATA[<<P_1:Size_1/TSL_1, ..., P_k:Size_k/TSL_k>>]]></c>, then - Rep(E) = <c><![CDATA[{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)}]}]]></c>. + <c>V</c>.</item> + <item>If P is a universal pattern <c>_</c>, then + Rep(P) = <c>{var,LINE,'_'}</c>.</item> + <item>If P is a tuple pattern <c>{P_1, ..., P_k}</c>, then + Rep(P) = <c>{tuple,LINE,[Rep(P_1), ..., Rep(P_k)]}</c>.</item> + <item>If P is a nil pattern <c>[]</c>, then + Rep(P) = <c>{nil,LINE}</c>.</item> + <item>If P is a cons pattern <c>[P_h | P_t]</c>, then + Rep(P) = <c>{cons,LINE,Rep(P_h),Rep(P_t)}</c>.</item> + <item>If E is a binary pattern <c><<P_1:Size_1/TSL_1, ..., P_k:Size_k/TSL_k>></c>, then + Rep(E) = <c>{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)}]}</c>. For Rep(TSL), see below. - An omitted <c><![CDATA[Size]]></c> is represented by <c><![CDATA[default]]></c>. An omitted <c><![CDATA[TSL]]></c> - (type specifier list) is represented by <c><![CDATA[default]]></c>.</item> - <item>If P is <c><![CDATA[P_1 Op P_2]]></c>, where <c><![CDATA[Op]]></c> is a binary operator (this - is either an occurrence of <c><![CDATA[++]]></c> applied to a literal string or character + An omitted <c>Size</c> is represented by <c>default</c>. An omitted <c>TSL</c> + (type specifier list) is represented by <c>default</c>.</item> + <item>If P is <c>P_1 Op P_2</c>, where <c>Op</c> is a binary operator (this + is either an occurrence of <c>++</c> 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) = <c><![CDATA[{op,LINE,Op,Rep(P_1),Rep(P_2)}]]></c>.</item> - <item>If P is <c><![CDATA[Op P_0]]></c>, where <c><![CDATA[Op]]></c> is a unary operator (this is an + then Rep(P) = <c>{op,LINE,Op,Rep(P_1),Rep(P_2)}</c>.</item> + <item>If P is <c>Op P_0</c>, where <c>Op</c> is a unary operator (this is an occurrence of an expression that can be evaluated to a number at compile - time), then Rep(P) = <c><![CDATA[{op,LINE,Op,Rep(P_0)}]]></c>.</item> - <item>If P is a record pattern <c><![CDATA[#Name{Field_1=P_1, ..., Field_k=P_k}]]></c>, + time), then Rep(P) = <c>{op,LINE,Op,Rep(P_0)}</c>.</item> + <item>If P is a record pattern <c>#Name{Field_1=P_1, ..., Field_k=P_k}</c>, then Rep(P) = - <c><![CDATA[{record,LINE,Name, [{record_field,LINE,Rep(Field_1),Rep(P_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(P_k)}]}]]></c>.</item> - <item>If P is <c><![CDATA[#Name.Field]]></c>, then - Rep(P) = <c><![CDATA[{record_index,LINE,Name,Rep(Field)}]]></c>.</item> - <item>If P is <c><![CDATA[( P_0 )]]></c>, then - Rep(P) = <c><![CDATA[Rep(P_0)]]></c>, - i.e., patterns cannot be distinguished from their bodies.</item> + <c>{record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(P_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(P_k)}]}</c>.</item> + <item>If P is <c>#Name.Field</c>, then + Rep(P) = <c>{record_index,LINE,Name,Rep(Field)}</c>.</item> + <item>If P is <c>( P_0 )</c>, then + Rep(P) = <c>Rep(P_0)</c>, + that is, patterns cannot be distinguished from their bodies.</item> </list> <p>Note that every pattern has the same source form as some expression, and is represented the same way as the corresponding expression.</p> @@ -343,180 +226,167 @@ <section> <title>Expressions</title> - <p>A body B is a sequence of expressions <c><![CDATA[E_1, ..., E_k]]></c>, and - Rep(B) = <c><![CDATA[[Rep(E_1), ..., Rep(E_k)]]]></c>.</p> + <p>A body B is a sequence of expressions <c>E_1, ..., E_k</c>, and + Rep(B) = <c>[Rep(E_1), ..., Rep(E_k)]</c>.</p> <p>An expression E is one of the following alternatives:</p> <list type="bulleted"> - <item>If P is an atomic literal <c><![CDATA[L]]></c>, then - Rep(P) = Rep(L).</item> - <item>If E is <c><![CDATA[P = E_0]]></c>, then - Rep(E) = <c><![CDATA[{match,LINE,Rep(P),Rep(E_0)}]]></c>.</item> - <item>If E is a variable <c><![CDATA[V]]></c>, then - Rep(E) = <c><![CDATA[{var,LINE,A}]]></c>, - where <c><![CDATA[A]]></c> is an atom with a printname consisting of the same - characters as <c><![CDATA[V]]></c>.</item> - <item>If E is a tuple skeleton <c><![CDATA[{E_1, ..., E_k}]]></c>, then - Rep(E) = <c><![CDATA[{tuple,LINE,[Rep(E_1), ..., Rep(E_k)]}]]></c>.</item> - <item>If E is <c><![CDATA[[]]]></c>, then - Rep(E) = <c><![CDATA[{nil,LINE}]]></c>.</item> - <item>If E is a cons skeleton <c><![CDATA[[E_h | E_t]]]></c>, then - Rep(E) = <c><![CDATA[{cons,LINE,Rep(E_h),Rep(E_t)}]]></c>.</item> - <item>If E is a binary constructor <c><![CDATA[<<V_1:Size_1/TSL_1, ..., V_k:Size_k/TSL_k>>]]></c>, then - Rep(E) = <c><![CDATA[{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)}]}]]></c>. + <item>If P is an atomic literal <c>L</c>, then Rep(P) = Rep(L).</item> + <item>If E is <c>P = E_0</c>, then + Rep(E) = <c>{match,LINE,Rep(P),Rep(E_0)}</c>.</item> + <item>If E is a variable <c>V</c>, then Rep(E) = <c>{var,LINE,A}</c>, + where <c>A</c> is an atom with a printname consisting of the same + characters as <c>V</c>.</item> + <item>If E is a tuple skeleton <c>{E_1, ..., E_k}</c>, then + Rep(E) = <c>{tuple,LINE,[Rep(E_1), ..., Rep(E_k)]}</c>.</item> + <item>If E is <c>[]</c>, then + Rep(E) = <c>{nil,LINE}</c>.</item> + <item>If E is a cons skeleton <c>[E_h | E_t]</c>, then + Rep(E) = <c>{cons,LINE,Rep(E_h),Rep(E_t)}</c>.</item> + <item>If E is a binary constructor <c><<V_1:Size_1/TSL_1, ..., V_k:Size_k/TSL_k>></c>, then Rep(E) = + <c>{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)}]}</c>. For Rep(TSL), see below. - An omitted <c><![CDATA[Size]]></c> is represented by <c><![CDATA[default]]></c>. An omitted <c><![CDATA[TSL]]></c> - (type specifier list) is represented by <c><![CDATA[default]]></c>.</item> - <item>If E is <c><![CDATA[E_1 Op E_2]]></c>, where <c><![CDATA[Op]]></c> is a binary operator, - then Rep(E) = <c><![CDATA[{op,LINE,Op,Rep(E_1),Rep(E_2)}]]></c>.</item> - <item>If E is <c><![CDATA[Op E_0]]></c>, where <c><![CDATA[Op]]></c> is a unary operator, then - Rep(E) = <c><![CDATA[{op,LINE,Op,Rep(E_0)}]]></c>.</item> - <item>If E is <c><![CDATA[#Name{Field_1=E_1, ..., Field_k=E_k}]]></c>, then - Rep(E) = - <c><![CDATA[{record,LINE,Name, [{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}]]></c>.</item> - <item>If E is <c><![CDATA[E_0#Name{Field_1=E_1, ..., Field_k=E_k}]]></c>, then + An omitted <c>Size</c> is represented by <c>default</c>. An omitted <c>TSL</c> + (type specifier list) is represented by <c>default</c>.</item> + <item>If E is <c>E_1 Op E_2</c>, where <c>Op</c> is a binary operator, + then Rep(E) = <c>{op,LINE,Op,Rep(E_1),Rep(E_2)}</c>.</item> + <item>If E is <c>Op E_0</c>, where <c>Op</c> is a unary operator, then + Rep(E) = <c>{op,LINE,Op,Rep(E_0)}</c>.</item> + <item>If E is <c>#Name{Field_1=E_1, ..., Field_k=E_k}</c>, + then Rep(E) = + <c>{record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}</c>.</item> + <item>If E is <c>E_0#Name{Field_1=E_1, ..., Field_k=E_k}</c>, then Rep(E) = - <c><![CDATA[{record,LINE,Rep(E_0),Name, [{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}]]></c>.</item> - <item>If E is <c><![CDATA[#Name.Field]]></c>, then - Rep(E) = <c><![CDATA[{record_index,LINE,Name,Rep(Field)}]]></c>.</item> - <item>If E is <c><![CDATA[E_0#Name.Field]]></c>, then - Rep(E) = <c><![CDATA[{record_field,LINE,Rep(E_0),Name,Rep(Field)}]]></c>.</item> - <item>If E is <c><![CDATA[#{W_1, ..., W_k}]]></c> where each - <c><![CDATA[W_i]]></c> is a map assoc or exact field, then Rep(E) = - <c><![CDATA[{map,LINE,[Rep(W_1), ..., Rep(W_k)]}]]></c>. For Rep(W), see + <c>{record,LINE,Rep(E_0),Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}</c>.</item> + <item>If E is <c>#Name.Field</c>, then + Rep(E) = <c>{record_index,LINE,Name,Rep(Field)}</c>.</item> + <item>If E is <c>E_0#Name.Field</c>, then + Rep(E) = <c>{record_field,LINE,Rep(E_0),Name,Rep(Field)}</c>.</item> + <item>If E is <c>#{W_1, ..., W_k}</c> where each + <c>W_i</c> is a map assoc or exact field, then Rep(E) = + <c>{map,LINE,[Rep(W_1), ..., Rep(W_k)]}</c>. For Rep(W), see below.</item> - <item>If E is <c><![CDATA[E_0#{W_1, ..., W_k}]]></c> where - <c><![CDATA[W_i]]></c> is a map assoc or exact field, then Rep(E) = - <c><![CDATA[{map,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}]]></c>. For - Rep(W), see below.</item> - <item>If E is <c><![CDATA[catch E_0]]></c>, then - Rep(E) = <c><![CDATA[{'catch',LINE,Rep(E_0)}]]></c>.</item> - <item>If E is <c><![CDATA[E_0(E_1, ..., E_k)]]></c>, then - Rep(E) = <c><![CDATA[{call,LINE,Rep(E_0),[Rep(E_1), ..., Rep(E_k)]}]]></c>.</item> - <item>If E is <c><![CDATA[E_m:E_0(E_1, ..., E_k)]]></c>, then - Rep(E) = - <c><![CDATA[{call,LINE,{remote,LINE,Rep(E_m),Rep(E_0)},[Rep(E_1), ..., Rep(E_k)]}]]></c>.</item> - <item>If E is a list comprehension <c><![CDATA[[E_0 || W_1, ..., W_k]]]></c>, - where each <c><![CDATA[W_i]]></c> is a generator or a filter, then - Rep(E) = <c><![CDATA[{lc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}]]></c>. For Rep(W), see - below.</item> - <item>If E is a binary comprehension <c><![CDATA[<<E_0 || W_1, ..., W_k>>]]></c>, - where each <c><![CDATA[W_i]]></c> is a generator or a filter, then - Rep(E) = <c><![CDATA[{bc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}]]></c>. For Rep(W), see + <item>If E is <c>E_0#{W_1, ..., W_k}</c> where + <c>W_i</c> is a map assoc or exact field, then Rep(E) = + <c>{map,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}</c>. + For Rep(W), see below.</item> + <item>If E is <c>catch E_0</c>, then + Rep(E) = <c>{'catch',LINE,Rep(E_0)}</c>.</item> + <item>If E is <c>E_0(E_1, ..., E_k)</c>, then + Rep(E) = <c>{call,LINE,Rep(E_0),[Rep(E_1), ..., Rep(E_k)]}</c>.</item> + <item>If E is <c>E_m:E_0(E_1, ..., E_k)</c>, then Rep(E) = + <c>{call,LINE,{remote,LINE,Rep(E_m),Rep(E_0)},[Rep(E_1), ..., Rep(E_k)]}</c>. + </item> + <item>If E is a list comprehension <c>[E_0 || W_1, ..., W_k]</c>, + where each <c>W_i</c> is a generator or a filter, then Rep(E) = + <c>{lc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}</c>. For Rep(W), see below.</item> - <item>If E is <c><![CDATA[begin B end]]></c>, where <c><![CDATA[B]]></c> is a body, then - Rep(E) = <c><![CDATA[{block,LINE,Rep(B)}]]></c>.</item> - <item>If E is <c><![CDATA[if Ic_1 ; ... ; Ic_k end]]></c>, - where each <c><![CDATA[Ic_i]]></c> is an if clause then - Rep(E) = - <c><![CDATA[{'if',LINE,[Rep(Ic_1), ..., Rep(Ic_k)]}]]></c>.</item> - <item>If E is <c><![CDATA[case E_0 of Cc_1 ; ... ; Cc_k end]]></c>, - where <c><![CDATA[E_0]]></c> is an expression and each <c><![CDATA[Cc_i]]></c> is a - case clause then - Rep(E) = - <c><![CDATA[{'case',LINE,Rep(E_0),[Rep(Cc_1), ..., Rep(Cc_k)]}]]></c>.</item> - <item>If E is <c><![CDATA[try B catch Tc_1 ; ... ; Tc_k end]]></c>, - where <c><![CDATA[B]]></c> is a body and each <c><![CDATA[Tc_i]]></c> is a catch clause then - Rep(E) = - <c><![CDATA[{'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],[]}]]></c>.</item> - <item>If E is <c><![CDATA[try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n end]]></c>, - where <c><![CDATA[B]]></c> is a body, - each <c><![CDATA[Cc_i]]></c> is a case clause and - each <c><![CDATA[Tc_j]]></c> is a catch clause then - Rep(E) = - <c><![CDATA[{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],[]}]]></c>.</item> - <item>If E is <c><![CDATA[try B after A end]]></c>, - where <c><![CDATA[B]]></c> and <c><![CDATA[A]]></c> are bodies then - Rep(E) = - <c><![CDATA[{'try',LINE,Rep(B),[],[],Rep(A)}]]></c>.</item> - <item>If E is <c><![CDATA[try B of Cc_1 ; ... ; Cc_k after A end]]></c>, - where <c><![CDATA[B]]></c> and <c><![CDATA[A]]></c> are a bodies and - each <c><![CDATA[Cc_i]]></c> is a case clause then - Rep(E) = - <c><![CDATA[{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[],Rep(A)}]]></c>.</item> - <item>If E is <c><![CDATA[try B catch Tc_1 ; ... ; Tc_k after A end]]></c>, - where <c><![CDATA[B]]></c> and <c><![CDATA[A]]></c> are bodies and - each <c><![CDATA[Tc_i]]></c> is a catch clause then - Rep(E) = - <c><![CDATA[{'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],Rep(A)}]]></c>.</item> - <item>If E is <c><![CDATA[try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n after A end]]></c>, - where <c><![CDATA[B]]></c> and <c><![CDATA[A]]></c> are a bodies, - each <c><![CDATA[Cc_i]]></c> is a case clause and - each <c><![CDATA[Tc_j]]></c> is a catch clause then - Rep(E) = - <c><![CDATA[{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],Rep(A)}]]></c>.</item> - <item>If E is <c><![CDATA[receive Cc_1 ; ... ; Cc_k end]]></c>, - where each <c><![CDATA[Cc_i]]></c> is a case clause then + <item>If E is a binary comprehension + <c><<E_0 || W_1, ..., W_k>></c>, + where each <c>W_i</c> is a generator or a filter, then + Rep(E) = <c>{bc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}</c>. + For Rep(W), see below.</item> + <item>If E is <c>begin B end</c>, where <c>B</c> is a body, then + Rep(E) = <c>{block,LINE,Rep(B)}</c>.</item> + <item>If E is <c>if Ic_1 ; ... ; Ic_k end</c>, + where each <c>Ic_i</c> is an if clause then Rep(E) = + <c>{'if',LINE,[Rep(Ic_1), ..., Rep(Ic_k)]}</c>.</item> + <item>If E is <c>case E_0 of Cc_1 ; ... ; Cc_k end</c>, + where <c>E_0</c> is an expression and each <c>Cc_i</c> is a + case clause then Rep(E) = + <c>{'case',LINE,Rep(E_0),[Rep(Cc_1), ..., Rep(Cc_k)]}</c>.</item> + <item>If E is <c>try B catch Tc_1 ; ... ; Tc_k end</c>, + where <c>B</c> is a body and each <c>Tc_i</c> is a catch clause then Rep(E) = - <c><![CDATA[{'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)]}]]></c>.</item> - <item>If E is <c><![CDATA[receive Cc_1 ; ... ; Cc_k after E_0 -> B_t end]]></c>, - where each <c><![CDATA[Cc_i]]></c> is a case clause, - <c><![CDATA[E_0]]></c> is an expression and <c><![CDATA[B_t]]></c> is a body, then + <c>{'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],[]}</c>.</item> + <item>If E is <c>try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n end</c>, + where <c>B</c> is a body, + each <c>Cc_i</c> is a case clause and + each <c>Tc_j</c> is a catch clause then Rep(E) = + <c>{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],[]}</c>.</item> + <item>If E is <c>try B after A end</c>, + where <c>B</c> and <c>A</c> are bodies then Rep(E) = + <c>{'try',LINE,Rep(B),[],[],Rep(A)}</c>.</item> + <item>If E is <c>try B of Cc_1 ; ... ; Cc_k after A end</c>, + where <c>B</c> and <c>A</c> are a bodies and + each <c>Cc_i</c> is a case clause then Rep(E) = + <c>{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[],Rep(A)}</c>.</item> + <item>If E is <c>try B catch Tc_1 ; ... ; Tc_k after A end</c>, + where <c>B</c> and <c>A</c> are bodies and + each <c>Tc_i</c> is a catch clause then Rep(E) = + <c>{'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],Rep(A)}</c>.</item> + <item>If E is <c>try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n after A end</c>, + where <c>B</c> and <c>A</c> are a bodies, + each <c>Cc_i</c> is a case clause and + each <c>Tc_j</c> is a catch clause then Rep(E) = - <c><![CDATA[{'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)],Rep(E_0),Rep(B_t)}]]></c>.</item> - <item>If E is <c><![CDATA[fun Name / Arity]]></c>, then - Rep(E) = <c><![CDATA[{'fun',LINE,{function,Name,Arity}}]]></c>.</item> - <item>If E is <c><![CDATA[fun Module:Name/Arity]]></c>, then - Rep(E) = <c><![CDATA[{'fun',LINE,{function,Rep(Module),Rep(Name),Rep(Arity)}}]]></c>. - (Before the R15 release: Rep(E) = <c><![CDATA[{'fun',LINE,{function,Module,Name,Arity}}]]></c>.)</item> - <item>If E is <c><![CDATA[fun Fc_1 ; ... ; Fc_k end]]></c> - where each <c><![CDATA[Fc_i]]></c> is a function clause then Rep(E) = - <c><![CDATA[{'fun',LINE,{clauses,[Rep(Fc_1), ..., Rep(Fc_k)]}}]]></c>.</item> - <item>If E is <c><![CDATA[fun Name Fc_1 ; ... ; Name Fc_k end]]></c> - where <c><![CDATA[Name]]></c> is a variable and each - <c><![CDATA[Fc_i]]></c> is a function clause then Rep(E) = - <c><![CDATA[{named_fun,LINE,Name,[Rep(Fc_1), ..., Rep(Fc_k)]}]]></c>. + <c>{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],Rep(A)}</c>.</item> + <item>If E is <c>receive Cc_1 ; ... ; Cc_k end</c>, + where each <c>Cc_i</c> is a case clause then Rep(E) = + <c>{'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)]}</c>.</item> + <item>If E is <c>receive Cc_1 ; ... ; Cc_k after E_0 -> B_t end</c>, + where each <c>Cc_i</c> is a case clause, + <c>E_0</c> is an expression and <c>B_t</c> is a body, then Rep(E) = + <c>{'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)],Rep(E_0),Rep(B_t)}</c>.</item> + <item>If E is <c>fun Name / Arity</c>, then + Rep(E) = <c>{'fun',LINE,{function,Name,Arity}}</c>.</item> + <item>If E is <c>fun Module:Name/Arity</c>, then Rep(E) = + <c>{'fun',LINE,{function,Rep(Module),Rep(Name),Rep(Arity)}}</c>. + (Before the R15 release: Rep(E) = + <c>{'fun',LINE,{function,Module,Name,Arity}}</c>.)</item> + <item>If E is <c>fun Fc_1 ; ... ; Fc_k end</c> + where each <c>Fc_i</c> is a function clause then Rep(E) = + <c>{'fun',LINE,{clauses,[Rep(Fc_1), ..., Rep(Fc_k)]}}</c>.</item> + <item>If E is <c>fun Name Fc_1 ; ... ; Name Fc_k end</c> + where <c>Name</c> is a variable and each + <c>Fc_i</c> is a function clause then Rep(E) = + <c>{named_fun,LINE,Name,[Rep(Fc_1), ..., Rep(Fc_k)]}</c>. </item> - <item>If E is <c><![CDATA[query [E_0 || W_1, ..., W_k] end]]></c>, - where each <c><![CDATA[W_i]]></c> is a generator or a filter, then - Rep(E) = <c><![CDATA[{'query',LINE,{lc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}}]]></c>. - For Rep(W), see below.</item> - <item>If E is <c><![CDATA[E_0.Field]]></c>, a Mnesia record access - inside a query, then - Rep(E) = <c><![CDATA[{record_field,LINE,Rep(E_0),Rep(Field)}]]></c>.</item> - <item>If E is <c><![CDATA[( E_0 )]]></c>, then - Rep(E) = <c><![CDATA[Rep(E_0)]]></c>, - i.e., parenthesized expressions cannot be distinguished from their bodies.</item> + <item>If E is <c>( E_0 )</c>, then + Rep(E) = <c>Rep(E_0)</c>, that is, parenthesized + expressions cannot be distinguished from their bodies.</item> </list> <section> - <title>Generators and filters</title> - <p>When W is a generator or a filter (in the body of a list or binary comprehension), then:</p> + <title>Generators and Filters</title> + <p>When W is a generator or a filter (in the body of a list or + binary comprehension), then:</p> <list type="bulleted"> - <item>If W is a generator <c><![CDATA[P <- E]]></c>, where <c><![CDATA[P]]></c> is a pattern and <c><![CDATA[E]]></c> - is an expression, then - Rep(W) = <c><![CDATA[{generate,LINE,Rep(P),Rep(E)}]]></c>.</item> - <item>If W is a generator <c><![CDATA[P <= E]]></c>, where <c><![CDATA[P]]></c> is a pattern and <c><![CDATA[E]]></c> - is an expression, then - Rep(W) = <c><![CDATA[{b_generate,LINE,Rep(P),Rep(E)}]]></c>.</item> - <item>If W is a filter <c><![CDATA[E]]></c>, which is an expression, then - Rep(W) = <c><![CDATA[Rep(E)]]></c>.</item> + <item>If W is a generator <c>P <- E</c>, where <c>P</c> is + a pattern and <c>E</c> is an expression, then + Rep(W) = <c>{generate,LINE,Rep(P),Rep(E)}</c>.</item> + <item>If W is a generator <c>P <= E</c>, where <c>P</c> is + a pattern and <c>E</c> is an expression, then + Rep(W) = <c>{b_generate,LINE,Rep(P),Rep(E)}</c>.</item> + <item>If W is a filter <c>E</c>, which is an expression, then + Rep(W) = <c>Rep(E)</c>.</item> </list> </section> <section> - <title>Binary element type specifiers</title> + <title>Binary Element Type Specifiers</title> <p>A type specifier list TSL for a binary element is a sequence of type - specifiers <c><![CDATA[TS_1 - ... - TS_k]]></c>. - Rep(TSL) = <c><![CDATA[[Rep(TS_1), ..., Rep(TS_k)]]]></c>.</p> + specifiers <c>TS_1 - ... - TS_k</c>. + Rep(TSL) = <c>[Rep(TS_1), ..., Rep(TS_k)]</c>.</p> <p>When TS is a type specifier for a binary element, then:</p> <list type="bulleted"> - <item>If TS is an atom <c><![CDATA[A]]></c>, Rep(TS) = <c><![CDATA[A]]></c>.</item> - <item>If TS is a couple <c><![CDATA[A:Value]]></c> where <c><![CDATA[A]]></c> is an atom and <c><![CDATA[Value]]></c> - is an integer, Rep(TS) = <c><![CDATA[{A, Value}]]></c>.</item> + <item>If TS is an atom <c>A</c>, then Rep(TS) = <c>A</c>.</item> + <item>If TS is a couple <c>A:Value</c> where <c>A</c> is an atom + and <c>Value</c> is an integer, then Rep(TS) = + <c>{A,Value}</c>.</item> </list> </section> <section> - <title>Map assoc and exact fields</title> + <title>Map Assoc and Exact Fields</title> <p>When W is an assoc or exact field (in the body of a map), then:</p> <list type="bulleted"> - <item>If W is an assoc field <c><![CDATA[K => V]]></c>, where - <c><![CDATA[K]]></c> and <c><![CDATA[V]]></c> are both expressions, - then Rep(W) = <c><![CDATA[{map_field_assoc,LINE,Rep(K),Rep(V)}]]></c>. + <item>If W is an assoc field <c>K => V</c>, where + <c>K</c> and <c>V</c> are both expressions, + then Rep(W) = <c>{map_field_assoc,LINE,Rep(K),Rep(V)}</c>. </item> - <item>If W is an exact field <c><![CDATA[K := V]]></c>, where - <c><![CDATA[K]]></c> and <c><![CDATA[V]]></c> are both expressions, - then Rep(W) = <c><![CDATA[{map_field_exact,LINE,Rep(K),Rep(V)}]]></c>. + <item>If W is an exact field <c>K := V</c>, where + <c>K</c> and <c>V</c> are both expressions, + then Rep(W) = <c>{map_field_exact,LINE,Rep(K),Rep(V)}</c>. </item> </list> </section> @@ -524,112 +394,220 @@ <section> <title>Clauses</title> - <p>There are function clauses, if clauses, case clauses + <p>There are function clauses, if clauses, case clauses and catch clauses.</p> - <p>A clause <c><![CDATA[C]]></c> is one of the following alternatives:</p> + <p>A clause <c>C</c> is one of the following alternatives:</p> <list type="bulleted"> - <item>If C is a function clause <c><![CDATA[( Ps ) -> B]]></c> - where <c><![CDATA[Ps]]></c> is a pattern sequence and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,Rep(Ps),[],Rep(B)}]]></c>.</item> - <item>If C is a function clause <c><![CDATA[( Ps ) when Gs -> B]]></c> - where <c><![CDATA[Ps]]></c> is a pattern sequence, - <c><![CDATA[Gs]]></c> is a guard sequence and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,Rep(Ps),Rep(Gs),Rep(B)}]]></c>.</item> - <item>If C is an if clause <c><![CDATA[Gs -> B]]></c> - where <c><![CDATA[Gs]]></c> is a guard sequence and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,[],Rep(Gs),Rep(B)}]]></c>.</item> - <item>If C is a case clause <c><![CDATA[P -> B]]></c> - where <c><![CDATA[P]]></c> is a pattern and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,[Rep(P)],[],Rep(B)}]]></c>.</item> - <item>If C is a case clause <c><![CDATA[P when Gs -> B]]></c> - where <c><![CDATA[P]]></c> is a pattern, - <c><![CDATA[Gs]]></c> is a guard sequence and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,[Rep(P)],Rep(Gs),Rep(B)}]]></c>.</item> - <item>If C is a catch clause <c><![CDATA[P -> B]]></c> - where <c><![CDATA[P]]></c> is a pattern and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,[Rep({throw,P,_})],[],Rep(B)}]]></c>.</item> - <item>If C is a catch clause <c><![CDATA[X : P -> B]]></c> - where <c><![CDATA[X]]></c> is an atomic literal or a variable pattern, - <c><![CDATA[P]]></c> is a pattern and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,[Rep({X,P,_})],[],Rep(B)}]]></c>.</item> - <item>If C is a catch clause <c><![CDATA[P when Gs -> B]]></c> - where <c><![CDATA[P]]></c> is a pattern, <c><![CDATA[Gs]]></c> is a guard sequence - and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,[Rep({throw,P,_})],Rep(Gs),Rep(B)}]]></c>.</item> - <item>If C is a catch clause <c><![CDATA[X : P when Gs -> B]]></c> - where <c><![CDATA[X]]></c> is an atomic literal or a variable pattern, - <c><![CDATA[P]]></c> is a pattern, <c><![CDATA[Gs]]></c> is a guard sequence - and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,[Rep({X,P,_})],Rep(Gs),Rep(B)}]]></c>.</item> + <item>If C is a function clause <c>( Ps ) -> B</c> + where <c>Ps</c> is a pattern sequence and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,Rep(Ps),[],Rep(B)}</c>.</item> + <item>If C is a function clause <c>( Ps ) when Gs -> B</c> + where <c>Ps</c> is a pattern sequence, + <c>Gs</c> is a guard sequence and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,Rep(Ps),Rep(Gs),Rep(B)}</c>.</item> + <item>If C is an if clause <c>Gs -> B</c> + where <c>Gs</c> is a guard sequence and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,[],Rep(Gs),Rep(B)}</c>.</item> + <item>If C is a case clause <c>P -> B</c> + where <c>P</c> is a pattern and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,[Rep(P)],[],Rep(B)}</c>.</item> + <item>If C is a case clause <c>P when Gs -> B</c> + where <c>P</c> is a pattern, + <c>Gs</c> is a guard sequence and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,[Rep(P)],Rep(Gs),Rep(B)}</c>.</item> + <item>If C is a catch clause <c>P -> B</c> + where <c>P</c> is a pattern and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,[Rep({throw,P,_})],[],Rep(B)}</c>.</item> + <item>If C is a catch clause <c>X : P -> B</c> + where <c>X</c> is an atomic literal or a variable pattern, + <c>P</c> is a pattern and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,[Rep({X,P,_})],[],Rep(B)}</c>.</item> + <item>If C is a catch clause <c>P when Gs -> B</c> + where <c>P</c> is a pattern, <c>Gs</c> is a guard sequence + and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,[Rep({throw,P,_})],Rep(Gs),Rep(B)}</c>.</item> + <item>If C is a catch clause <c>X : P when Gs -> B</c> + where <c>X</c> is an atomic literal or a variable pattern, + <c>P</c> is a pattern, <c>Gs</c> is a guard sequence + and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,[Rep({X,P,_})],Rep(Gs),Rep(B)}</c>.</item> </list> </section> <section> <title>Guards</title> - <p>A guard sequence Gs is a sequence of guards <c><![CDATA[G_1; ...; G_k]]></c>, and - Rep(Gs) = <c><![CDATA[[Rep(G_1), ..., Rep(G_k)]]]></c>. If the guard sequence is - empty, Rep(Gs) = <c><![CDATA[[]]]></c>.</p> - <p>A guard G is a nonempty sequence of guard tests <c><![CDATA[Gt_1, ..., Gt_k]]></c>, and - Rep(G) = <c><![CDATA[[Rep(Gt_1), ..., Rep(Gt_k)]]]></c>.</p> - <p>A guard test <c><![CDATA[Gt]]></c> is one of the following alternatives:</p> + <p>A guard sequence Gs is a sequence of guards <c>G_1; ...; G_k</c>, and + Rep(Gs) = <c>[Rep(G_1), ..., Rep(G_k)]</c>. If the guard sequence is + empty, Rep(Gs) = <c>[]</c>.</p> + <p>A guard G is a nonempty sequence of guard tests + <c>Gt_1, ..., Gt_k</c>, and Rep(G) = + <c>[Rep(Gt_1), ..., Rep(Gt_k)]</c>.</p> + <p>A guard test <c>Gt</c> is one of the following alternatives:</p> <list type="bulleted"> <item>If Gt is an atomic literal L, then Rep(Gt) = Rep(L).</item> - <item>If Gt is a variable pattern <c><![CDATA[V]]></c>, then - Rep(Gt) = <c><![CDATA[{var,LINE,A}]]></c>, - where A is an atom with a printname consisting of the same characters as - <c><![CDATA[V]]></c>.</item> - <item>If Gt is a tuple skeleton <c><![CDATA[{Gt_1, ..., Gt_k}]]></c>, then - Rep(Gt) = <c><![CDATA[{tuple,LINE,[Rep(Gt_1), ..., Rep(Gt_k)]}]]></c>.</item> - <item>If Gt is <c><![CDATA[[]]]></c>, then - Rep(Gt) = <c><![CDATA[{nil,LINE}]]></c>.</item> - <item>If Gt is a cons skeleton <c><![CDATA[[Gt_h | Gt_t]]]></c>, then - Rep(Gt) = <c><![CDATA[{cons,LINE,Rep(Gt_h),Rep(Gt_t)}]]></c>.</item> - <item>If Gt is a binary constructor <c><![CDATA[<<Gt_1:Size_1/TSL_1, ..., Gt_k:Size_k/TSL_k>>]]></c>, then - Rep(Gt) = <c><![CDATA[{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)}]}]]></c>. + <item>If Gt is a variable pattern <c>V</c>, then + Rep(Gt) = <c>{var,LINE,A}</c>, where A is an atom with + a printname consisting of the same characters as <c>V</c>.</item> + <item>If Gt is a tuple skeleton <c>{Gt_1, ..., Gt_k}</c>, then + Rep(Gt) = <c>{tuple,LINE,[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.</item> + <item>If Gt is <c>[]</c>, then Rep(Gt) = <c>{nil,LINE}</c>.</item> + <item>If Gt is a cons skeleton <c>[Gt_h | Gt_t]</c>, then + Rep(Gt) = <c>{cons,LINE,Rep(Gt_h),Rep(Gt_t)}</c>.</item> + <item>If Gt is a binary constructor + <c><<Gt_1:Size_1/TSL_1, ..., Gt_k:Size_k/TSL_k>></c>, then + Rep(Gt) = <c>{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)}]}</c>. For Rep(TSL), see above. - An omitted <c><![CDATA[Size]]></c> is represented by <c><![CDATA[default]]></c>. An omitted <c><![CDATA[TSL]]></c> - (type specifier list) is represented by <c><![CDATA[default]]></c>.</item> - <item>If Gt is <c><![CDATA[Gt_1 Op Gt_2]]></c>, where <c><![CDATA[Op]]></c> - is a binary operator, then Rep(Gt) = <c><![CDATA[{op,LINE,Op,Rep(Gt_1),Rep(Gt_2)}]]></c>.</item> - <item>If Gt is <c><![CDATA[Op Gt_0]]></c>, where <c><![CDATA[Op]]></c> is a unary operator, then - Rep(Gt) = <c><![CDATA[{op,LINE,Op,Rep(Gt_0)}]]></c>.</item> - <item>If Gt is <c><![CDATA[#Name{Field_1=Gt_1, ..., Field_k=Gt_k}]]></c>, then + An omitted <c>Size</c> is represented by <c>default</c>. + An omitted <c>TSL</c> (type specifier list) is represented + by <c>default</c>.</item> + <item>If Gt is <c>Gt_1 Op Gt_2</c>, where <c>Op</c> + is a binary operator, then Rep(Gt) = + <c>{op,LINE,Op,Rep(Gt_1),Rep(Gt_2)}</c>.</item> + <item>If Gt is <c>Op Gt_0</c>, where <c>Op</c> is a unary operator, then + Rep(Gt) = <c>{op,LINE,Op,Rep(Gt_0)}</c>.</item> + <item>If Gt is <c>#Name{Field_1=Gt_1, ..., Field_k=Gt_k}</c>, then Rep(E) = - <c><![CDATA[{record,LINE,Name, [{record_field,LINE,Rep(Field_1),Rep(Gt_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(Gt_k)}]}]]></c>.</item> - <item>If Gt is <c><![CDATA[#Name.Field]]></c>, then - Rep(Gt) = <c><![CDATA[{record_index,LINE,Name,Rep(Field)}]]></c>.</item> - <item>If Gt is <c><![CDATA[Gt_0#Name.Field]]></c>, then - Rep(Gt) = <c><![CDATA[{record_field,LINE,Rep(Gt_0),Name,Rep(Field)}]]></c>.</item> - <item>If Gt is <c><![CDATA[A(Gt_1, ..., Gt_k)]]></c>, where <c><![CDATA[A]]></c> is an atom, then - Rep(Gt) = <c><![CDATA[{call,LINE,Rep(A),[Rep(Gt_1), ..., Rep(Gt_k)]}]]></c>.</item> - <item>If Gt is <c><![CDATA[A_m:A(Gt_1, ..., Gt_k)]]></c>, where <c><![CDATA[A_m]]></c> is - the atom <c><![CDATA[erlang]]></c> and <c><![CDATA[A]]></c> is an atom or an operator, then - Rep(Gt) = <c><![CDATA[{call,LINE,{remote,LINE,Rep(A_m),Rep(A)},[Rep(Gt_1), ..., Rep(Gt_k)]}]]></c>.</item> - <item>If Gt is <c><![CDATA[{A_m,A}(Gt_1, ..., Gt_k)]]></c>, where <c><![CDATA[A_m]]></c> is - the atom <c><![CDATA[erlang]]></c> and <c><![CDATA[A]]></c> is an atom or an operator, then - Rep(Gt) = <c><![CDATA[{call,LINE,Rep({A_m,A}),[Rep(Gt_1), ..., Rep(Gt_k)]}]]></c>.</item> - <item>If Gt is <c><![CDATA[( Gt_0 )]]></c>, then - Rep(Gt) = <c><![CDATA[Rep(Gt_0)]]></c>, - i.e., parenthesized guard tests cannot be distinguished from their bodies.</item> + <c>{record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(Gt_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(Gt_k)}]}</c>.</item> + <item>If Gt is <c>#Name.Field</c>, then + Rep(Gt) = <c>{record_index,LINE,Name,Rep(Field)}</c>.</item> + <item>If Gt is <c>Gt_0#Name.Field</c>, then + Rep(Gt) = <c>{record_field,LINE,Rep(Gt_0),Name,Rep(Field)}</c>.</item> + <item>If Gt is <c>A(Gt_1, ..., Gt_k)</c>, where <c>A</c> is an atom, then + Rep(Gt) = <c>{call,LINE,Rep(A),[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.</item> + <item>If Gt is <c>A_m:A(Gt_1, ..., Gt_k)</c>, where <c>A_m</c> is + the atom <c>erlang</c> and <c>A</c> is an atom or an operator, then + Rep(Gt) = <c>{call,LINE,{remote,LINE,Rep(A_m),Rep(A)},[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.</item> + <item>If Gt is <c>{A_m,A}(Gt_1, ..., Gt_k)</c>, where <c>A_m</c> is + the atom <c>erlang</c> and <c>A</c> is an atom or an operator, then + Rep(Gt) = <c>{call,LINE,Rep({A_m,A}),[Rep(Gt_1), ..., Rep(Gt_k)]}</c>. + </item> + <item>If Gt is <c>( Gt_0 )</c>, then + Rep(Gt) = <c>Rep(Gt_0)</c>, that is, parenthesized + guard tests cannot be distinguished from their bodies.</item> </list> <p>Note that every guard test has the same source form as some expression, and is represented the same way as the corresponding expression.</p> </section> <section> - <title>The abstract format after preprocessing</title> - <p>The compilation option <c><![CDATA[debug_info]]></c> can be given to the - compiler to have the abstract code stored in - the <c><![CDATA[abstract_code]]></c> chunk in the BEAM file + <title>Types</title> + <list type="bulleted"> + <item>If T is an annotated type <c>Anno :: Type</c>, + where <c>Anno</c> is a variable and + <c>Type</c> is a type, then Rep(T) = + <c>{ann_type,LINE,[Rep(Anno),Rep(Type)]}</c>.</item> + <item>If T is an atom or integer literal L, then Rep(T) = Rep(L). + </item> + <item>If T is <c>L Op R</c>, + where <c>Op</c> is a binary operator and <c>L</c> and <c>R</c> + are types (this is an occurrence of an expression that can be + evaluated to an integer at compile time), then + Rep(T) = <c>{op,LINE,Op,Rep(L),Rep(R)}</c>.</item> + <item>If T is <c>Op A</c>, where <c>Op</c> is a + unary operator and <c>A</c> is a type (this is an occurrence of + an expression that can be evaluated to an integer at compile time), + then Rep(T) = <c>{op,LINE,Op,Rep(A)}</c>.</item> + <item>If T is a bitstring type <c><<_:M,_:_*N>></c>, + where <c>M</c> and <c>N</c> are singleton integer types, then Rep(T) = + <c>{type,LINE,binary,[Rep(M),Rep(N)]}</c>.</item> + <item>If T is the empty list type <c>[]</c>, then Rep(T) = + <c>{type,Line,nil,[]}</c>.</item> + <item>If T is a fun type <c>fun()</c>, then Rep(T) = + <c>{type,LINE,'fun',[]}</c>.</item> + <item>If T is a fun type <c>fun((...) -> B)</c>, + where <c>B</c> is a type, then + Rep(T) = <c>{type,LINE,'fun',[{type,LINE,any},Rep(B)]}</c>. + </item> + <item>If T is a fun type <c>fun(Ft)</c>, where + <c>Ft</c> is a function type, + then Rep(T) = <c>Rep(Ft)</c>.</item> + <item>If T is an integer range type <c>L .. H</c>, + where <c>L</c> and <c>H</c> are singleton integer types, then + Rep(T) = <c>{type,LINE,range,[Rep(L),Rep(H)]}</c>.</item> + <item>If T is a map type <c>map()</c>, then Rep(T) = + <c>{type,LINE,map,any}</c>.</item> + <item>If T is a map type <c>#{P_1, ..., P_k}</c>, where each + <c>P_i</c> is a map pair type, then Rep(T) = + <c>{type,LINE,map,[Rep(P_1), ..., Rep(P_k)]}</c>.</item> + <item>If T is a map pair type <c>K => V</c>, where + <c>K</c> and <c>V</c> are types, then Rep(T) = + <c>{type,LINE,map_field_assoc,[Rep(K),Rep(V)]}</c>.</item> + <item>If T is a predefined (or built-in) type <c>N(A_1, ..., A_k)</c>, + where each <c>A_i</c> is a type, then Rep(T) = + <c>{type,LINE,N,[Rep(A_1), ..., Rep(A_k)]}</c>.</item> + <item>If T is a record type <c>#Name{F_1, ..., F_k}</c>, + where each <c>F_i</c> is a record field type, then Rep(T) = + <c>{type,LINE,record,[Rep(Name),Rep(F_1), ..., Rep(F_k)]}</c>. + </item> + <item>If T is a record field type <c>Name :: Type</c>, + where <c>Type</c> is a type, then Rep(T) = + <c>{type,LINE,field_type,[Rep(Name),Rep(Type)]}</c>.</item> + <item>If T is a remote type <c>M:N(A_1, ..., A_k)</c>, where + each <c>A_i</c> is a type, then Rep(T) = + <c>{remote_type,LINE,[Rep(M),Rep(N),[Rep(A_1), ..., Rep(A_k)]]}</c>. + </item> + <item>If T is a tuple type <c>tuple()</c>, then Rep(T) = + <c>{type,LINE,tuple,any}</c>.</item> + <item>If T is a tuple type <c>{A_1, ..., A_k}</c>, where + each <c>A_i</c> is a type, then Rep(T) = + <c>{type,LINE,tuple,[Rep(A_1), ..., Rep(A_k)]}</c>.</item> + <item>If T is a type union <c>T_1 | ... | T_k</c>, + where each <c>T_i</c> is a type, then Rep(T) = + <c>{type,LINE,union,[Rep(T_1), ..., Rep(T_k)]}</c>.</item> + <item>If T is a type variable <c>V</c>, then Rep(T) = + <c>{var,LINE,A}</c>, where <c>A</c> is an atom with a printname + consisting of the same characters as <c>V</c>. A type variable + is any variable except underscore (<c>_</c>).</item> + <item>If T is a user-defined type <c>N(A_1, ..., A_k)</c>, + where each <c>A_i</c> is a type, then Rep(T) = + <c>{user_type,LINE,N,[Rep(A_1), ..., Rep(A_k)]}</c>.</item> + <item>If T is <c>( T_0 )</c>, then Rep(T) = <c>Rep(T_0)</c>, + that is, parenthesized types cannot be distinguished from their + bodies.</item> + </list> + + <section> + <title>Function Types</title> + <list type="bulleted"> + <item>If Ft is a constrained function type <c>Ft_1 when Fc</c>, + where <c>Ft_1</c> is a function type and + <c>Fc</c> is a function constraint, then Rep(T) = + <c>{type,LINE,bounded_fun,[Rep(Ft_1),Rep(Fc)]}</c>.</item> + <item>If Ft is a function type <c>(A_1, ..., A_n) -> B</c>, + where each <c>A_i</c> and <c>B</c> are types, then + Rep(Ft) = <c>{type,LINE,'fun',[{type,LINE,product,[Rep(A_1), + ..., Rep(A_n)]},Rep(B)]}</c>.</item> + </list> + </section> + + <section> + <title>Function Constraints</title> + <p>A function constraint Fc is a nonempty sequence of constraints + <c>C_1, ..., C_k</c>, and + Rep(Fc) = <c>[Rep(C_1), ..., Rep(C_k)]</c>.</p> + <list type="bulleted"> + <item>If C is a constraint <c>is_subtype(V, T)</c> or <c>V :: T</c>, + where <c>V</c> is a type variable and <c>T</c> is a type, then + Rep(C) = <c>{type,LINE,constraint,[Rep(F),[Rep(V),Rep(T)]]}</c>. + </item> + </list> + </section> + </section> + + <section> + <title>The Abstract Format After Preprocessing</title> + <p>The compilation option <c>debug_info</c> can be given to the + compiler to have the abstract code stored in + the <c>abstract_code</c> chunk in the BEAM file (for debugging purposes).</p> - <p>In OTP R9C and later, the <c><![CDATA[abstract_code]]></c> chunk will + <p>In OTP R9C and later, the <c>abstract_code</c> chunk will contain</p> - <p><c><![CDATA[{raw_abstract_v1,AbstractCode}]]></c></p> - <p>where <c><![CDATA[AbstractCode]]></c> is the abstract code as described + <p><c>{raw_abstract_v1,AbstractCode}</c></p> + <p>where <c>AbstractCode</c> is the abstract code as described in this document.</p> <p>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 <c><![CDATA[abstract_v1]]></c> (R7B) or <c><![CDATA[abstract_v2]]></c> + tuple would be either <c>abstract_v1</c> (R7B) or <c>abstract_v2</c> (R8B).</p> </section> </chapter> diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index f27e73b9d3..b4bdc5735c 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -31,8 +31,9 @@ </header> <p>This document describes the changes made to the ERTS application.</p> -<section><title>Erts 7.1</title> + +<section><title>Erts 7.1</title> <section><title>Fixed Bugs and Malfunctions</title> <list> <item> @@ -981,6 +982,26 @@ </section> +<section><title>Erts 6.4.1.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The 'raw' socket option could not be used multiple times + in one call to any e.g gen_tcp function because only one + of the occurrences were used. This bug has been fixed, + and also a small bug concerning propagating error codes + from within inet:setopts/2.</p> + <p> + Own Id: OTP-11482 Aux Id: seq12872 </p> + </item> + </list> + </section> + +</section> + + <section><title>Erts 6.4.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index a829599fe5..89011d89ad 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1997-2013. All Rights Reserved. + * Copyright Ericsson AB 1997-2015. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -6076,9 +6076,9 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len) int arg_sz; enum PacketParseType old_htype = desc->htype; int old_active = desc->active; - int propagate = 0; /* Set to 1 if failure to set this option - should be propagated to erlang (not all - errors can be propagated for BC reasons) */ + int propagate; /* Set to 1 if failure to set this option + should be propagated to erlang (not all + errors can be propagated for BC reasons) */ int res; #ifdef HAVE_SCTP /* SCTP sockets are treated completely separately: */ @@ -6095,6 +6095,7 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len) arg_ptr = (char*) &ival; arg_sz = sizeof(ival); proto = SOL_SOCKET; + propagate = 0; switch(opt) { case INET_LOPT_HEADER: diff --git a/erts/emulator/hipe/hipe_x86_signal.c b/erts/emulator/hipe/hipe_x86_signal.c index bb8a3f041f..69d4ea10c2 100644 --- a/erts/emulator/hipe/hipe_x86_signal.c +++ b/erts/emulator/hipe/hipe_x86_signal.c @@ -198,7 +198,7 @@ static void do_init(void) #define INIT() do { if (!init_done()) do_init(); } while (0) #endif /* __DARWIN__ */ -#if !defined(__GLIBC__) && !defined(__DARWIN__) && !defined(__NetBSD__) +#if defined(__sun__) /* * Assume Solaris/x86 2.8. * There is a number of sigaction() procedures in libc: @@ -232,7 +232,34 @@ static void do_init(void) } #define _NSIG NSIG #define INIT() do { if (!init_done()) do_init(); } while (0) -#endif /* not glibc or darwin */ +#endif /* __sun__ */ + +#if !(defined(__GLIBC__) || defined(__DARWIN__) || defined(__NetBSD__) || defined(__sun__)) +/* + * Unknown libc -- assume musl. Note: musl deliberately does not provide a musl-specific + * feature test macro, so we cannot check for it. + * + * sigaction is a weak alias for __sigaction, which is a wrapper for __libc_sigaction. + * There are libc-internal calls to __libc_sigaction which install handlers, so we must + * override __libc_sigaction rather than __sigaction. + */ +#include <dlfcn.h> +static int (*__next_sigaction)(int, const struct sigaction*, struct sigaction*); +#define init_done() (__next_sigaction != 0) +#define __SIGACTION __libc_sigaction +static void do_init(void) +{ + __next_sigaction = dlsym(RTLD_NEXT, "__libc_sigaction"); + if (__next_sigaction != 0) + return; + perror("dlsym"); + abort(); +} +#ifndef _NSIG +#define _NSIG NSIG +#endif +#define INIT() do { if (!init_done()) do_init(); } while (0) +#endif /* !(__GLIBC__ || __DARWIN__ || __NetBSD__ || __sun__) */ #if !defined(__NetBSD__) /* diff --git a/lib/asn1/src/asn1rtt_ber.erl b/lib/asn1/src/asn1rtt_ber.erl index 39fa8aaf99..e50b14941c 100644 --- a/lib/asn1/src/asn1rtt_ber.erl +++ b/lib/asn1/src/asn1rtt_ber.erl @@ -739,6 +739,8 @@ encode_named_bit_string([H|_]=Bits, NamedBitList, TagIn) when is_atom(H) -> do_encode_named_bit_string(Bits, NamedBitList, TagIn); encode_named_bit_string([{bit,_}|_]=Bits, NamedBitList, TagIn) -> do_encode_named_bit_string(Bits, NamedBitList, TagIn); +encode_named_bit_string([], _NamedBitList, TagIn) -> + encode_unnamed_bit_string(<<>>, TagIn); encode_named_bit_string(Bits, _NamedBitList, TagIn) when is_bitstring(Bits) -> encode_unnamed_bit_string(Bits, TagIn). @@ -746,6 +748,8 @@ encode_named_bit_string(C, [H|_]=Bits, NamedBitList, TagIn) when is_atom(H) -> do_encode_named_bit_string(C, Bits, NamedBitList, TagIn); encode_named_bit_string(C, [{bit,_}|_]=Bits, NamedBitList, TagIn) -> do_encode_named_bit_string(C, Bits, NamedBitList, TagIn); +encode_named_bit_string(C, [], _NamedBitList, TagIn) -> + encode_unnamed_bit_string(C, <<>>, TagIn); encode_named_bit_string(C, Bits, _NamedBitList, TagIn) when is_bitstring(Bits) -> encode_unnamed_bit_string(C, Bits, TagIn). diff --git a/lib/asn1/test/testPrimStrings.erl b/lib/asn1/test/testPrimStrings.erl index fa778765b1..46793c6bff 100644 --- a/lib/asn1/test/testPrimStrings.erl +++ b/lib/asn1/test/testPrimStrings.erl @@ -123,6 +123,7 @@ bit_string(Rules, Opts) -> %% Bs2 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (7)) %%========================================================== + roundtrip('Bs2', []), roundtrip('Bs2', [mo,tu,fr]), bs_roundtrip('Bs2', <<2#0110010:7>>, [mo,tu,fr]), bs_roundtrip('Bs2', <<2#0110011:7>>, [mo,tu,fr,sa]), @@ -131,6 +132,7 @@ bit_string(Rules, Opts) -> %% Bs3 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (1..7)) %%========================================================== + roundtrip('Bs3', []), roundtrip('Bs3', [mo,tu,fr]), bs_roundtrip('Bs3', <<2#0110010:7>>, [mo,tu,fr]), bs_roundtrip('Bs3', <<2#0110010:7>>, [mo,tu,fr]), @@ -139,6 +141,13 @@ bit_string(Rules, Opts) -> bs_roundtrip('Bs3', <<2#11:2>>, [su,mo]), %%========================================================== + %% Bs4 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } + %%========================================================== + + roundtrip('Bs4', []), + roundtrip('Bs4', [mo,tu,fr,sa]), + + %%========================================================== %% Bs7 ::= BIT STRING (SIZE (24)) %%========================================================== diff --git a/lib/erl_docgen/priv/dtd/cites.dtd b/lib/erl_docgen/priv/dtd/cites.dtd index 73931af009..4558947db0 100644 --- a/lib/erl_docgen/priv/dtd/cites.dtd +++ b/lib/erl_docgen/priv/dtd/cites.dtd @@ -30,7 +30,7 @@ <!ELEMENT cite (id, shortdef, def, resp?) > <!ELEMENT id (#PCDATA) > <!ELEMENT shortdef (#PCDATA) > -<!ELEMENT def (#PCDATA|c|em)* > +<!ELEMENT def (#PCDATA|c|i|em)* > <!ELEMENT resp (#PCDATA) > <!ELEMENT c (#PCDATA) > <!ELEMENT em (#PCDATA|c)* > diff --git a/lib/erl_docgen/priv/dtd/common.dtd b/lib/erl_docgen/priv/dtd/common.dtd index ded16d308f..a29fc233fa 100644 --- a/lib/erl_docgen/priv/dtd/common.dtd +++ b/lib/erl_docgen/priv/dtd/common.dtd @@ -24,21 +24,23 @@ <!ENTITY % block "p|pre|code|list|taglist|codeinclude| erleval" > -<!ENTITY % inline "#PCDATA|c|em|term|cite|br|path|seealso| - url|marker" > +<!ENTITY % inline "#PCDATA|c|i|em|term|cite|br|path|seealso| + url|marker|anno" > <!-- XXX --> <!ELEMENT p (%inline;)* > -<!ELEMENT pre (#PCDATA|seealso|url|input)* > -<!ELEMENT input (#PCDATA|seealso|url)* > -<!ELEMENT code (#PCDATA) > +<!ELEMENT pre (#PCDATA|seealso|url|input|anno)* > +<!ELEMENT input (#PCDATA|seealso|url|anno)* > +<!ELEMENT code (#PCDATA|anno)* > <!ATTLIST code type (erl|c|none) "none" > <!ELEMENT quote (p)* > <!ELEMENT warning (%block;|quote|br|marker)* > <!ELEMENT note (%block;|quote|br|marker)* > <!ELEMENT dont (%block;|quote|br|marker)* > <!ELEMENT do (%block;|quote|br|marker)* > -<!ELEMENT c (#PCDATA) > -<!ELEMENT em (#PCDATA|c)* > +<!ELEMENT c (#PCDATA|anno)* > +<!ELEMENT i (#PCDATA|c|anno)* > +<!ELEMENT em (#PCDATA|c|anno)* > +<!ELEMENT anno (#PCDATA) > <!-- XXX --> <!ELEMENT term (termdef?) > @@ -64,13 +66,13 @@ <!ELEMENT list (item+) > <!ATTLIST list type (ordered|bulleted) "bulleted" > -<!ELEMENT taglist (tag,item)+ > -<!ELEMENT tag (#PCDATA|c|em|seealso|url|marker)* > +<!ELEMENT taglist (tag,item+)+ > +<!ELEMENT tag (#PCDATA|c|i|em|br|seealso|url|marker|anno)* > <!ELEMENT item (%inline;|%block;)* > <!-- References --> -<!ELEMENT seealso (#PCDATA|c|em)* > +<!ELEMENT seealso (#PCDATA|c|i|em|anno)* > <!ATTLIST seealso marker CDATA #REQUIRED > <!ELEMENT url (#PCDATA) > <!ATTLIST url href CDATA #REQUIRED > diff --git a/lib/erl_docgen/priv/dtd/common.header.dtd b/lib/erl_docgen/priv/dtd/common.header.dtd index 71a8662572..eb27dc8f97 100644 --- a/lib/erl_docgen/priv/dtd/common.header.dtd +++ b/lib/erl_docgen/priv/dtd/common.header.dtd @@ -18,8 +18,8 @@ $Id$ --> <!ELEMENT header (copyright?,legalnotice?,title,shorttitle?, - prepared,responsible?,docno,approved?, - checked?,date,rev,file?) > + prepared?,responsible?,docno?,approved?, + checked?,date?,rev?,file?) > <!-- The titlestyle attribute is only defined to make all the book.xml files diff --git a/lib/erl_docgen/priv/dtd/common.refs.dtd b/lib/erl_docgen/priv/dtd/common.refs.dtd index f57e46a624..6889e990de 100644 --- a/lib/erl_docgen/priv/dtd/common.refs.dtd +++ b/lib/erl_docgen/priv/dtd/common.refs.dtd @@ -27,15 +27,16 @@ <!ELEMENT description (%block;|quote|br|marker|warning|note|dont|do)* > <!ELEMENT funcs (func)+ > -<!ELEMENT func (name+,type_desc*,fsummary,type?,desc?) > +<!ELEMENT func (name+,fsummary,(type|type_desc)*,desc?) > <!-- ELEMENT name is defined in each ref dtd --> -<!ELEMENT fsummary (#PCDATA|c|em)* > +<!ELEMENT fsummary (#PCDATA|c|i|em|anno)* > <!ELEMENT type (v,d?)* > <!ATTLIST type variable CDATA #IMPLIED + name CDATA #IMPLIED name_i CDATA #IMPLIED> -<!ELEMENT v (#PCDATA) > -<!ELEMENT d (#PCDATA|c|em)* > -<!ELEMENT desc (%block;|quote|br|marker|warning|note|dont|do|anno)* > +<!ELEMENT v (#PCDATA|seealso)* > +<!ELEMENT d (#PCDATA|c|i|em)* > +<!ELEMENT desc (%block;|quote|br|marker|warning|note|dont|do)* > <!ELEMENT authors (aname,email)+ > <!ELEMENT aname (#PCDATA) > <!ELEMENT email (#PCDATA) > @@ -43,5 +44,6 @@ warning|note|dont|do)*) > <!ELEMENT datatypes (datatype)+ > <!ELEMENT datatype (name+,desc?) > -<!ELEMENT type_desc (#PCDATA) > -<!ATTLIST type_desc variable CDATA #REQUIRED> +<!ELEMENT type_desc (#PCDATA|anno|c|seealso)* > +<!ATTLIST type_desc variable CDATA #IMPLIED + name CDATA #IMPLIED> diff --git a/lib/erl_docgen/priv/dtd/erlref.dtd b/lib/erl_docgen/priv/dtd/erlref.dtd index d62e2a5fcb..835407520a 100644 --- a/lib/erl_docgen/priv/dtd/erlref.dtd +++ b/lib/erl_docgen/priv/dtd/erlref.dtd @@ -32,4 +32,5 @@ <!ELEMENT name (#PCDATA) > <!ATTLIST name name CDATA #IMPLIED arity CDATA #IMPLIED - clause_i CDATA #IMPLIED> + clause_i CDATA #IMPLIED + n_vars CDATA #IMPLIED> diff --git a/lib/erl_docgen/priv/dtd/terms.dtd b/lib/erl_docgen/priv/dtd/terms.dtd index fd160b5c02..c2965eb61c 100644 --- a/lib/erl_docgen/priv/dtd/terms.dtd +++ b/lib/erl_docgen/priv/dtd/terms.dtd @@ -30,7 +30,7 @@ <!ELEMENT term (id, shortdef, def, resp?) > <!ELEMENT id (#PCDATA) > <!ELEMENT shortdef (#PCDATA) > -<!ELEMENT def (#PCDATA|c|em)* > +<!ELEMENT def (#PCDATA|c|i|em)* > <!ELEMENT resp (#PCDATA) > <!ELEMENT c (#PCDATA) > <!ELEMENT em (#PCDATA|c)* > diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl index f5ddd364d3..c2325fbee9 100644 --- a/lib/erl_docgen/priv/xsl/db_html.xsl +++ b/lib/erl_docgen/priv/xsl/db_html.xsl @@ -990,12 +990,15 @@ </p> </xsl:template> - <!-- Inline elements --> <xsl:template match="b"> <strong><xsl:apply-templates/></strong> </xsl:template> + <xsl:template match="i"> + <i><xsl:apply-templates/></i> + </xsl:template> + <xsl:template match="br"> <br/> </xsl:template> diff --git a/lib/erl_docgen/priv/xsl/db_man.xsl b/lib/erl_docgen/priv/xsl/db_man.xsl index 120bf9880d..5201465e42 100644 --- a/lib/erl_docgen/priv/xsl/db_man.xsl +++ b/lib/erl_docgen/priv/xsl/db_man.xsl @@ -595,6 +595,12 @@ <xsl:text>\fR\& </xsl:text> </xsl:template> + <xsl:template match="i"> + <xsl:text>\fI</xsl:text> + <xsl:apply-templates/> + <xsl:text>\fR\& </xsl:text> + </xsl:template> + <xsl:template match="br"> <xsl:choose> <xsl:when test="ancestor::head"> diff --git a/lib/erl_docgen/priv/xsl/db_pdf.xsl b/lib/erl_docgen/priv/xsl/db_pdf.xsl index 53e202d52c..37a2d55274 100644 --- a/lib/erl_docgen/priv/xsl/db_pdf.xsl +++ b/lib/erl_docgen/priv/xsl/db_pdf.xsl @@ -1186,6 +1186,12 @@ </fo:inline> </xsl:template> + <xsl:template match="i"> + <fo:inline font-weight="italic"> + <xsl:apply-templates/> + </fo:inline> + </xsl:template> + <xsl:template match="br"> <fo:block/> </xsl:template> diff --git a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl index 03fc161c5a..0ac7985a48 100644 --- a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl +++ b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2012. All Rights Reserved. +%% Copyright Ericsson AB 2001-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -352,8 +352,8 @@ otp_xmlify_e(#xmlElement{name=code} = E) -> % 4) end; otp_xmlify_e(#xmlElement{name=Tag} = E) % 5a when Tag==h1; Tag==h2; Tag==h3; Tag==h4; Tag==h5 -> - Content = text_and_a_name_only(E#xmlElement.content), - [E#xmlElement{name=b, content=Content}]; + {Name, Text} = text_and_a_name_only(E#xmlElement.content), + [Name, E#xmlElement{name=b, content=Text}]; otp_xmlify_e(#xmlElement{name=Tag} = E) % 5b-c) when Tag==center; Tag==font -> @@ -1190,17 +1190,13 @@ get_text(#xmlElement{content=[#xmlText{value=Text}]}) -> get_text(#xmlElement{content=[E]}) -> get_text(E). -%% text_and_name_only(Es) -> Ts -text_and_a_name_only([#xmlElement{ - name = a, - attributes = [#xmlAttribute{name=name}]} = Name|Es]) -> - [Name|text_and_a_name_only(Es)]; -text_and_a_name_only([#xmlElement{content = Content}|Es]) -> - text_and_a_name_only(Content) ++ text_and_a_name_only(Es); -text_and_a_name_only([#xmlText{} = E |Es]) -> - [E | text_and_a_name_only(Es)]; -text_and_a_name_only([]) -> - []. +%% text_and_name_only(Es) -> {N, Ts} +text_and_a_name_only(Es) -> + [Name|_] = [Name || + #xmlElement{ + name = a, + attributes = [#xmlAttribute{name=name}]}=Name <- Es], + {Name#xmlElement{content = []}, text_only(Es)}. %% text_only(Es) -> Ts %% Takes a list of xmlElement and xmlText and return a lists of xmlText. diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk index 2abd3d2b7e..43f5a570d7 100644 --- a/lib/erl_docgen/vsn.mk +++ b/lib/erl_docgen/vsn.mk @@ -1 +1 @@ -ERL_DOCGEN_VSN = 0.4 +ERL_DOCGEN_VSN = 0.4.1 diff --git a/lib/eunit/include/eunit.hrl b/lib/eunit/include/eunit.hrl index 88e9d6c19b..8f678b0290 100644 --- a/lib/eunit/include/eunit.hrl +++ b/lib/eunit/include/eunit.hrl @@ -135,7 +135,6 @@ -define(_assertThrow(Term, Expr), ?_assertException(throw, Term, Expr)). -define(_assertNotException(Class, Term, Expr), ?_test(?assertNotException(Class, Term, Expr))). --define(_assertReceive(Guard, Expr), ?_test(?assertReceive(Guard, Expr))). %% Macros for running operating system commands. (Note that these %% require EUnit to be present at runtime, or at least eunit_lib.) diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 268a8404f1..d02c3e8ad2 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -185,6 +185,22 @@ </section> +<section><title>Kernel 3.2.0.1</title> + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>The 'raw' socket option could not be used multiple times + in one call to any e.g gen_tcp function because only one + of the occurrences were used. This bug has been fixed, + and also a small bug concerning propagating error codes + from within inet:setopts/2.</p> + <p>Own Id: OTP-11482 Aux Id: seq12872 </p> + </item> + </list> + </section> + </section> + + <section><title>Kernel 3.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index 855c6377a3..b573112445 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -692,6 +692,7 @@ connect_options(Opts, Family) -> case con_opt(Opts, BaseOpts, connect_options()) of {ok, R} -> {ok, R#connect_opts { + opts = lists:reverse(R#connect_opts.opts), ifaddr = translate_ip(R#connect_opts.ifaddr, Family) }}; Error -> Error @@ -762,6 +763,7 @@ listen_options(Opts, Family) -> case list_opt(Opts, BaseOpts, listen_options()) of {ok, R} -> {ok, R#listen_opts { + opts = lists:reverse(R#listen_opts.opts), ifaddr = translate_ip(R#listen_opts.ifaddr, Family) }}; Error -> Error @@ -820,6 +822,7 @@ udp_options(Opts, Family) -> case udp_opt(Opts, #udp_opts { }, udp_options()) of {ok, R} -> {ok, R#udp_opts { + opts = lists:reverse(R#udp_opts.opts), ifaddr = translate_ip(R#udp_opts.ifaddr, Family) }}; Error -> Error @@ -893,9 +896,12 @@ sctp_options() -> sctp_options(Opts, Mod) -> case sctp_opt(Opts, Mod, #sctp_opts{}, sctp_options()) of {ok,#sctp_opts{ifaddr=undefined}=SO} -> - {ok,SO#sctp_opts{ifaddr=Mod:translate_ip(?SCTP_DEF_IFADDR)}}; - {ok,_}=OK -> - OK; + {ok, + SO#sctp_opts{ + opts=lists:reverse(SO#sctp_opts.opts), + ifaddr=Mod:translate_ip(?SCTP_DEF_IFADDR)}}; + {ok,SO} -> + {ok,SO#sctp_opts{opts=lists:reverse(SO#sctp_opts.opts)}}; Error -> Error end. @@ -967,6 +973,8 @@ add_opt(Name, Val, Opts, As) -> case lists:member(Name, As) of true -> case prim_inet:is_sockopt_val(Name, Val) of + true when Name =:= raw -> + {ok, [{Name,Val} | Opts]}; true -> Opts1 = lists:keydelete(Name, 1, Opts), {ok, [{Name,Val} | Opts1]}; diff --git a/lib/kernel/test/inet_sockopt_SUITE.erl b/lib/kernel/test/inet_sockopt_SUITE.erl index 1262f36fae..cb522c8abe 100644 --- a/lib/kernel/test/inet_sockopt_SUITE.erl +++ b/lib/kernel/test/inet_sockopt_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2013. All Rights Reserved. +%% Copyright Ericsson AB 2007-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -52,6 +52,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, simple/1, loop_all/1, simple_raw/1, simple_raw_getbin/1, + multiple_raw/1, multiple_raw_getbin/1, doc_examples_raw/1,doc_examples_raw_getbin/1, large_raw/1,large_raw_getbin/1,combined/1,combined_getbin/1, ipv6_v6only_udp/1, ipv6_v6only_tcp/1, ipv6_v6only_sctp/1, @@ -65,6 +66,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [simple, loop_all, simple_raw, simple_raw_getbin, + multiple_raw, multiple_raw_getbin, doc_examples_raw, doc_examples_raw_getbin, large_raw, large_raw_getbin, combined, combined_getbin, ipv6_v6only_udp, ipv6_v6only_tcp, ipv6_v6only_sctp, @@ -185,6 +187,84 @@ nintbin2int(<<Int:16/native>>) -> Int; nintbin2int(<<Int:8/native>>) -> Int; nintbin2int(<<>>) -> 0. + + +multiple_raw(suite) -> []; +multiple_raw(doc) -> "Test setopt/getopt of multiple raw options."; +multiple_raw(Config) when is_list(Config) -> + do_multiple_raw(Config,false). +multiple_raw_getbin(suite) -> []; +multiple_raw_getbin(doc) -> "Test setopt/getopt of multiple raw options, " + "with binaries in getopt."; +multiple_raw_getbin(Config) when is_list(Config) -> + do_multiple_raw(Config,true). + +do_multiple_raw(Config, Binary) -> + Port = start_helper(Config), + SolSocket = ask_helper(Port, ?C_GET_SOL_SOCKET), + SoKeepalive = ask_helper(Port, ?C_GET_SO_KEEPALIVE), + SoKeepaliveTrue = {raw,SolSocket,SoKeepalive,<<1:32/native>>}, + SoKeepaliveFalse = {raw,SolSocket,SoKeepalive,<<0:32/native>>}, + SoReuseaddr = ask_helper(Port, ?C_GET_SO_REUSEADDR), + SoReuseaddrTrue = {raw,SolSocket,SoReuseaddr,<<1:32/native>>}, + SoReuseaddrFalse = {raw,SolSocket,SoReuseaddr,<<0:32/native>>}, + {S1,S2} = + create_socketpair( + [SoReuseaddrFalse,SoKeepaliveTrue], + [SoKeepaliveFalse,SoReuseaddrTrue]), + {ok,[{reuseaddr,false},{keepalive,true}]} = + inet:getopts(S1, [reuseaddr,keepalive]), + {ok, + [{raw,SolSocket,SoReuseaddr,S1R1}, + {raw,SolSocket,SoKeepalive,S1K1}]} = + inet:getopts( + S1, + [{raw,SolSocket,SoReuseaddr,binarify(4, Binary)}, + {raw,SolSocket,SoKeepalive,binarify(4, Binary)}]), + true = nintbin2int(S1R1) =:= 0, + true = nintbin2int(S1K1) =/= 0, + {ok,[{keepalive,false},{reuseaddr,true}]} = + inet:getopts(S2, [keepalive,reuseaddr]), + {ok, + [{raw,SolSocket,SoKeepalive,S2K1}, + {raw,SolSocket,SoReuseaddr,S2R1}]} = + inet:getopts( + S2, + [{raw,SolSocket,SoKeepalive,binarify(4, Binary)}, + {raw,SolSocket,SoReuseaddr,binarify(4, Binary)}]), + true = nintbin2int(S2K1) =:= 0, + true = nintbin2int(S2R1) =/= 0, + %% + ok = inet:setopts( + S1, [SoReuseaddrTrue,SoKeepaliveFalse]), + ok = inet:setopts( + S2, [SoKeepaliveTrue,SoReuseaddrFalse]), + {ok, + [{raw,SolSocket,SoReuseaddr,S1R2}, + {raw,SolSocket,SoKeepalive,S1K2}]} = + inet:getopts( + S1, + [{raw,SolSocket,SoReuseaddr,binarify(4, Binary)}, + {raw,SolSocket,SoKeepalive,binarify(4, Binary)}]), + true = nintbin2int(S1R2) =/= 0, + true = nintbin2int(S1K2) =:= 0, + {ok, + [{raw,SolSocket,SoKeepalive,S2K2}, + {raw,SolSocket,SoReuseaddr,S2R2}]} = + inet:getopts( + S2, + [{raw,SolSocket,SoKeepalive,binarify(4, Binary)}, + {raw,SolSocket,SoReuseaddr,binarify(4, Binary)}]), + true = nintbin2int(S2K2) =/= 0, + true = nintbin2int(S2R2) =:= 0, + %% + gen_tcp:close(S1), + gen_tcp:close(S2), + stop_helper(Port), + ok. + + + doc_examples_raw(suite) -> []; doc_examples_raw(doc) -> "Test that the example code from the documentation " "works"; diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index 6faa3d5f9a..4d4a219b4f 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -26,8 +26,9 @@ <file>notes.xml</file> </header> <p>This document describes the changes made to the SSL application.</p> - <section><title>SSL 7.1</title> + +<section><title>SSL 7.1</title> <section><title>Fixed Bugs and Malfunctions</title> <list> <item> @@ -107,12 +108,6 @@ <p> Own Id: OTP-12815</p> </item> - <item> - <p> - Gracefully ignore proprietary hash_sign algorithms</p> - <p> - Own Id: OTP-12829</p> - </item> </list> </section> @@ -163,6 +158,20 @@ </section> +<section><title>SSL 6.0.1.1</title> + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Gracefully ignore proprietary hash_sign algorithms</p> + <p> + Own Id: OTP-12829</p> + </item> + </list> + </section> +</section> + + <section><title>SSL 6.0.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index c4cb5fdc80..5678e7eebe 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -293,6 +293,9 @@ format_error({variable_in_record_def,V}) -> %% --- binaries --- format_error({undefined_bittype,Type}) -> io_lib:format("bit type ~w undefined", [Type]); +format_error({bittype_mismatch,Val1,Val2,What}) -> + io_lib:format("conflict in ~s specification for bit field: '~p' and '~p'", + [What,Val1,Val2]); format_error(bittype_unit) -> "a bit unit size must not be specified unless a size is specified too"; format_error(illegal_bitsize) -> diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl index f7a969977a..c5177aca90 100644 --- a/lib/stdlib/src/erl_pp.erl +++ b/lib/stdlib/src/erl_pp.erl @@ -253,6 +253,8 @@ lattribute(import, Name, _Opts, _State) when is_list(Name) -> attr("import", [{var,a0(),pname(Name)}]); lattribute(import, {From,Falist}, _Opts, _State) -> attr("import",[{var,a0(),pname(From)},falist(Falist)]); +lattribute(export_type, Talist, _Opts, _State) -> + call({var,a0(),"-export_type"}, [falist(Talist)], 0, options(none)); lattribute(optional_callbacks, Falist, Opts, _State) -> ArgL = try falist(Falist) catch _:_ -> abstract(Falist, Opts) @@ -321,7 +323,6 @@ ltype({type,_,'fun',[{type,_,any},_]}=FunType, _) -> ltype({type,_Line,'fun',[{type,_,product,_},_]}=FunType, _) -> [fun_type(['fun',$(], FunType),$)]; ltype({type,Line,T,Ts}, _) -> - %% Compatibility. Before 18.0. simple_type({atom,Line,T}, Ts); ltype({user_type,Line,T,Ts}, _) -> simple_type({atom,Line,T}, Ts); @@ -346,16 +347,8 @@ map_type(Fs) -> map_pair_types(Fs) -> tuple_type(Fs, fun map_pair_type/2). -map_pair_type({type,_Line,map_field_assoc,[Ktype,Vtype]}, Prec) -> - map_assoc_typed(ltype(Ktype), Vtype, Prec). - -map_assoc_typed(B, {type,_,union,Ts}, Prec) -> - {first,[B,$\s],{seq,[],[],[],map_assoc_union_type(Ts, Prec)}}; -map_assoc_typed(B, Type, Prec) -> - {list,[{cstep,[B," =>"],ltype(Type, Prec)}]}. - -map_assoc_union_type([T|Ts], Prec) -> - [[leaf("=> "),ltype(T)] | ltypes(Ts, fun union_elem/2, Prec)]. +map_pair_type({type,_Line,map_field_assoc,[KType,VType]}, Prec) -> + {list,[{cstep,[ltype(KType, Prec),leaf(" =>")],ltype(VType, Prec)}]}. record_type(Name, Fields) -> {first,[record_name(Name)],field_types(Fields)}. @@ -370,9 +363,6 @@ typed(B, Type) -> {_L,_P,R} = type_inop_prec('::'), {list,[{cstep,[B,' ::'],ltype(Type, R)}]}. -union_elem(T, Prec) -> - [leaf(" | "),ltype(T, Prec)]. - tuple_type(Ts, F) -> {seq,${,$},[$,],ltypes(Ts, F, 0)}. @@ -399,6 +389,9 @@ guard_type(Before, Gs) -> Gl = {list,[{step,'when',expr_list(Gs, [$,], fun constraint/2, Opts)}]}, {list,[{step,Before,Gl}]}. +constraint({type,_Line,constraint,[{atom,_,is_subtype},[{var,_,_}=V,Type]]}, + _Opts) -> + typed(lexpr(V, options(none)), Type); constraint({type,_Line,constraint,[Tag,As]}, _Opts) -> simple_type(Tag, As). diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 0424e2b967..5347ccaf1f 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -3604,7 +3604,10 @@ bin_syntax_errors(Config) -> t(<<X/unit:8>>) -> X; t(<<X:7/float>>) -> X; t(<< <<_:8>> >>) -> ok; - t(<<(x ! y):8/integer>>) -> ok. + t(<<(x ! y):8/integer>>) -> ok; + t(X) -> + {<<X/binary-integer>>,<<X/signed-unsigned-integer>>, + <<X/little-big>>,<<X/unit:4-unit:8>>}. ">>, [], {error,[{1,erl_lint,illegal_bitsize}, @@ -3613,7 +3616,12 @@ bin_syntax_errors(Config) -> {4,erl_lint,{undefined_bittype,bad_type}}, {5,erl_lint,bittype_unit}, {7,erl_lint,illegal_pattern}, - {8,erl_lint,illegal_pattern}], + {8,erl_lint,illegal_pattern}, + {10,erl_lint,{bittype_mismatch,integer,binary,"type"}}, + {10,erl_lint,{bittype_mismatch,unsigned,signed,"sign"}}, + {11,erl_lint,{bittype_mismatch,8,4,"unit"}}, + {11,erl_lint,{bittype_mismatch,big,little,"endianness"}} + ], [{6,erl_lint,{bad_bitsize,"float"}}]}} ], [] = run(Config, Ts), @@ -3920,22 +3928,35 @@ run_test2(Conf, Test, Warnings0) -> %% is no reason to produce an output file since we are only %% interested in the errors and warnings. - %% Print warnings, call erl_lint:format_error/1. + %% Print warnings, call erl_lint:format_error/1. (But note that + %% the compiler will ignore failing calls to erl_lint:format_error/1.) compile:file(File, [binary,report|Opts]), case compile:file(File, [binary|Opts]) of - {ok, _M, Code, Ws} when is_binary(Code) -> warnings(File, Ws); - {error, [{File,Es}], []} -> {errors, Es, []}; - {error, [{File,Es}], [{File,Ws}]} -> {error, Es, Ws}; - {error, [{File,Es1},{File,Es2}], []} -> {errors2, Es1, Es2} + {ok, _M, Code, Ws} when is_binary(Code) -> + warnings(File, Ws); + {error, [{File,Es}], []} -> + {errors, call_format_error(Es), []}; + {error, [{File,Es}], [{File,Ws}]} -> + {error, call_format_error(Es), call_format_error(Ws)}; + {error, [{File,Es1},{File,Es2}], []} -> + {errors2, Es1, Es2} end. warnings(File, Ws) -> case lists:append([W || {F, W} <- Ws, F =:= File]) of - [] -> []; - L -> {warnings, L} + [] -> + []; + L -> + {warnings, call_format_error(L)} end. +call_format_error(L) -> + %% Smoke test of format_error/1 to make sure that no crashes + %% slip through. + _ = [Mod:format_error(Term) || {_,Mod,Term} <- L], + L. + fail() -> io:format("failed~n"), ?t:fail(). diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl index 389fd059f6..92e2764c65 100644 --- a/lib/stdlib/test/erl_pp_SUITE.erl +++ b/lib/stdlib/test/erl_pp_SUITE.erl @@ -960,6 +960,9 @@ maps_syntax(Config) when is_list(Config) -> "-compile(export_all).\n" "-type t1() :: map().\n" "-type t2() :: #{ atom() => integer(), atom() => float() }.\n" + "-type u() :: #{a => (I :: integer()) | (A :: atom()),\n" + " (X :: atom()) | (Y :: atom()) =>\n" + " (I :: integer()) | (A :: atom())}.\n" "-spec f1(t1()) -> 'true'.\n" "f1(M) when is_map(M) -> true.\n" "-spec f2(t2()) -> integer().\n" diff --git a/lib/wx/api_gen/gl_gen_erl.erl b/lib/wx/api_gen/gl_gen_erl.erl index 20406a8d05..84e9600bc0 100644 --- a/lib/wx/api_gen/gl_gen_erl.erl +++ b/lib/wx/api_gen/gl_gen_erl.erl @@ -226,10 +226,14 @@ gen_types(Where) -> w("-type clamp() :: float(). %% 0.0..1.0~n", []), w("-type offset() :: non_neg_integer(). %% Offset in memory block~n", []) end, - w("-type matrix() :: {float(),float(),float(),float(),~n", []), + w("-type matrix12() :: {float(),float(),float(),float(),~n", []), + w(" float(),float(),float(),float(),~n", []), + w(" float(),float(),float(),float()}.~n", []), + w("-type matrix16() :: {float(),float(),float(),float(),~n", []), w(" float(),float(),float(),float(),~n", []), w(" float(),float(),float(),float(),~n", []), w(" float(),float(),float(),float()}.~n", []), + w("-type matrix() :: matrix12() | matrix16().~n", []), w("-type mem() :: binary() | tuple(). %% Memory block~n", []), ok. @@ -480,10 +484,12 @@ doc_arg_type2(T=#type{single=true}) -> doc_arg_type3(T); doc_arg_type2(T=#type{single=undefined}) -> doc_arg_type3(T); -doc_arg_type2(T=#type{single={tuple,undefined}}) -> - "{" ++ doc_arg_type3(T) ++ "}"; +doc_arg_type2(_T=#type{single={tuple,undefined}}) -> + "tuple()"; doc_arg_type2(#type{base=float, single={tuple,16}}) -> "matrix()"; +doc_arg_type2(#type{base=string, single=list}) -> + "iolist()"; doc_arg_type2(T=#type{single={tuple,Sz}}) -> "{" ++ args(fun doc_arg_type3/1, ",", lists:duplicate(Sz,T)) ++ "}"; doc_arg_type2(T=#type{single=list}) -> diff --git a/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src b/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src index 5e02066309..08fef1c2ff 100644 --- a/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src +++ b/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src @@ -42,11 +42,15 @@ case 101: { // wxEvtHandler::Disconnect int eventType = wxeEventTypeFromAtom(bp); bp += *eventTypeLen; if(eventType > 0) { + if(recurse_level > 1) { + delayed_delete->Append(Ecmd.Save()); + } else { bool Result = This->Disconnect((int) *winid,(int) *lastId,eventType, (wxObjectEventFunction)(wxEventFunction) &wxeEvtListener::forward, NULL, Listener); rt.addBool(Result); + } } else { rt.addAtom("badarg"); rt.addAtom("event_type"); diff --git a/lib/wx/api_gen/wx_gen_cpp.erl b/lib/wx/api_gen/wx_gen_cpp.erl index 5649336b5d..ed7b27f3bf 100644 --- a/lib/wx/api_gen/wx_gen_cpp.erl +++ b/lib/wx/api_gen/wx_gen_cpp.erl @@ -1141,6 +1141,7 @@ gen_macros() -> w("#include <wx/html/htmlcell.h>~n"), w("#include <wx/filename.h>~n"), w("#include <wx/sysopt.h>~n"), + w("#include <wx/overlay.h>~n"), w("~n~n", []), w("#ifndef wxICON_DEFAULT_BITMAP_TYPE~n",[]), @@ -1276,6 +1277,11 @@ encode_events(Evs) -> w(" } else {~n"), w(" send_res = rt.send();~n"), w(" if(cb->skip) event->Skip();~n"), + w(" if(app->recurse_level < 1) {~n"), + w(" app->recurse_level++;~n"), + w(" app->dispatch_cmds();~n"), + w(" app->recurse_level--;~n"), + w(" }~n"), w(" };~n"), w(" return send_res;~n"), w(" }~n"). diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf index f076323bea..eabbec3297 100644 --- a/lib/wx/api_gen/wxapi.conf +++ b/lib/wx/api_gen/wxapi.conf @@ -367,7 +367,7 @@ {class,wxMirrorDC, wxDC, [], ['wxMirrorDC', '~wxMirrorDC']}. {class,wxScreenDC, wxDC, [], ['wxScreenDC', '~wxScreenDC']}. -{class,wxPostScriptDC,wxDC,[], +{class,wxPostScriptDC,wxDC,[{ifdef, wxUSE_POSTSCRIPT}], ['wxPostScriptDC','~wxPostScriptDC', {'SetResolution', [{deprecated, "!wxCHECK_VERSION(2,9,0)"}]}, {'GetResolution', [{deprecated, "!wxCHECK_VERSION(2,9,0)"}]}]}. @@ -1975,3 +1975,9 @@ {class, wxMouseCaptureLostEvent, wxEvent, [{event,[wxEVT_MOUSE_CAPTURE_LOST]}],[]}. + +{class, wxOverlay, root, [], + ['wxOverlay', '~wxOverlay', 'Reset']}. + +{class, wxDCOverlay, root, [], + ['wxDCOverlay', '~wxDCOverlay', 'Clear']}. diff --git a/lib/wx/c_src/gen/wxe_derived_dest.h b/lib/wx/c_src/gen/wxe_derived_dest.h index 03d1502c2a..1dcf029244 100644 --- a/lib/wx/c_src/gen/wxe_derived_dest.h +++ b/lib/wx/c_src/gen/wxe_derived_dest.h @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2008-2014. All Rights Reserved. + * Copyright Ericsson AB 2008-2015. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -86,11 +86,13 @@ class EwxScreenDC : public wxScreenDC { EwxScreenDC() : wxScreenDC() {}; }; +#if wxUSE_POSTSCRIPT class EwxPostScriptDC : public wxPostScriptDC { public: ~EwxPostScriptDC() {((WxeApp *)wxTheApp)->clearPtr(this);}; EwxPostScriptDC(const wxPrintData& printData) : wxPostScriptDC(printData) {}; EwxPostScriptDC() : wxPostScriptDC() {}; }; +#endif // wxUSE_POSTSCRIPT class EwxWindowDC : public wxWindowDC { public: ~EwxWindowDC() {((WxeApp *)wxTheApp)->clearPtr(this);}; @@ -787,3 +789,9 @@ class EwxPopupTransientWindow : public wxPopupTransientWindow { }; #endif // wxUSE_POPUPWIN +class EwxDCOverlay : public wxDCOverlay { + public: ~EwxDCOverlay() {((WxeApp *)wxTheApp)->clearPtr(this);}; + EwxDCOverlay(wxOverlay& overlay,wxWindowDC * dc,int x,int y,int width,int height) : wxDCOverlay(overlay,dc,x,y,width,height) {}; + EwxDCOverlay(wxOverlay& overlay,wxWindowDC * dc) : wxDCOverlay(overlay,dc) {}; +}; + diff --git a/lib/wx/c_src/gen/wxe_events.cpp b/lib/wx/c_src/gen/wxe_events.cpp index a532ee985d..4affe2ba53 100644 --- a/lib/wx/c_src/gen/wxe_events.cpp +++ b/lib/wx/c_src/gen/wxe_events.cpp @@ -897,6 +897,11 @@ case 235: {// wxMouseCaptureLostEvent } else { send_res = rt.send(); if(cb->skip) event->Skip(); + if(app->recurse_level < 1) { + app->recurse_level++; + app->dispatch_cmds(); + app->recurse_level--; + } }; return send_res; } diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp index 3211664499..4025fb1c16 100644 --- a/lib/wx/c_src/gen/wxe_funcs.cpp +++ b/lib/wx/c_src/gen/wxe_funcs.cpp @@ -113,11 +113,15 @@ case 101: { // wxEvtHandler::Disconnect int eventType = wxeEventTypeFromAtom(bp); bp += *eventTypeLen; if(eventType > 0) { + if(recurse_level > 1) { + delayed_delete->Append(Ecmd.Save()); + } else { bool Result = This->Disconnect((int) *winid,(int) *lastId,eventType, (wxObjectEventFunction)(wxEventFunction) &wxeEvtListener::forward, NULL, Listener); rt.addBool(Result); + } } else { rt.addAtom("badarg"); rt.addAtom("event_type"); @@ -5856,6 +5860,7 @@ case wxScreenDC_new: { // wxScreenDC::wxScreenDC rt.addRef(getRef((void *)Result,memenv), "wxScreenDC"); break; } +#if wxUSE_POSTSCRIPT case wxPostScriptDC_new_0: { // wxPostScriptDC::wxPostScriptDC wxPostScriptDC * Result = new EwxPostScriptDC(); newPtr((void *) Result, 4, memenv); @@ -5883,6 +5888,7 @@ case wxPostScriptDC_GetResolution: { // wxPostScriptDC::GetResolution break; } #endif +#endif // wxUSE_POSTSCRIPT #if !wxCHECK_VERSION(2,9,0) case wxWindowDC_new_0: { // wxWindowDC::wxWindowDC wxWindowDC * Result = new EwxWindowDC(); @@ -31959,6 +31965,56 @@ case wxPopupTransientWindow_Dismiss: { // wxPopupTransientWindow::Dismiss break; } #endif // wxUSE_POPUPWIN +case wxOverlay_new: { // wxOverlay::wxOverlay + wxOverlay * Result = new wxOverlay(); + newPtr((void *) Result, 236, memenv); + rt.addRef(getRef((void *)Result,memenv), "wxOverlay"); + break; +} +case wxOverlay_destruct: { // wxOverlay::~wxOverlay + wxOverlay *This = (wxOverlay *) getPtr(bp,memenv); bp += 4; + if(This) { ((WxeApp *) wxTheApp)->clearPtr((void *) This); + delete This;} + break; +} +case wxOverlay_Reset: { // wxOverlay::Reset + wxOverlay *This = (wxOverlay *) getPtr(bp,memenv); bp += 4; + if(!This) throw wxe_badarg(0); + This->Reset(); + break; +} +case wxDCOverlay_new_6: { // wxDCOverlay::wxDCOverlay + wxOverlay *overlay = (wxOverlay *) getPtr(bp,memenv); bp += 4; + wxWindowDC *dc = (wxWindowDC *) getPtr(bp,memenv); bp += 4; + int * x = (int *) bp; bp += 4; + int * y = (int *) bp; bp += 4; + int * width = (int *) bp; bp += 4; + int * height = (int *) bp; bp += 4; + wxDCOverlay * Result = new EwxDCOverlay(*overlay,dc,*x,*y,*width,*height); + newPtr((void *) Result, 237, memenv); + rt.addRef(getRef((void *)Result,memenv), "wxDCOverlay"); + break; +} +case wxDCOverlay_new_2: { // wxDCOverlay::wxDCOverlay + wxOverlay *overlay = (wxOverlay *) getPtr(bp,memenv); bp += 4; + wxWindowDC *dc = (wxWindowDC *) getPtr(bp,memenv); bp += 4; + wxDCOverlay * Result = new EwxDCOverlay(*overlay,dc); + newPtr((void *) Result, 237, memenv); + rt.addRef(getRef((void *)Result,memenv), "wxDCOverlay"); + break; +} +case wxDCOverlay_destruct: { // wxDCOverlay::~wxDCOverlay + wxDCOverlay *This = (wxDCOverlay *) getPtr(bp,memenv); bp += 4; + if(This) { ((WxeApp *) wxTheApp)->clearPtr((void *) This); + delete This;} + break; +} +case wxDCOverlay_Clear: { // wxDCOverlay::Clear + wxDCOverlay *This = (wxDCOverlay *) getPtr(bp,memenv); bp += 4; + if(!This) throw wxe_badarg(0); + This->Clear(); + break; +} default: { wxeReturn error = wxeReturn(WXE_DRV_PORT, Ecmd.caller, false); error.addAtom("_wxe_error_"); error.addInt((int) Ecmd.op); @@ -32005,6 +32061,8 @@ bool WxeApp::delete_object(void *ptr, wxeRefData *refd) { case 215: /* delete (wxBitmapDataObject *) ptr;These objects must be deleted by owner object */ break; case 227: delete (wxLogNull *) ptr; break; case 231: delete (EwxLocale *) ptr; return false; + case 236: delete (wxOverlay *) ptr; break; + case 237: delete (EwxDCOverlay *) ptr; return false; default: delete (wxObject *) ptr; return false; } return true; diff --git a/lib/wx/c_src/gen/wxe_macros.h b/lib/wx/c_src/gen/wxe_macros.h index 59f9c7054e..5f51ac5f91 100644 --- a/lib/wx/c_src/gen/wxe_macros.h +++ b/lib/wx/c_src/gen/wxe_macros.h @@ -64,6 +64,7 @@ #include <wx/html/htmlcell.h> #include <wx/filename.h> #include <wx/sysopt.h> +#include <wx/overlay.h> #ifndef wxICON_DEFAULT_BITMAP_TYPE @@ -3411,5 +3412,12 @@ #define wxPopupTransientWindow_destruct 3583 #define wxPopupTransientWindow_Popup 3584 #define wxPopupTransientWindow_Dismiss 3585 +#define wxOverlay_new 3586 +#define wxOverlay_destruct 3587 +#define wxOverlay_Reset 3588 +#define wxDCOverlay_new_6 3589 +#define wxDCOverlay_new_2 3590 +#define wxDCOverlay_destruct 3591 +#define wxDCOverlay_Clear 3592 diff --git a/lib/wx/c_src/wxe_helpers.cpp b/lib/wx/c_src/wxe_helpers.cpp index cc57374d5b..1696b8bd50 100644 --- a/lib/wx/c_src/wxe_helpers.cpp +++ b/lib/wx/c_src/wxe_helpers.cpp @@ -61,6 +61,7 @@ wxeFifo::wxeFifo(unsigned int sz) m_max = sz; m_n = 0; m_first = 0; + cb_start = 0; m_old = NULL; for(unsigned int i = 0; i < sz; i++) { m_q[i].buffer = NULL; @@ -76,15 +77,30 @@ wxeFifo::~wxeFifo() { wxeCommand * wxeFifo::Get() { unsigned int pos; - if(m_n > 0) { + do { + if(m_n <= 0) + return NULL; + pos = m_first++; m_n--; m_first %= m_max; - return &m_q[pos]; - } - return NULL; + } while(m_q[pos].op == -1); + return &m_q[pos]; +} + +wxeCommand * wxeFifo::Peek(unsigned int *i) +{ + unsigned int pos; + do { + if(*i >= m_n || m_n <= 0) + return NULL; + pos = (m_first+*i) % m_max; + (*i)++; + } while(m_q[pos].op == -1); + return &m_q[pos]; } + void wxeFifo::Add(int fc, char * cbuf,int buflen, wxe_data *sd) { unsigned int pos; @@ -140,10 +156,12 @@ void wxeFifo::Append(wxeCommand *orig) pos = (m_first + m_n) % m_max; m_n++; + curr = &m_q[pos]; + curr->op = orig->op; + if(curr->op == -1) return; curr->caller = orig->caller; curr->port = orig->port; - curr->op = orig->op; curr->len = orig->len; curr->bin[0] = orig->bin[0]; curr->bin[1] = orig->bin[1]; @@ -171,17 +189,19 @@ void wxeFifo::Realloc() wxeCommand * old = m_q; wxeCommand * queue = (wxeCommand *)driver_alloc(new_sz*sizeof(wxeCommand)); + // fprintf(stderr, "\r\nrealloc qsz %d\r\n", new_sz);fflush(stderr); + m_max=new_sz; m_first = 0; m_n=0; m_q = queue; for(i=0; i < n; i++) { - unsigned int pos = i+first; - if(old[pos%max].op >= 0) { - Append(&old[pos%max]); - } + unsigned int pos = (i+first)%max; + if(old[pos].op >= 0) + Append(&old[pos]); } + for(i = m_n; i < new_sz; i++) { // Reset the rest m_q[i].buffer = NULL; m_q[i].op = -1; @@ -190,6 +210,26 @@ void wxeFifo::Realloc() m_old = old; } +// Strip end of queue if ops are already taken care of, avoids reallocs +void wxeFifo::Strip() +{ + while((m_n > 0) && (m_q[(m_first + m_n - 1)%m_max].op == -1)) { + m_n--; + } +} + +unsigned int wxeFifo::Cleanup(unsigned int def) +{ + if(m_old) { + driver_free(m_old); + m_old = NULL; + // Realloced we need to start from the beginning + return 0; + } else { + return def; + } +} + /* **************************************************************************** * TreeItemData * ****************************************************************************/ diff --git a/lib/wx/c_src/wxe_helpers.h b/lib/wx/c_src/wxe_helpers.h index 4f9d9ca9c3..ff949e332b 100644 --- a/lib/wx/c_src/wxe_helpers.h +++ b/lib/wx/c_src/wxe_helpers.h @@ -67,9 +67,13 @@ class wxeFifo { void Append(wxeCommand *Other); wxeCommand * Get(); + wxeCommand * Peek(unsigned int *item); void Realloc(); + void Strip(); + unsigned int Cleanup(unsigned int peek=0); + unsigned int cb_start; unsigned int m_max; unsigned int m_first; unsigned int m_n; diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp index 5b34f08704..c5bad41573 100644 --- a/lib/wx/c_src/wxe_impl.cpp +++ b/lib/wx/c_src/wxe_impl.cpp @@ -57,10 +57,8 @@ extern ErlDrvTermData init_caller; extern int wxe_status; wxeFifo * wxe_queue = NULL; -wxeFifo * wxe_queue_cb_saved = NULL; unsigned int wxe_needs_signal = 0; // inside batch if larger than 0 -unsigned int wxe_cb_invoked = 0; /* ************************************************************ * Commands from erlang @@ -123,11 +121,10 @@ bool WxeApp::OnInit() { global_me = new wxeMemEnv(); - wxe_queue = new wxeFifo(1000); - wxe_queue_cb_saved = new wxeFifo(200); + wxe_queue = new wxeFifo(2000); cb_buff = NULL; recurse_level = 0; - delayed_delete = new wxeFifo(10); + delayed_delete = new wxeFifo(100); delayed_cleanup = new wxList; wxe_ps_init2(); @@ -173,7 +170,6 @@ void WxeApp::shutdown(wxeMetaCommand& Ecmd) { wxe_status = WXE_EXITING; ExitMainLoop(); delete wxe_queue; - delete wxe_queue_cb_saved; } void WxeApp::dummy_close(wxEvent& Ev) { @@ -229,12 +225,11 @@ void handle_event_callback(ErlDrvPort port, ErlDrvTermData process) if(driver_monitor_process(port, process, &monitor) == 0) { // Should we be able to handle commands when recursing? probably // fprintf(stderr, "\r\nCB EV Start %lu \r\n", process);fflush(stderr); - app->recurse_level++; - app->dispatch_cb(wxe_queue, wxe_queue_cb_saved, process); - app->recurse_level--; + app->recurse_level += 2; + app->dispatch_cb(wxe_queue, process); + app->recurse_level -= 2; // fprintf(stderr, "CB EV done %lu \r\n", process);fflush(stderr); driver_demonitor_process(port, &monitor); - wxe_cb_invoked = 1; } } @@ -242,16 +237,11 @@ void WxeApp::dispatch_cmds() { if(wxe_status != WXE_INITIATED) return; - do { - wxe_cb_invoked = 0; - recurse_level++; - // fprintf(stderr, "\r\ndispatch_saved 0 \r\n");fflush(stderr); - int level = dispatch(wxe_queue_cb_saved, 0, WXE_STORED); - // fprintf(stderr, "\r\ndispatch_normal %d\r\n", level);fflush(stderr); - dispatch(wxe_queue, level, WXE_NORMAL); - // fprintf(stderr, "\r\ndispatch_done \r\n");fflush(stderr); - recurse_level--; - } while(wxe_cb_invoked); + recurse_level++; + // fprintf(stderr, "\r\ndispatch_normal %d\r\n", level);fflush(stderr); + dispatch(wxe_queue); + // fprintf(stderr, "\r\ndispatch_done \r\n");fflush(stderr); + recurse_level--; // Cleanup old memenv's and deleted objects if(recurse_level == 0) { @@ -260,6 +250,7 @@ void WxeApp::dispatch_cmds() wxe_dispatch(*curr); curr->Delete(); } + delayed_delete->Cleanup(); if(delayed_cleanup->size() > 0) for( wxList::compatibility_iterator node = delayed_cleanup->GetFirst(); node; @@ -269,28 +260,19 @@ void WxeApp::dispatch_cmds() destroyMemEnv(*event); delete event; } - if(wxe_queue_cb_saved->m_old) { - driver_free(wxe_queue_cb_saved->m_old); - wxe_queue_cb_saved->m_old = NULL; - } - if(delayed_delete->m_old) { - driver_free(delayed_delete->m_old); - delayed_delete->m_old = NULL; - } } } -int WxeApp::dispatch(wxeFifo * batch, int blevel, int list_type) +int WxeApp::dispatch(wxeFifo * batch) { int ping = 0; + int blevel = 0; wxeCommand *event; - if(list_type == WXE_NORMAL) erl_drv_mutex_lock(wxe_batch_locker_m); + erl_drv_mutex_lock(wxe_batch_locker_m); while(true) { while((event = batch->Get()) != NULL) { - if(list_type == WXE_NORMAL) erl_drv_mutex_unlock(wxe_batch_locker_m); + erl_drv_mutex_unlock(wxe_batch_locker_m); switch(event->op) { - case -1: - break; case WXE_BATCH_END: {--blevel; } break; @@ -321,20 +303,10 @@ int WxeApp::dispatch(wxeFifo * batch, int blevel, int list_type) break; } event->Delete(); - if(list_type == WXE_NORMAL) { - if(wxe_cb_invoked) - return blevel; - else - erl_drv_mutex_lock(wxe_batch_locker_m); - } + erl_drv_mutex_lock(wxe_batch_locker_m); + batch->Cleanup(); } - if(list_type == WXE_STORED) - return blevel; - if(blevel <= 0) { // list_type == WXE_NORMAL - if(wxe_queue->m_old) { - driver_free(wxe_queue->m_old); - wxe_queue->m_old = NULL; - } + if(blevel <= 0) { erl_drv_mutex_unlock(wxe_batch_locker_m); return blevel; } @@ -348,12 +320,13 @@ int WxeApp::dispatch(wxeFifo * batch, int blevel, int list_type) } } -void WxeApp::dispatch_cb(wxeFifo * batch, wxeFifo * temp, ErlDrvTermData process) { +void WxeApp::dispatch_cb(wxeFifo * batch, ErlDrvTermData process) { wxeCommand *event; + unsigned int peek; erl_drv_mutex_lock(wxe_batch_locker_m); + peek = batch->Cleanup(batch->cb_start); while(true) { - while((event = batch->Get()) != NULL) { - erl_drv_mutex_unlock(wxe_batch_locker_m); + while((event = batch->Peek(&peek)) != NULL) { wxeMemEnv *memenv = getMemEnv(event->port); // fprintf(stderr, " Ev %d %lu\r\n", event->op, event->caller); if(event->caller == process || // Callbacks from CB process only @@ -361,8 +334,8 @@ void WxeApp::dispatch_cb(wxeFifo * batch, wxeFifo * temp, ErlDrvTermData process event->op == WXE_CB_DIED || // Event callback process died // Allow connect_cb during CB i.e. msg from wxe_server. (memenv && event->caller == memenv->owner)) { + erl_drv_mutex_unlock(wxe_batch_locker_m); switch(event->op) { - case -1: case WXE_BATCH_END: case WXE_BATCH_BEGIN: case WXE_DEBUG_PING: @@ -373,52 +346,42 @@ void WxeApp::dispatch_cb(wxeFifo * batch, wxeFifo * temp, ErlDrvTermData process memcpy(cb_buff, event->buffer, event->len); } // continue case WXE_CB_DIED: + batch->cb_start = 0; event->Delete(); + erl_drv_mutex_lock(wxe_batch_locker_m); + batch->Strip(); + erl_drv_mutex_unlock(wxe_batch_locker_m); return; case WXE_CB_START: // CB start from now accept message from CB process only process = event->caller; break; default: - size_t start=temp->m_n; + batch->cb_start = peek; // In case of recursive callbacks if(event->op < OPENGL_START) { - // fprintf(stderr, " cb %d \r\n", event->op); wxe_dispatch(*event); } else { gl_dispatch(event->op,event->buffer,event->caller,event->bin); } - if(temp->m_n > start) { - erl_drv_mutex_lock(wxe_batch_locker_m); - // We have recursed dispatch_cb and messages for this - // callback may be saved on temp list move them - // to orig list - for(unsigned int i=start; i < temp->m_n; i++) { - wxeCommand *ev = &temp->m_q[(temp->m_first+i) % temp->m_max]; - if(ev->caller == process) { - batch->Append(ev); - } - } - erl_drv_mutex_unlock(wxe_batch_locker_m); - } break; } event->Delete(); - } else { - // fprintf(stderr, " save %d %lu\r\n", event->op, event->caller); - temp->Append(event); + erl_drv_mutex_lock(wxe_batch_locker_m); + peek = batch->Cleanup(peek); } - erl_drv_mutex_lock(wxe_batch_locker_m); } // sleep until something happens // fprintf(stderr, "%s:%d sleep %d %d\r\n", __FILE__, __LINE__, - // batch->m_n, temp->m_n);fflush(stderr); + // peek, batch->m_n);fflush(stderr); wxe_needs_signal = 1; - while(batch->m_n == 0) { + while(peek >= batch->m_n) { erl_drv_cond_wait(wxe_batch_locker_c, wxe_batch_locker_m); + peek = batch->Cleanup(peek); } wxe_needs_signal = 0; } } + /* Memory handling */ void WxeApp::newMemEnv(wxeMetaCommand& Ecmd) { diff --git a/lib/wx/c_src/wxe_impl.h b/lib/wx/c_src/wxe_impl.h index d6d3095a0f..fd25296c73 100644 --- a/lib/wx/c_src/wxe_impl.h +++ b/lib/wx/c_src/wxe_impl.h @@ -67,8 +67,8 @@ public: void shutdown(wxeMetaCommand& event); - int dispatch(wxeFifo *, int, int); - void dispatch_cb(wxeFifo * batch, wxeFifo * temp, ErlDrvTermData process); + int dispatch(wxeFifo *); + void dispatch_cb(wxeFifo * batch, ErlDrvTermData process); void wxe_dispatch(wxeCommand& event); diff --git a/lib/wx/examples/demo/ex_canvas.erl b/lib/wx/examples/demo/ex_canvas.erl index 1cbb96de1f..cdc783055c 100644 --- a/lib/wx/examples/demo/ex_canvas.erl +++ b/lib/wx/examples/demo/ex_canvas.erl @@ -35,7 +35,9 @@ parent, config, canvas, - bitmap + bitmap, + overlay, + pos }). start(Config) -> @@ -60,6 +62,10 @@ do_init(Config) -> wxPanel:connect(Canvas, paint, [callback]), wxPanel:connect(Canvas, size), + wxPanel:connect(Canvas, left_down), + wxPanel:connect(Canvas, left_up), + wxPanel:connect(Canvas, motion), + wxPanel:connect(Button, command_button_clicked), %% Add to sizers @@ -78,7 +84,9 @@ do_init(Config) -> Bitmap = wxBitmap:new(erlang:max(W,30),erlang:max(30,H)), {Panel, #state{parent=Panel, config=Config, - canvas = Canvas, bitmap = Bitmap}}. + canvas = Canvas, bitmap = Bitmap, + overlay = wxOverlay:new() + }}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Sync event from callback events, paint event must be handled in callbacks @@ -127,11 +135,39 @@ handle_event(#wx{event = #wxCommand{type = command_button_clicked}}, wxBitmap:destroy(Bmp), {noreply, State}; handle_event(#wx{event = #wxSize{size={W,H}}}, - State = #state{bitmap=Prev}) -> + State = #state{bitmap=Prev, canvas=Canvas}) -> Bitmap = wxBitmap:new(W,H), - draw(State#state.canvas, Bitmap, fun(DC) -> wxDC:clear(DC) end), + draw(Canvas, Bitmap, fun(DC) -> wxDC:clear(DC) end), wxBitmap:destroy(Prev), {noreply, State#state{bitmap = Bitmap}}; + +handle_event(#wx{event = #wxMouse{type=left_down, x=X, y=Y}}, State) -> + {noreply, State#state{pos={X,Y}}}; +handle_event(#wx{event = #wxMouse{type=motion, x=X1, y=Y1}}, + #state{pos=Start, overlay=Overlay, canvas=Canvas} = State) -> + case Start of + undefined -> ignore; + {X0,Y0} -> + DC = wxClientDC:new(Canvas), + DCO = wxDCOverlay:new(Overlay, DC), + wxDCOverlay:clear(DCO), + wxDC:setPen(DC, ?wxLIGHT_GREY_PEN), + wxDC:setBrush(DC, ?wxTRANSPARENT_BRUSH), + wxDC:drawRectangle(DC, {X0,Y0, X1-X0, Y1-Y0}), + wxDCOverlay:destroy(DCO), + wxClientDC:destroy(DC) + end, + {noreply, State}; +handle_event(#wx{event = #wxMouse{type=left_up}}, + #state{overlay=Overlay, canvas=Canvas} = State) -> + DC = wxClientDC:new(Canvas), + DCO = wxDCOverlay:new(Overlay, DC), + wxDCOverlay:clear(DCO), + wxDCOverlay:destroy(DCO), + wxClientDC:destroy(DC), + wxOverlay:reset(Overlay), + {noreply, State#state{pos=undefined}}; + handle_event(Ev = #wx{}, State = #state{}) -> demo:format(State#state.config, "Got Event ~p\n", [Ev]), {noreply, State}. @@ -155,7 +191,8 @@ handle_cast(Msg, State) -> code_change(_, _, State) -> {stop, ignore, State}. -terminate(_Reason, _) -> +terminate(_Reason, #state{overlay=Overlay}) -> + wxOverlay:destroy(Overlay), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/wx/src/gen/gl.erl b/lib/wx/src/gen/gl.erl index 58cdb59aa2..bedd4e9cca 100644 --- a/lib/wx/src/gen/gl.erl +++ b/lib/wx/src/gen/gl.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -53,10 +53,14 @@ -type enum() :: non_neg_integer(). %% See wx/include/gl.hrl -type clamp() :: float(). %% 0.0..1.0 -type offset() :: non_neg_integer(). %% Offset in memory block --type matrix() :: {float(),float(),float(),float(), +-type matrix12() :: {float(),float(),float(),float(), + float(),float(),float(),float(), + float(),float(),float(),float()}. +-type matrix16() :: {float(),float(),float(),float(), float(),float(),float(),float(), float(),float(),float(),float(), float(),float(),float(),float()}. +-type matrix() :: matrix12() | matrix16(). -type mem() :: binary() | tuple(). %% Memory block -export([clearIndex/1,clearColor/4,clear/1,indexMask/1,colorMask/4,alphaFunc/2, @@ -4289,14 +4293,14 @@ lighti(Light,Pname,Param) -> %% @doc %% See {@link lightf/3} --spec lightfv(Light, Pname, Params) -> ok when Light :: enum(),Pname :: enum(),Params :: {float()}. +-spec lightfv(Light, Pname, Params) -> ok when Light :: enum(),Pname :: enum(),Params :: tuple(). lightfv(Light,Pname,Params) -> cast(5207, <<Light:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). %% @doc %% See {@link lightf/3} --spec lightiv(Light, Pname, Params) -> ok when Light :: enum(),Pname :: enum(),Params :: {integer()}. +-spec lightiv(Light, Pname, Params) -> ok when Light :: enum(),Pname :: enum(),Params :: tuple(). lightiv(Light,Pname,Params) -> cast(5208, <<Light:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). @@ -4460,14 +4464,14 @@ lightModeli(Pname,Param) -> %% @doc %% See {@link lightModelf/2} --spec lightModelfv(Pname, Params) -> ok when Pname :: enum(),Params :: {float()}. +-spec lightModelfv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple(). lightModelfv(Pname,Params) -> cast(5213, <<Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>). %% @doc %% See {@link lightModelf/2} --spec lightModeliv(Pname, Params) -> ok when Pname :: enum(),Params :: {integer()}. +-spec lightModeliv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple(). lightModeliv(Pname,Params) -> cast(5214, <<Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>). @@ -4547,14 +4551,14 @@ materiali(Face,Pname,Param) -> %% @doc %% See {@link materialf/3} --spec materialfv(Face, Pname, Params) -> ok when Face :: enum(),Pname :: enum(),Params :: {float()}. +-spec materialfv(Face, Pname, Params) -> ok when Face :: enum(),Pname :: enum(),Params :: tuple(). materialfv(Face,Pname,Params) -> cast(5217, <<Face:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). %% @doc %% See {@link materialf/3} --spec materialiv(Face, Pname, Params) -> ok when Face :: enum(),Pname :: enum(),Params :: {integer()}. +-spec materialiv(Face, Pname, Params) -> ok when Face :: enum(),Pname :: enum(),Params :: tuple(). materialiv(Face,Pname,Params) -> cast(5218, <<Face:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). @@ -5890,21 +5894,21 @@ texGeni(Coord,Pname,Param) -> %% @doc %% See {@link texGend/3} --spec texGendv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: {float()}. +-spec texGendv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: tuple(). texGendv(Coord,Pname,Params) -> cast(5246, <<Coord:?GLenum,Pname:?GLenum,(size(Params)):?GLuint,0:32, (<< <<C:?GLdouble>> ||C <- tuple_to_list(Params)>>)/binary>>). %% @doc %% See {@link texGend/3} --spec texGenfv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: {float()}. +-spec texGenfv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: tuple(). texGenfv(Coord,Pname,Params) -> cast(5247, <<Coord:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). %% @doc %% See {@link texGend/3} --spec texGeniv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: {integer()}. +-spec texGeniv(Coord, Pname, Params) -> ok when Coord :: enum(),Pname :: enum(),Params :: tuple(). texGeniv(Coord,Pname,Params) -> cast(5248, <<Coord:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). @@ -6123,14 +6127,14 @@ texEnvi(Target,Pname,Param) -> %% replacement. The default value is `?GL_FALSE'. %% %% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml">external</a> documentation. --spec texEnvfv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {float()}. +-spec texEnvfv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). texEnvfv(Target,Pname,Params) -> cast(5254, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). %% @doc %% See {@link texEnvfv/3} --spec texEnviv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}. +-spec texEnviv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). texEnviv(Target,Pname,Params) -> cast(5255, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). @@ -6455,14 +6459,14 @@ texParameteri(Target,Pname,Param) -> %% @doc %% See {@link texParameterf/3} --spec texParameterfv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {float()}. +-spec texParameterfv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). texParameterfv(Target,Pname,Params) -> cast(5260, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). %% @doc %% See {@link texParameterf/3} --spec texParameteriv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}. +-spec texParameteriv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). texParameteriv(Target,Pname,Params) -> cast(5261, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). @@ -7609,14 +7613,14 @@ fogi(Pname,Param) -> %% @doc %% See {@link fogf/2} --spec fogfv(Pname, Params) -> ok when Pname :: enum(),Params :: {float()}. +-spec fogfv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple(). fogfv(Pname,Params) -> cast(5306, <<Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>). %% @doc %% See {@link fogf/2} --spec fogiv(Pname, Params) -> ok when Pname :: enum(),Params :: {integer()}. +-spec fogiv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple(). fogiv(Pname,Params) -> cast(5307, <<Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>). @@ -8522,24 +8526,24 @@ convolutionFilter2D(Target,Internalformat,Width,Height,Format,Type,Image) -> %% image were replicated. %% %% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionParameter.xml">external</a> documentation. --spec convolutionParameterf(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {float()}. +-spec convolutionParameterf(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). convolutionParameterf(Target,Pname,Params) -> cast(5339, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). %% @equiv convolutionParameterf(Target,Pname,Params) --spec convolutionParameterfv(Target :: enum(),Pname :: enum(),Params) -> ok when Params :: {Params :: {float()}}. +-spec convolutionParameterfv(Target :: enum(),Pname :: enum(),Params) -> ok when Params :: {Params :: tuple()}. convolutionParameterfv(Target,Pname,{Params}) -> convolutionParameterf(Target,Pname,Params). %% @doc %% See {@link convolutionParameterf/3} --spec convolutionParameteri(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}. +-spec convolutionParameteri(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). convolutionParameteri(Target,Pname,Params) -> cast(5340, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). %% @equiv convolutionParameteri(Target,Pname,Params) --spec convolutionParameteriv(Target :: enum(),Pname :: enum(),Params) -> ok when Params :: {Params :: {integer()}}. +-spec convolutionParameteriv(Target :: enum(),Pname :: enum(),Params) -> ok when Params :: {Params :: tuple()}. convolutionParameteriv(Target,Pname,{Params}) -> convolutionParameteri(Target,Pname,Params). %% @doc Copy pixels into a one-dimensional convolution filter @@ -9671,7 +9675,7 @@ pointParameterf(Pname,Param) -> %% @doc %% See {@link pointParameterf/2} --spec pointParameterfv(Pname, Params) -> ok when Pname :: enum(),Params :: {float()}. +-spec pointParameterfv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple(). pointParameterfv(Pname,Params) -> cast(5397, <<Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLfloat>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>). @@ -9684,7 +9688,7 @@ pointParameteri(Pname,Param) -> %% @doc %% See {@link pointParameterf/2} --spec pointParameteriv(Pname, Params) -> ok when Pname :: enum(),Params :: {integer()}. +-spec pointParameteriv(Pname, Params) -> ok when Pname :: enum(),Params :: tuple(). pointParameteriv(Pname,Params) -> cast(5399, <<Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((0+size(Params)) rem 2)*32)>>). @@ -11529,7 +11533,7 @@ linkProgram(Program) -> %% scanned or parsed at this time; they are simply copied into the specified shader object. %% %% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderSource.xml">external</a> documentation. --spec shaderSource(Shader, String) -> ok when Shader :: integer(),String :: [string()]. +-spec shaderSource(Shader, String) -> ok when Shader :: integer(),String :: iolist(). shaderSource(Shader,String) -> StringTemp = list_to_binary([[Str|[0]] || Str <- String ]), cast(5473, <<Shader:?GLuint,(length(String)):?GLuint,(size(StringTemp)):?GLuint,(StringTemp)/binary,0:((8-((size(StringTemp)+0) rem 8)) rem 8)>>). @@ -12278,7 +12282,7 @@ bindBufferBase(Target,Index,Buffer) -> %% and the buffer mode is `?GL_INTERLEAVED_ATTRIBS'. %% %% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTransformFeedbackVaryings.xml">external</a> documentation. --spec transformFeedbackVaryings(Program, Varyings, BufferMode) -> ok when Program :: integer(),Varyings :: [string()],BufferMode :: enum(). +-spec transformFeedbackVaryings(Program, Varyings, BufferMode) -> ok when Program :: integer(),Varyings :: iolist(),BufferMode :: enum(). transformFeedbackVaryings(Program,Varyings,BufferMode) -> VaryingsTemp = list_to_binary([[Str|[0]] || Str <- Varyings ]), cast(5536, <<Program:?GLuint,(length(Varyings)):?GLuint,(size(VaryingsTemp)):?GLuint,(VaryingsTemp)/binary,0:((8-((size(VaryingsTemp)+0) rem 8)) rem 8),BufferMode:?GLenum>>). @@ -12596,7 +12600,7 @@ uniform4uiv(Location,Value) -> %% @doc %% See {@link texParameterf/3} --spec texParameterIiv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}. +-spec texParameterIiv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). texParameterIiv(Target,Pname,Params) -> cast(5568, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). @@ -12604,7 +12608,7 @@ texParameterIiv(Target,Pname,Params) -> %% @doc glTexParameterI %% %% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexParameterI.xml">external</a> documentation. --spec texParameterIuiv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: {integer()}. +-spec texParameterIuiv(Target, Pname, Params) -> ok when Target :: enum(),Pname :: enum(),Params :: tuple(). texParameterIuiv(Target,Pname,Params) -> cast(5569, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, (<< <<C:?GLuint>> ||C <- tuple_to_list(Params)>>)/binary,0:(((1+size(Params)) rem 2)*32)>>). @@ -12651,21 +12655,21 @@ getTexParameterIuiv(Target,Pname) -> %% and the buffer being cleared is defined. However, this is not an error. %% %% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearBuffer.xml">external</a> documentation. --spec clearBufferiv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: {integer()}. +-spec clearBufferiv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: tuple(). clearBufferiv(Buffer,Drawbuffer,Value) -> cast(5572, <<Buffer:?GLenum,Drawbuffer:?GLint,(size(Value)):?GLuint, (<< <<C:?GLint>> ||C <- tuple_to_list(Value)>>)/binary,0:(((1+size(Value)) rem 2)*32)>>). %% @doc %% See {@link clearBufferiv/3} --spec clearBufferuiv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: {integer()}. +-spec clearBufferuiv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: tuple(). clearBufferuiv(Buffer,Drawbuffer,Value) -> cast(5573, <<Buffer:?GLenum,Drawbuffer:?GLint,(size(Value)):?GLuint, (<< <<C:?GLuint>> ||C <- tuple_to_list(Value)>>)/binary,0:(((1+size(Value)) rem 2)*32)>>). %% @doc %% See {@link clearBufferiv/3} --spec clearBufferfv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: {float()}. +-spec clearBufferfv(Buffer, Drawbuffer, Value) -> ok when Buffer :: enum(),Drawbuffer :: integer(),Value :: tuple(). clearBufferfv(Buffer,Drawbuffer,Value) -> cast(5574, <<Buffer:?GLenum,Drawbuffer:?GLint,(size(Value)):?GLuint, (<< <<C:?GLfloat>> ||C <- tuple_to_list(Value)>>)/binary,0:(((1+size(Value)) rem 2)*32)>>). @@ -13219,7 +13223,7 @@ createShaderObjectARB(ShaderType) -> %% @doc glShaderSourceARB %% %% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderSourceARB.xml">external</a> documentation. --spec shaderSourceARB(ShaderObj, String) -> ok when ShaderObj :: integer(),String :: [string()]. +-spec shaderSourceARB(ShaderObj, String) -> ok when ShaderObj :: integer(),String :: iolist(). shaderSourceARB(ShaderObj,String) -> StringTemp = list_to_binary([[Str|[0]] || Str <- String ]), cast(5630, <<ShaderObj:?GLhandleARB,(length(String)):?GLuint,(size(StringTemp)):?GLuint,(StringTemp)/binary,0:((8-((size(StringTemp)+4) rem 8)) rem 8)>>). @@ -13927,7 +13931,7 @@ isVertexArray(Array) -> %% If an error occurs, nothing is written to `UniformIndices' . %% %% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformIndices.xml">external</a> documentation. --spec getUniformIndices(Program, UniformNames) -> [integer()] when Program :: integer(),UniformNames :: [string()]. +-spec getUniformIndices(Program, UniformNames) -> [integer()] when Program :: integer(),UniformNames :: iolist(). getUniformIndices(Program,UniformNames) -> UniformNamesTemp = list_to_binary([[Str|[0]] || Str <- UniformNames ]), call(5675, <<Program:?GLuint,(length(UniformNames)):?GLuint,(size(UniformNamesTemp)):?GLuint,(UniformNamesTemp)/binary,0:((8-((size(UniformNamesTemp)+0) rem 8)) rem 8)>>). @@ -14458,7 +14462,7 @@ deleteNamedStringARB(Name) -> %% @doc glCompileShaderIncludeARB %% %% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompileShaderIncludeARB.xml">external</a> documentation. --spec compileShaderIncludeARB(Shader, Path) -> ok when Shader :: integer(),Path :: [string()]. +-spec compileShaderIncludeARB(Shader, Path) -> ok when Shader :: integer(),Path :: iolist(). compileShaderIncludeARB(Shader,Path) -> PathTemp = list_to_binary([[Str|[0]] || Str <- Path ]), cast(5703, <<Shader:?GLuint,(length(Path)):?GLuint,(size(PathTemp)):?GLuint,(PathTemp)/binary,0:((8-((size(PathTemp)+0) rem 8)) rem 8)>>). @@ -15617,7 +15621,7 @@ activeShaderProgram(Pipeline,Program) -> %% @doc glCreateShaderProgramv %% %% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateShaderProgramv.xml">external</a> documentation. --spec createShaderProgramv(Type, Strings) -> integer() when Type :: enum(),Strings :: [string()]. +-spec createShaderProgramv(Type, Strings) -> integer() when Type :: enum(),Strings :: iolist(). createShaderProgramv(Type,Strings) -> StringsTemp = list_to_binary([[Str|[0]] || Str <- Strings ]), call(5778, <<Type:?GLenum,(length(Strings)):?GLuint,(size(StringsTemp)):?GLuint,(StringsTemp)/binary,0:((8-((size(StringsTemp)+0) rem 8)) rem 8)>>). diff --git a/lib/wx/src/gen/glu.erl b/lib/wx/src/gen/glu.erl index 6a6e20b3e4..5faba48930 100644 --- a/lib/wx/src/gen/glu.erl +++ b/lib/wx/src/gen/glu.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2013. All Rights Reserved. +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -51,10 +51,14 @@ -define(GLint64,64/native-signed). -type vertex() :: {float(), float(), float()}. -type enum() :: non_neg_integer(). %% See wx/include/gl.hrl or glu.hrl --type matrix() :: {float(),float(),float(),float(), +-type matrix12() :: {float(),float(),float(),float(), + float(),float(),float(),float(), + float(),float(),float(),float()}. +-type matrix16() :: {float(),float(),float(),float(), float(),float(),float(),float(), float(),float(),float(),float(), float(),float(),float(),float()}. +-type matrix() :: matrix12() | matrix16(). -type mem() :: binary() | tuple(). %% Memory block -export([tesselate/2,build1DMipmapLevels/9,build1DMipmaps/6,build2DMipmapLevels/10, diff --git a/lib/wx/src/gen/wxDCOverlay.erl b/lib/wx/src/gen/wxDCOverlay.erl new file mode 100644 index 0000000000..f98e310ba6 --- /dev/null +++ b/lib/wx/src/gen/wxDCOverlay.erl @@ -0,0 +1,70 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. +%% +%% 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 +%% distributed under the License is distributed on an "AS IS" BASIS, +%% 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. +%% +%% %CopyrightEnd% +%% This file is generated DO NOT EDIT + +%% @doc See external documentation: <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdcoverlay.html">wxDCOverlay</a>. +%% @type wxDCOverlay(). An object reference, The representation is internal +%% and can be changed without notice. It can't be used for comparsion +%% stored on disc or distributed for use on other nodes. + +-module(wxDCOverlay). +-include("wxe.hrl"). +-export([clear/1,destroy/1,new/2,new/6]). + +%% inherited exports +-export([parent_class/1]). + +-export_type([wxDCOverlay/0]). +%% @hidden +parent_class(_Class) -> erlang:error({badtype, ?MODULE}). + +-type wxDCOverlay() :: wx:wx_object(). +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdcoverlay.html#wxdcoverlaywxdcoverlay">external documentation</a>. +-spec new(Overlay, Dc) -> wxDCOverlay() when + Overlay::wxOverlay:wxOverlay(), Dc::wxWindowDC:wxWindowDC(). +new(#wx_ref{type=OverlayT,ref=OverlayRef},#wx_ref{type=DcT,ref=DcRef}) -> + ?CLASS(OverlayT,wxOverlay), + ?CLASS(DcT,wxWindowDC), + wxe_util:construct(?wxDCOverlay_new_2, + <<OverlayRef:32/?UI,DcRef:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdcoverlay.html#wxdcoverlaywxdcoverlay">external documentation</a>. +-spec new(Overlay, Dc, X, Y, Width, Height) -> wxDCOverlay() when + Overlay::wxOverlay:wxOverlay(), Dc::wxWindowDC:wxWindowDC(), X::integer(), Y::integer(), Width::integer(), Height::integer(). +new(#wx_ref{type=OverlayT,ref=OverlayRef},#wx_ref{type=DcT,ref=DcRef},X,Y,Width,Height) + when is_integer(X),is_integer(Y),is_integer(Width),is_integer(Height) -> + ?CLASS(OverlayT,wxOverlay), + ?CLASS(DcT,wxWindowDC), + wxe_util:construct(?wxDCOverlay_new_6, + <<OverlayRef:32/?UI,DcRef:32/?UI,X:32/?UI,Y:32/?UI,Width:32/?UI,Height:32/?UI>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxdcoverlay.html#wxdcoverlayclear">external documentation</a>. +-spec clear(This) -> ok when + This::wxDCOverlay(). +clear(#wx_ref{type=ThisT,ref=ThisRef}) -> + ?CLASS(ThisT,wxDCOverlay), + wxe_util:cast(?wxDCOverlay_Clear, + <<ThisRef:32/?UI>>). + +%% @doc Destroys this object, do not use object again +-spec destroy(This::wxDCOverlay()) -> ok. +destroy(Obj=#wx_ref{type=Type}) -> + ?CLASS(Type,wxDCOverlay), + wxe_util:destroy(?wxDCOverlay_destruct,Obj), + ok. diff --git a/lib/wx/src/gen/wxOverlay.erl b/lib/wx/src/gen/wxOverlay.erl new file mode 100644 index 0000000000..7da3ece657 --- /dev/null +++ b/lib/wx/src/gen/wxOverlay.erl @@ -0,0 +1,57 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2015. All Rights Reserved. +%% +%% 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 +%% distributed under the License is distributed on an "AS IS" BASIS, +%% 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. +%% +%% %CopyrightEnd% +%% This file is generated DO NOT EDIT + +%% @doc See external documentation: <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxoverlay.html">wxOverlay</a>. +%% @type wxOverlay(). An object reference, The representation is internal +%% and can be changed without notice. It can't be used for comparsion +%% stored on disc or distributed for use on other nodes. + +-module(wxOverlay). +-include("wxe.hrl"). +-export([destroy/1,new/0,reset/1]). + +%% inherited exports +-export([parent_class/1]). + +-export_type([wxOverlay/0]). +%% @hidden +parent_class(_Class) -> erlang:error({badtype, ?MODULE}). + +-type wxOverlay() :: wx:wx_object(). +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxoverlay.html#wxoverlaywxoverlay">external documentation</a>. +-spec new() -> wxOverlay(). +new() -> + wxe_util:construct(?wxOverlay_new, + <<>>). + +%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxoverlay.html#wxoverlayreset">external documentation</a>. +-spec reset(This) -> ok when + This::wxOverlay(). +reset(#wx_ref{type=ThisT,ref=ThisRef}) -> + ?CLASS(ThisT,wxOverlay), + wxe_util:cast(?wxOverlay_Reset, + <<ThisRef:32/?UI>>). + +%% @doc Destroys this object, do not use object again +-spec destroy(This::wxOverlay()) -> ok. +destroy(Obj=#wx_ref{type=Type}) -> + ?CLASS(Type,wxOverlay), + wxe_util:destroy(?wxOverlay_destruct,Obj), + ok. diff --git a/lib/wx/src/gen/wxe_debug.hrl b/lib/wx/src/gen/wxe_debug.hrl index 2cb73c0fed..6c7602acd3 100644 --- a/lib/wx/src/gen/wxe_debug.hrl +++ b/lib/wx/src/gen/wxe_debug.hrl @@ -3363,6 +3363,13 @@ wxdebug_table() -> {3583, {wxPopupTransientWindow, destruct, 0}}, {3584, {wxPopupTransientWindow, popup, 1}}, {3585, {wxPopupTransientWindow, dismiss, 0}}, + {3586, {wxOverlay, new, 0}}, + {3587, {wxOverlay, destruct, 0}}, + {3588, {wxOverlay, reset, 0}}, + {3589, {wxDCOverlay, new_6, 6}}, + {3590, {wxDCOverlay, new_2, 2}}, + {3591, {wxDCOverlay, destruct, 0}}, + {3592, {wxDCOverlay, clear, 0}}, {-1, {mod, func, -1}} ]. diff --git a/lib/wx/src/gen/wxe_funcs.hrl b/lib/wx/src/gen/wxe_funcs.hrl index d8c2ba9171..3a34cd494d 100644 --- a/lib/wx/src/gen/wxe_funcs.hrl +++ b/lib/wx/src/gen/wxe_funcs.hrl @@ -3360,3 +3360,10 @@ -define(wxPopupTransientWindow_destruct, 3583). -define(wxPopupTransientWindow_Popup, 3584). -define(wxPopupTransientWindow_Dismiss, 3585). +-define(wxOverlay_new, 3586). +-define(wxOverlay_destruct, 3587). +-define(wxOverlay_Reset, 3588). +-define(wxDCOverlay_new_6, 3589). +-define(wxDCOverlay_new_2, 3590). +-define(wxDCOverlay_destruct, 3591). +-define(wxDCOverlay_Clear, 3592). diff --git a/lib/wx/src/wxe_server.erl b/lib/wx/src/wxe_server.erl index cc253b1143..ae9440f890 100644 --- a/lib/wx/src/wxe_server.erl +++ b/lib/wx/src/wxe_server.erl @@ -352,25 +352,8 @@ handle_disconnect(Object, Evh = #evh{cb=Fun}, From, State0 = #state{users=Users0, cb=Callbacks}) -> #user{events=Evs0} = gb_trees:get(From, Users0), FunId = gb_trees:lookup(Fun, Callbacks), - case find_handler(Evs0, Object, Evh#evh{cb=FunId}) of - [] -> - {reply, false, State0}; - Handlers -> - case disconnect(Object,Handlers) of - #evh{} -> {reply, true, State0}; - Result -> {reply, Result, State0} - end - end. - -disconnect(Object,[Ev|Evs]) -> - try wxEvtHandler:disconnect_impl(Object,Ev) of - true -> Ev; - false -> disconnect(Object, Evs); - Error -> Error - catch _:_ -> - false - end; -disconnect(_, []) -> false. + Handlers = find_handler(Evs0, Object, Evh#evh{cb=FunId}), + {reply, {try_in_order, Handlers}, State0}. find_handler([{Object,Evh}|Evs], Object, Match) -> case match_handler(Match, Evh) of diff --git a/lib/wx/src/wxe_util.erl b/lib/wx/src/wxe_util.erl index 1983e6783a..398ceddd4f 100644 --- a/lib/wx/src/wxe_util.erl +++ b/lib/wx/src/wxe_util.erl @@ -127,8 +127,21 @@ connect_cb(Object,EvData0 = #evh{cb=Callback}) -> disconnect_cb(Object,EvData) -> Server = (wx:get_env())#wx_env.sv, - gen_server:call(Server, {disconnect_cb,Object,EvData}, infinity). - + {try_in_order, Handlers} = + gen_server:call(Server, {disconnect_cb,Object,EvData}, infinity), + disconnect(Object, Handlers). + +disconnect(Object,[Ev|Evs]) -> + try wxEvtHandler:disconnect_impl(Object,Ev) of + true -> true; + false -> disconnect(Object, Evs); + Error -> Error + catch _:_ -> + false + end; +disconnect(_, []) -> false. + + debug_cast(1, Op, _Args, _Port) -> check_previous(), case ets:lookup(wx_debug_info,Op) of diff --git a/make/otp_release_targets.mk b/make/otp_release_targets.mk index 97e9e4bb43..e104b68991 100644 --- a/make/otp_release_targets.mk +++ b/make/otp_release_targets.mk @@ -113,7 +113,16 @@ $(HTMLDIR)/$(APPLICATION).eix: $(XML_FILES) $(SPECS_FILES) docs: $(HTMLDIR)/$(APPLICATION).eix xmllint: $(XML_FILES) - $(XMLLINT) --noout --valid --nodefdtd --loaddtd --path $(DOCGEN)/priv/dtd:$(DOCGEN)/priv/dtd_html_entities $(XML_FILES) + @echo "Running xmllint" + @BookFiles=`awk -F\" '/xi:include/ {print $$2}' book.xml`; \ + for i in $$BookFiles; do \ + if [ $$i = "notes.xml" ]; then \ + echo Checking $$i; \ + xmllint --noout --valid --nodefdtd --loaddtd --path $(DOCGEN)/priv/dtd:$(DOCGEN)/priv/dtd_html_entities $$i; \ + else\ + awk -F\" '/xi:include/ {print "echo Checking " $$2 ;print "xmllint --noout --valid --nodefdtd --loaddtd --path $(DOCGEN)/priv/dtd:$(DOCGEN)/priv/dtd_html_entities " $$2}' $$i |sh; \ + fi \ + done # ---------------------------------------------------- # Local documentation target for testing diff --git a/otp_versions.table b/otp_versions.table index 9abffe87ed..e31f5e425a 100644 --- a/otp_versions.table +++ b/otp_versions.table @@ -8,6 +8,7 @@ OTP-18.0.3 : erts-7.0.3 # asn1-4.0 common_test-1.11 compiler-6.0 cosEvent-2.2 co OTP-18.0.2 : erts-7.0.2 runtime_tools-1.9.1 # asn1-4.0 common_test-1.11 compiler-6.0 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6 debugger-4.1 dialyzer-2.8 diameter-1.10 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 et-1.5.1 eunit-2.2.10 gs-1.6 hipe-3.12 ic-4.4 inets-6.0 jinterface-1.6 kernel-4.0 megaco-3.18 mnesia-4.13 observer-2.1 odbc-2.11 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0 reltool-0.7 sasl-2.5 snmp-5.2 ssh-4.0 ssl-7.0 stdlib-2.5 syntax_tools-1.7 test_server-3.9 tools-2.8 typer-0.9.9 webtool-0.9 wx-1.4 xmerl-1.3.8 : OTP-18.0.1 : erts-7.0.1 # asn1-4.0 common_test-1.11 compiler-6.0 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6 debugger-4.1 dialyzer-2.8 diameter-1.10 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 et-1.5.1 eunit-2.2.10 gs-1.6 hipe-3.12 ic-4.4 inets-6.0 jinterface-1.6 kernel-4.0 megaco-3.18 mnesia-4.13 observer-2.1 odbc-2.11 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0 reltool-0.7 runtime_tools-1.9 sasl-2.5 snmp-5.2 ssh-4.0 ssl-7.0 stdlib-2.5 syntax_tools-1.7 test_server-3.9 tools-2.8 typer-0.9.9 webtool-0.9 wx-1.4 xmerl-1.3.8 : OTP-18.0 : asn1-4.0 common_test-1.11 compiler-6.0 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6 debugger-4.1 dialyzer-2.8 diameter-1.10 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 erts-7.0 et-1.5.1 eunit-2.2.10 gs-1.6 hipe-3.12 ic-4.4 inets-6.0 jinterface-1.6 kernel-4.0 megaco-3.18 mnesia-4.13 observer-2.1 odbc-2.11 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0 reltool-0.7 runtime_tools-1.9 sasl-2.5 snmp-5.2 ssh-4.0 ssl-7.0 stdlib-2.5 syntax_tools-1.7 test_server-3.9 tools-2.8 typer-0.9.9 webtool-0.9 wx-1.4 xmerl-1.3.8 # : +OTP-17.5.6.5 : erts-6.4.1.4 kernel-3.2.0.1 ssl-6.0.1.1 # asn1-3.0.4 common_test-1.10.1 compiler-5.0.4 cosEvent-2.1.15 cosEventDomain-1.1.14 cosFileTransfer-1.1.16 cosNotification-1.1.21 cosProperty-1.1.17 cosTime-1.1.14 cosTransactions-1.2.14 crypto-3.5 debugger-4.0.3.1 dialyzer-2.7.4 diameter-1.9.2.1 edoc-0.7.16 eldap-1.1.1 erl_docgen-0.3.7 erl_interface-3.7.20 et-1.5 eunit-2.2.9 gs-1.5.16 hipe-3.11.3 ic-4.3.6 inets-5.10.9 jinterface-1.5.12 megaco-3.17.3 mnesia-4.12.5 observer-2.0.4 odbc-2.10.22 orber-3.7.1 os_mon-2.3.1 ose-1.0.2 otp_mibs-1.0.10 parsetools-2.0.12 percept-0.8.10 public_key-0.23 reltool-0.6.6 runtime_tools-1.8.16.1 sasl-2.4.1 snmp-5.1.2 ssh-3.2.4 stdlib-2.4 syntax_tools-1.6.18 test_server-3.8.1 tools-2.7.2 typer-0.9.8 webtool-0.8.10 wx-1.3.3 xmerl-1.3.7 : OTP-17.5.6.4 : debugger-4.0.3.1 erts-6.4.1.3 # asn1-3.0.4 common_test-1.10.1 compiler-5.0.4 cosEvent-2.1.15 cosEventDomain-1.1.14 cosFileTransfer-1.1.16 cosNotification-1.1.21 cosProperty-1.1.17 cosTime-1.1.14 cosTransactions-1.2.14 crypto-3.5 dialyzer-2.7.4 diameter-1.9.2.1 edoc-0.7.16 eldap-1.1.1 erl_docgen-0.3.7 erl_interface-3.7.20 et-1.5 eunit-2.2.9 gs-1.5.16 hipe-3.11.3 ic-4.3.6 inets-5.10.9 jinterface-1.5.12 kernel-3.2 megaco-3.17.3 mnesia-4.12.5 observer-2.0.4 odbc-2.10.22 orber-3.7.1 os_mon-2.3.1 ose-1.0.2 otp_mibs-1.0.10 parsetools-2.0.12 percept-0.8.10 public_key-0.23 reltool-0.6.6 runtime_tools-1.8.16.1 sasl-2.4.1 snmp-5.1.2 ssh-3.2.4 ssl-6.0.1 stdlib-2.4 syntax_tools-1.6.18 test_server-3.8.1 tools-2.7.2 typer-0.9.8 webtool-0.8.10 wx-1.3.3 xmerl-1.3.7 : OTP-17.5.6.3 : diameter-1.9.2.1 # asn1-3.0.4 common_test-1.10.1 compiler-5.0.4 cosEvent-2.1.15 cosEventDomain-1.1.14 cosFileTransfer-1.1.16 cosNotification-1.1.21 cosProperty-1.1.17 cosTime-1.1.14 cosTransactions-1.2.14 crypto-3.5 debugger-4.0.3 dialyzer-2.7.4 edoc-0.7.16 eldap-1.1.1 erl_docgen-0.3.7 erl_interface-3.7.20 erts-6.4.1.2 et-1.5 eunit-2.2.9 gs-1.5.16 hipe-3.11.3 ic-4.3.6 inets-5.10.9 jinterface-1.5.12 kernel-3.2 megaco-3.17.3 mnesia-4.12.5 observer-2.0.4 odbc-2.10.22 orber-3.7.1 os_mon-2.3.1 ose-1.0.2 otp_mibs-1.0.10 parsetools-2.0.12 percept-0.8.10 public_key-0.23 reltool-0.6.6 runtime_tools-1.8.16.1 sasl-2.4.1 snmp-5.1.2 ssh-3.2.4 ssl-6.0.1 stdlib-2.4 syntax_tools-1.6.18 test_server-3.8.1 tools-2.7.2 typer-0.9.8 webtool-0.8.10 wx-1.3.3 xmerl-1.3.7 : OTP-17.5.6.2 : erts-6.4.1.2 runtime_tools-1.8.16.1 # asn1-3.0.4 common_test-1.10.1 compiler-5.0.4 cosEvent-2.1.15 cosEventDomain-1.1.14 cosFileTransfer-1.1.16 cosNotification-1.1.21 cosProperty-1.1.17 cosTime-1.1.14 cosTransactions-1.2.14 crypto-3.5 debugger-4.0.3 dialyzer-2.7.4 diameter-1.9.2 edoc-0.7.16 eldap-1.1.1 erl_docgen-0.3.7 erl_interface-3.7.20 et-1.5 eunit-2.2.9 gs-1.5.16 hipe-3.11.3 ic-4.3.6 inets-5.10.9 jinterface-1.5.12 kernel-3.2 megaco-3.17.3 mnesia-4.12.5 observer-2.0.4 odbc-2.10.22 orber-3.7.1 os_mon-2.3.1 ose-1.0.2 otp_mibs-1.0.10 parsetools-2.0.12 percept-0.8.10 public_key-0.23 reltool-0.6.6 sasl-2.4.1 snmp-5.1.2 ssh-3.2.4 ssl-6.0.1 stdlib-2.4 syntax_tools-1.6.18 test_server-3.8.1 tools-2.7.2 typer-0.9.8 webtool-0.8.10 wx-1.3.3 xmerl-1.3.7 : diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml index 7891f3a6b9..22627058c1 100644 --- a/system/doc/reference_manual/typespec.xml +++ b/system/doc/reference_manual/typespec.xml @@ -197,6 +197,9 @@ <cell><c>char()</c></cell><cell><c>0..16#10ffff</c></cell> </row> <row> + <cell><c>nil()</c></cell><cell><c>[]</c></cell> + </row> + <row> <cell><c>number()</c></cell><cell><c>integer() | float()</c></cell> </row> <row> @@ -312,7 +315,7 @@ <p> As seen, the basic syntax of a type is an atom followed by closed parentheses. New types are declared using <c>-type</c> and <c>-opaque</c> - compiler attributes as in the following: + attributes as in the following: </p> <pre> -type my_struct_type() :: Type. @@ -435,8 +438,8 @@ <section> <title>Specifications for Functions</title> <p> - A specification (or contract) for a function is given using the new - compiler attribute <c>-spec</c>. The general format is as follows: + A specification (or contract) for a function is given using the + <c>-spec</c> attribute. The general format is as follows: </p> <pre> -spec Module:Function(ArgType1, ..., ArgTypeN) -> ReturnType.</pre> @@ -451,7 +454,7 @@ explicitly) import these functions. </p> <p> - Within a given module, the following shorthand suffice in most cases: + Within a given module, the following shorthand suffices in most cases: </p> <pre> -spec Function(ArgType1, ..., ArgTypeN) -> ReturnType.</pre> |