From a07a1d465994427d322c523f26dcabefeb14cf01 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Magnus=20L=C3=A5ng?=
Date: Sat, 27 Feb 2016 18:49:33 +0100
Subject: erl_parse: Add parsing for new map type syntax
erl_types typesets mandatory keys with :=, and uses "..." as a shorthand
for "any() => any()". Add these to erl_parse so that all representable
types can be written in type-specs.
---
lib/stdlib/examples/erl_id_trans.erl | 4 ++++
lib/stdlib/src/erl_parse.yrl | 4 ++++
system/doc/reference_manual/typespec.xml | 32 +++++++++++++++++++++++---------
3 files changed, 31 insertions(+), 9 deletions(-)
diff --git a/lib/stdlib/examples/erl_id_trans.erl b/lib/stdlib/examples/erl_id_trans.erl
index c2e345763a..eab2ec4164 100644
--- a/lib/stdlib/examples/erl_id_trans.erl
+++ b/lib/stdlib/examples/erl_id_trans.erl
@@ -671,6 +671,10 @@ map_pair_types([{type,Line,map_field_assoc,[K,V]}|Ps]) ->
K1 = type(K),
V1 = type(V),
[{type,Line,map_field_assoc,[K1,V1]}|map_pair_types(Ps)];
+map_pair_types([{type,Line,map_field_exact,[K,V]}|Ps]) ->
+ K1 = type(K),
+ V1 = type(V),
+ [{type,Line,map_field_exact,[K1,V1]}|map_pair_types(Ps)];
map_pair_types([]) -> [].
field_types([{type,Line,field_type,[{atom,La,A},T]}|Fs]) ->
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index 6f8e5e8449..6d84f82713 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -173,6 +173,10 @@ fun_type -> '(' top_types ')' '->' top_type
map_pair_types -> map_pair_type : ['$1'].
map_pair_types -> map_pair_type ',' map_pair_types : ['$1'|'$3'].
map_pair_type -> top_type '=>' top_type : {type, ?anno('$2'), map_field_assoc,['$1','$3']}.
+map_pair_type -> top_type ':=' top_type : {type, ?anno('$2'), map_field_exact,['$1','$3']}.
+map_pair_type -> '...' : {type, ?anno('$1'), map_field_assoc,
+ [{type, ?anno('$1'), any, []},
+ {type, ?anno('$1'), any, []}]}.
field_types -> field_type : ['$1'].
field_types -> field_type ',' field_types : ['$1'|'$3'].
diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml
index c5d24a96b5..36ae252b2f 100644
--- a/system/doc/reference_manual/typespec.xml
+++ b/system/doc/reference_manual/typespec.xml
@@ -132,15 +132,18 @@
| nonempty_list(Type) %% Proper non-empty list
Map :: map() %% stands for a map of any size
- | #{} %% stands for a map of any size
+ | #{} %% stands for the empty map
| #{PairList}
Tuple :: tuple() %% stands for a tuple of any size
| {}
| {TList}
- PairList :: Type => Type
- | Type => Type, PairList
+ PairList :: Pair
+ | Pair, PairList
+
+ Pair :: Type := Type %% notes a pair that must be present
+ | Type => Type
TList :: Type
| Type, TList
@@ -169,6 +172,23 @@
elements of unknown type, is [_] (or [any()]), not [].
The notation [] specifies the singleton type for the empty list.
+
+ The general form of maps is #{PairList}. The key types in
+ PairList are allowed to overlap, and if they do, the leftmost pair
+ takes precedence. A map value does not belong to this type if contains a key
+ that is not in PairList.
+
+
+ Because it is common to end a map type with any() => any() to denote
+ that keys that do not belong to any other pair in PairList are
+ allowed, and may map to any value, the shorhand notation ... is
+ allowed as the last pair of a map type.
+
+
+ Notice that the syntactic representation of map() is #{...}
+ (or #{_ => _}, or #{any() => any()}), not #{}.
+ The notation #{} specifies the singleton type for the empty map.
+
For convenience, the following types are also built-in.
They can be thought as predefined aliases for the type unions also shown in
@@ -302,12 +322,6 @@
This is described in
Type Information in Record Declarations.
-
- Map types, both map() and #{...},
- are considered experimental during OTP 17.
- No type information of maps pairs, only the containing map types,
- are used by Dialyzer in OTP 17.
-