1%% %CopyrightBegin%
2%%
3%% Copyright Ericsson AB 2013. All Rights Reserved.
4%%
5%% Licensed under the Apache License, Version 2.0 (the "License");
6%% you may not use this file except in compliance with the License.
7%% You may obtain a copy of the License at
8%%
9%%     http://www.apache.org/licenses/LICENSE-2.0
10%%
11%% Unless required by applicable law or agreed to in writing, software
12%% distributed under the License is distributed on an "AS IS" BASIS,
13%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14%% See the License for the specific language governing permissions and
15%% limitations under the License.
16%%
17%% %CopyrightEnd%
18%%
19-module(map_SUITE).
20-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
21	init_per_group/2,end_per_group/2
22    ]).
23
24-export([
25	%% literals
26	t_build_and_match_literals/1, t_build_and_match_literals_large/1,
27	t_update_literals/1, t_update_literals_large/1,
28        t_match_and_update_literals/1, t_match_and_update_literals_large/1,
29	t_update_map_expressions/1,
30	t_update_assoc/1, t_update_assoc_large/1,
31        t_update_exact/1, t_update_exact_large/1,
32	t_guard_bifs/1,
33        t_guard_sequence/1, t_guard_sequence_large/1,
34        t_guard_update/1, t_guard_update_large/1,
35	t_guard_receive/1, t_guard_receive_large/1,
36        t_guard_fun/1,
37	t_list_comprehension/1,
38	t_map_sort_literals/1,
39	t_map_size/1, t_map_get/1,
40	t_build_and_match_aliasing/1,
41	t_is_map/1,
42
43	%% variables
44	t_build_and_match_variables/1,
45	t_update_assoc_variables/1,t_update_exact_variables/1,
46	t_nested_pattern_expressions/1,
47	t_guard_update_variables/1,
48	t_guard_sequence_variables/1,
49	t_guard_sequence_mixed/1,
50	t_frequency_table/1,
51
52	%% warnings
53	t_warn_useless_build/1,
54	t_warn_pair_key_overloaded/1,
55
56	%% not covered in 17.0-rc1
57	t_build_and_match_over_alloc/1,
58	t_build_and_match_empty_val/1,
59	t_build_and_match_val/1,
60	t_build_and_match_nil/1,
61	t_build_and_match_structure/1,
62
63	%% errors in 17.0-rc1
64	t_update_values/1,
65        t_expand_map_update/1,
66        t_export/1,
67
68	%% errors in 18
69        t_register_corruption/1,
70	t_bad_update/1,
71
72        %% new in OTP 21
73        t_reused_key_variable/1,
74
75        %% new in OTP 22
76        t_mixed_clause/1,cover_beam_trim/1,
77        t_duplicate_keys/1,
78
79        %% new in OTP 23
80        t_key_expressions/1
81    ]).
82
83suite() -> [].
84
85all() ->
86    [
87	%% literals
88	t_build_and_match_literals, t_build_and_match_literals_large,
89	t_update_literals, t_update_literals_large,
90        t_match_and_update_literals, t_match_and_update_literals_large,
91	t_update_map_expressions,
92	t_update_assoc, t_update_assoc_large,
93        t_update_exact, t_update_exact_large,
94	t_guard_bifs,
95        t_guard_sequence, t_guard_sequence_large,
96        t_guard_update, t_guard_update_large,
97	t_guard_receive, t_guard_receive_large,
98        t_guard_fun, t_list_comprehension,
99	t_map_sort_literals,
100	t_map_size, t_map_get,
101	t_build_and_match_aliasing,
102	t_is_map,
103
104	%% variables
105	t_build_and_match_variables,
106	t_update_assoc_variables,t_update_exact_variables,
107	t_nested_pattern_expressions,
108	t_guard_update_variables,
109	t_guard_sequence_variables,
110	t_guard_sequence_mixed,
111	t_frequency_table,
112
113	%% warnings
114	t_warn_useless_build,
115	t_warn_pair_key_overloaded,
116
117	%% not covered in 17.0-rc1
118	t_build_and_match_over_alloc,
119	t_build_and_match_empty_val,
120	t_build_and_match_val,
121	t_build_and_match_nil,
122	t_build_and_match_structure,
123
124	%% errors in 17.0-rc1
125	t_update_values,
126        t_expand_map_update,
127        t_export,
128
129	%% errors in 18
130        t_register_corruption,
131        t_bad_update,
132
133        %% new in OTP 21
134        t_reused_key_variable,
135
136        %% new in OTP 22
137        t_mixed_clause,cover_beam_trim,
138        t_duplicate_keys,
139
140        %% new in OTP 23
141        t_key_expressions
142    ].
143
144groups() -> [].
145
146init_per_suite(Config) ->
147    test_lib:recompile(?MODULE),
148    Config.
149
150end_per_suite(_Config) ->
151    ok.
152
153init_per_group(_GroupName, Config) -> Config.
154end_per_group(_GroupName, Config) -> Config.
155
156%% tests
157
158t_build_and_match_literals(Config) when is_list(Config) ->
159    #{} = id(#{}),
160    #{1:=a} = id(#{1=>a}),
161    #{1:=a,2:=b} = id(#{1=>a,2=>b}),
162    #{1:=a,2:=b,3:="c"} = id(#{1=>a,2=>b,3=>"c"}),
163    #{1:=a,2:=b,3:="c","4":="d"} = id(#{1=>a,2=>b,3=>"c","4"=>"d"}),
164    #{1:=a,2:=b,3:="c","4":="d",<<"5">>:=<<"e">>} =
165	id(#{1=>a,2=>b,3=>"c","4"=>"d",<<"5">>=><<"e">>}),
166    #{1:=a,2:=b,3:="c","4":="d",<<"5">>:=<<"e">>,{"6",7}:="f"} =
167	id(#{1=>a,2=>b,3=>"c","4"=>"d",<<"5">>=><<"e">>,{"6",7}=>"f"}),
168    #{1:=a,2:=b,3:="c","4":="d",<<"5">>:=<<"e">>,{"6",7}:="f",8:=g} =
169	id(#{1=>a,2=>b,3=>"c","4"=>"d",<<"5">>=><<"e">>,{"6",7}=>"f",8=>g}),
170
171    #{<<"hi all">> := 1} = id(#{<<"hi",32,"all">> => 1}),
172
173    #{a:=X,a:=X=3,b:=4} = id(#{a=>3,b=>4}), % weird but ok =)
174
175    #{ a:=#{ b:=#{c := third, b:=second}}, b:=first} =
176	id(#{ b=>first, a=>#{ b=>#{c => third, b=> second}}}),
177
178    M = #{ map_1=>#{ map_2=>#{value_3 => third}, value_2=> second}, value_1=>first},
179    M = #{ map_1:=#{ map_2:=#{value_3 := third}, value_2:= second}, value_1:=first} =
180	 id(#{ map_1=>#{ map_2=>#{value_3 => third}, value_2=> second}, value_1=>first}),
181
182    %% map key
183    #{ #{} := 42 } = id(#{ #{} => 42 }),
184    #{ #{ "a" => 3 } := 42 } = id(#{ #{ "a" => 3} => 42 }),
185
186    %% nil key
187    #{[]:=ok,1:=2} = id(#{[]=>ok,1=>2}),
188    #{1:=2,[]:=ok,1:=2} = id(#{[]=>ok,1=>2}),
189
190    %% pseudo literals
191    #{ -3 := yep } = id(#{ -3 => yep }),
192    #{ <<0:358>> := "three" } = id(#{<<0:358>> =>"three"}),
193
194    %% error case
195    {'EXIT',{{badmatch,_},_}} = (catch (#{x:=3,x:=2} = id(#{x=>3}))),
196    {'EXIT',{{badmatch,_},_}} = (catch (#{x:=2} = id(#{x=>3}))),
197    {'EXIT',{{badmatch,_},_}} = (catch (#{x:=3} = id({a,b,c}))),
198    {'EXIT',{{badmatch,_},_}} = (catch (#{x:=3} = id(#{y=>3}))),
199    {'EXIT',{{badmatch,_},_}} = (catch (#{x:=3} = id(#{x=>"three"}))),
200    {'EXIT',{{badmatch,_},_}} = (catch (#{#{"a"=>42} := 3}=id(#{#{"a"=>3}=>42}))),
201    ok.
202
203t_build_and_match_literals_large(Config) when is_list(Config) ->
204    % normal non-repeating
205    M0 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
206               11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
207               12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
208               13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
209               14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
210
211               15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
212               16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
213               17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
214               18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
215               19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" }),
216
217    #{10:=a0,20:=b0,30:="c0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M0,
218    #{11:=a1,21:=b1,31:="c1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M0,
219    #{12:=a2,22:=b2,32:="c2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M0,
220    #{13:=a3,23:=b3,33:="c3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M0,
221    #{14:=a4,24:=b4,34:="c4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M0,
222
223    #{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M0,
224    #{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M0,
225    #{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M0,
226    #{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M0,
227    #{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M0,
228
229    60 = map_size(M0),
230    60 = maps:size(M0),
231
232    % with repeating
233    M1 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
234               11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
235               12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
236               13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
237               14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
238
239               10=>na0,20=>nb0,30=>"nc0","40"=>"nd0",<<"50">>=>"ne0",{["00"]}=>"n10",
240               11=>na1,21=>nb1,31=>"nc1","41"=>"nd1",<<"51">>=>"ne1",{["01"]}=>"n11",
241               12=>na2,22=>nb2,32=>"nc2","42"=>"nd2",<<"52">>=>"ne2",{["02"]}=>"n12",
242
243               15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
244               16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
245               17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
246
247               13=>na3,23=>nb3,33=>"nc3","43"=>"nd3",<<"53">>=>"ne3",{["03"]}=>"n13",
248               14=>na4,24=>nb4,34=>"nc4","44"=>"nd4",<<"54">>=>"ne4",{["04"]}=>"n14",
249
250               18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
251               19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" }),
252
253    #{10:=na0,20:=nb0,30:="nc0","40":="nd0",<<"50">>:="ne0",{["00"]}:="n10"} = M1,
254    #{11:=na1,21:=nb1,31:="nc1","41":="nd1",<<"51">>:="ne1",{["01"]}:="n11"} = M1,
255    #{12:=na2,22:=nb2,32:="nc2","42":="nd2",<<"52">>:="ne2",{["02"]}:="n12"} = M1,
256    #{13:=na3,23:=nb3,33:="nc3","43":="nd3",<<"53">>:="ne3",{["03"]}:="n13"} = M1,
257    #{14:=na4,24:=nb4,34:="nc4","44":="nd4",<<"54">>:="ne4",{["04"]}:="n14"} = M1,
258
259    #{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M1,
260    #{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M1,
261    #{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M1,
262    #{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M1,
263    #{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M1,
264
265    60 = map_size(M1),
266    60 = maps:size(M1),
267
268    % with floats
269
270    M2 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
271               11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
272               12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
273               13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
274               14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
275
276               15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
277               16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
278               17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
279               18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
280               19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19",
281
282               10.0=>fa0,20.0=>fb0,30.0=>"fc0",
283               11.0=>fa1,21.0=>fb1,31.0=>"fc1",
284               12.0=>fa2,22.0=>fb2,32.0=>"fc2",
285               13.0=>fa3,23.0=>fb3,33.0=>"fc3",
286               14.0=>fa4,24.0=>fb4,34.0=>"fc4",
287
288               15.0=>fa5,25.0=>fb5,35.0=>"fc5",
289               16.0=>fa6,26.0=>fb6,36.0=>"fc6",
290               17.0=>fa7,27.0=>fb7,37.0=>"fc7",
291               18.0=>fa8,28.0=>fb8,38.0=>"fc8",
292               19.0=>fa9,29.0=>fb9,39.0=>"fc9"}),
293
294    #{10:=a0,20:=b0,30:="c0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M2,
295    #{11:=a1,21:=b1,31:="c1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M2,
296    #{12:=a2,22:=b2,32:="c2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M2,
297    #{13:=a3,23:=b3,33:="c3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M2,
298    #{14:=a4,24:=b4,34:="c4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M2,
299
300    #{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M2,
301    #{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M2,
302    #{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M2,
303    #{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M2,
304    #{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M2,
305
306    #{10.0:=fa0,20.0:=fb0,30.0:="fc0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M2,
307    #{11.0:=fa1,21.0:=fb1,31.0:="fc1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M2,
308    #{12.0:=fa2,22.0:=fb2,32.0:="fc2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M2,
309    #{13.0:=fa3,23.0:=fb3,33.0:="fc3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M2,
310    #{14.0:=fa4,24.0:=fb4,34.0:="fc4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M2,
311
312    #{15.0:=fa5,25.0:=fb5,35.0:="fc5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M2,
313    #{16.0:=fa6,26.0:=fb6,36.0:="fc6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M2,
314    #{17.0:=fa7,27.0:=fb7,37.0:="fc7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M2,
315    #{18.0:=fa8,28.0:=fb8,38.0:="fc8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M2,
316    #{19.0:=fa9,29.0:=fb9,39.0:="fc9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M2,
317
318    90 = map_size(M2),
319    90 = maps:size(M2),
320
321    % with bignums
322    M3 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
323               11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
324               12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
325               13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
326               14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
327
328               15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
329               16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
330               17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
331               18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
332               19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19",
333
334               10.0=>fa0,20.0=>fb0,30.0=>"fc0",
335               11.0=>fa1,21.0=>fb1,31.0=>"fc1",
336               12.0=>fa2,22.0=>fb2,32.0=>"fc2",
337               13.0=>fa3,23.0=>fb3,33.0=>"fc3",
338               14.0=>fa4,24.0=>fb4,34.0=>"fc4",
339
340               15.0=>fa5,25.0=>fb5,35.0=>"fc5",
341               16.0=>fa6,26.0=>fb6,36.0=>"fc6",
342               17.0=>fa7,27.0=>fb7,37.0=>"fc7",
343               18.0=>fa8,28.0=>fb8,38.0=>"fc8",
344               19.0=>fa9,29.0=>fb9,39.0=>"fc9",
345
346               36893488147419103232=>big1,  73786976294838206464=>big2,
347               147573952589676412928=>big3, 18446744073709551616=>big4,
348               4294967296=>big5,            8589934592=>big6,
349               4294967295=>big7,            67108863=>big8
350             }),
351
352    #{10:=a0,20:=b0,30:="c0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M3,
353    #{11:=a1,21:=b1,31:="c1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M3,
354    #{12:=a2,22:=b2,32:="c2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M3,
355    #{13:=a3,23:=b3,33:="c3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M3,
356    #{14:=a4,24:=b4,34:="c4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M3,
357
358    #{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M3,
359    #{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M3,
360    #{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M3,
361    #{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M3,
362    #{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M3,
363
364    #{10.0:=fa0,20.0:=fb0,30.0:="fc0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M3,
365    #{11.0:=fa1,21.0:=fb1,31.0:="fc1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M3,
366    #{12.0:=fa2,22.0:=fb2,32.0:="fc2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M3,
367    #{13.0:=fa3,23.0:=fb3,33.0:="fc3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M3,
368    #{14.0:=fa4,24.0:=fb4,34.0:="fc4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M3,
369
370    #{15.0:=fa5,25.0:=fb5,35.0:="fc5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M3,
371    #{16.0:=fa6,26.0:=fb6,36.0:="fc6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M3,
372    #{17.0:=fa7,27.0:=fb7,37.0:="fc7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M3,
373    #{18.0:=fa8,28.0:=fb8,38.0:="fc8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M3,
374    #{19.0:=fa9,29.0:=fb9,39.0:="fc9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M3,
375
376    #{36893488147419103232:=big1,67108863:=big8,"45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M3,
377    #{147573952589676412928:=big3,8589934592:=big6,"46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M3,
378    #{4294967296:=big5,18446744073709551616:=big4,"47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M3,
379    #{4294967295:=big7,73786976294838206464:=big2,"48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M3,
380
381    98 = map_size(M3),
382    98 = maps:size(M3),
383
384    %% with maps
385
386    M4 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
387               11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
388               12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
389               13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
390               14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
391
392               15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
393               16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
394               17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
395               18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
396               19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19",
397
398               10.0=>fa0,20.0=>fb0,30.0=>"fc0",
399               11.0=>fa1,21.0=>fb1,31.0=>"fc1",
400               12.0=>fa2,22.0=>fb2,32.0=>"fc2",
401               13.0=>fa3,23.0=>fb3,33.0=>"fc3",
402               14.0=>fa4,24.0=>fb4,34.0=>"fc4",
403
404               15.0=>fa5,25.0=>fb5,35.0=>"fc5",
405               16.0=>fa6,26.0=>fb6,36.0=>"fc6",
406               17.0=>fa7,27.0=>fb7,37.0=>"fc7",
407               18.0=>fa8,28.0=>fb8,38.0=>"fc8",
408               19.0=>fa9,29.0=>fb9,39.0=>"fc9",
409
410               #{ one => small, map => key } => "small map key 1",
411               #{ second => small, map => key } => "small map key 2",
412               #{ third => small, map => key } => "small map key 3",
413
414               #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
415                  11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
416                  12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
417                  13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
418                  14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
419
420                  15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
421                  16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
422                  17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
423                  18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
424                  19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
425
426               #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
427                  11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
428                  12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
429                  13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
430                  14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
431
432                  15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
433                  k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
434                  17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
435                  18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
436                  19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 2" }),
437
438    #{10:=a0,20:=b0,30:="c0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M4,
439    #{11:=a1,21:=b1,31:="c1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M4,
440    #{12:=a2,22:=b2,32:="c2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M4,
441    #{13:=a3,23:=b3,33:="c3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M4,
442    #{14:=a4,24:=b4,34:="c4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M4,
443
444    #{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M4,
445    #{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M4,
446    #{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M4,
447    #{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M4,
448    #{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M4,
449
450    #{ #{ one => small, map => key }    := "small map key 1",
451       #{ second => small, map => key } := "small map key 2",
452       #{ third => small, map => key }  := "small map key 3" } = M4,
453
454    #{ #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
455          11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
456          12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
457          13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
458          14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
459
460          15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
461          16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
462          17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
463          18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
464          19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } := "large map key 1",
465
466       #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
467          11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
468          12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
469          13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
470          14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
471
472          15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
473          k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
474          17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
475          18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
476          19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } := "large map key 2" } = M4,
477
478
479    #{ 15:=V1,25:=b5,35:=V2,"45":="d5",<<"55">>:=V3,{["05"]}:="15",
480       #{ one => small, map => key }    := "small map key 1",
481       #{ second => small, map => key } := V4,
482       #{ third => small, map => key }  := "small map key 3",
483       #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
484          11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
485          12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
486          13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
487          14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
488
489          15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
490          16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
491          17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
492          18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
493          19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } := V5 } = M4,
494
495    a5   = V1,
496    "c5" = V2,
497    "e5" = V3,
498    "small map key 2" = V4,
499    "large map key 1" = V5,
500
501    95 = map_size(M4),
502    95 = maps:size(M4),
503
504    % call for value
505
506    M5 = id(#{ 10=>id(a0),20=>b0,30=>id("c0"),"40"=>"d0",<<"50">>=>id("e0"),{["00"]}=>"10",
507               11=>id(a1),21=>b1,31=>id("c1"),"41"=>"d1",<<"51">>=>id("e1"),{["01"]}=>"11",
508               12=>id(a2),22=>b2,32=>id("c2"),"42"=>"d2",<<"52">>=>id("e2"),{["02"]}=>"12",
509               13=>id(a3),23=>b3,33=>id("c3"),"43"=>"d3",<<"53">>=>id("e3"),{["03"]}=>"13",
510               14=>id(a4),24=>b4,34=>id("c4"),"44"=>"d4",<<"54">>=>id("e4"),{["04"]}=>"14",
511
512               15=>id(a5),25=>b5,35=>id("c5"),"45"=>"d5",<<"55">>=>id("e5"),{["05"]}=>"15",
513               16=>id(a6),26=>b6,36=>id("c6"),"46"=>"d6",<<"56">>=>id("e6"),{["06"]}=>"16",
514               17=>id(a7),27=>b7,37=>id("c7"),"47"=>"d7",<<"57">>=>id("e7"),{["07"]}=>"17",
515               18=>id(a8),28=>b8,38=>id("c8"),"48"=>"d8",<<"58">>=>id("e8"),{["08"]}=>"18",
516               19=>id(a9),29=>b9,39=>id("c9"),"49"=>"d9",<<"59">>=>id("e9"),{["09"]}=>"19",
517
518               10.0=>fa0,20.0=>id(fb0),30.0=>id("fc0"),
519               11.0=>fa1,21.0=>id(fb1),31.0=>id("fc1"),
520               12.0=>fa2,22.0=>id(fb2),32.0=>id("fc2"),
521               13.0=>fa3,23.0=>id(fb3),33.0=>id("fc3"),
522               14.0=>fa4,24.0=>id(fb4),34.0=>id("fc4"),
523
524               15.0=>fa5,25.0=>id(fb5),35.0=>id("fc5"),
525               16.0=>fa6,26.0=>id(fb6),36.0=>id("fc6"),
526               17.0=>fa7,27.0=>id(fb7),37.0=>id("fc7"),
527               18.0=>fa8,28.0=>id(fb8),38.0=>id("fc8"),
528               19.0=>fa9,29.0=>id(fb9),39.0=>id("fc9"),
529
530               #{ one => small, map => key } => id("small map key 1"),
531               #{ second => small, map => key } => "small map key 2",
532               #{ third => small, map => key } => "small map key 3",
533
534               #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
535                  11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
536                  12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
537                  13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
538                  14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
539
540                  15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
541                  16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
542                  17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
543                  18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
544                  19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
545
546               #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
547                  11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
548                  12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
549                  13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
550                  14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
551
552                  15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
553                  k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
554                  17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
555                  18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
556                  19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => id("large map key 2") }),
557
558    #{10:=a0,20:=b0,30:="c0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M5,
559    #{11:=a1,21:=b1,31:="c1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M5,
560    #{12:=a2,22:=b2,32:="c2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M5,
561    #{13:=a3,23:=b3,33:="c3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M5,
562    #{14:=a4,24:=b4,34:="c4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M5,
563
564    #{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M5,
565    #{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M5,
566    #{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M5,
567    #{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M5,
568    #{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M5,
569
570    #{ #{ one => small, map => key }    := "small map key 1",
571       #{ second => small, map => key } := "small map key 2",
572       #{ third => small, map => key }  := "small map key 3" } = M5,
573
574    #{ #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
575          11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
576          12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
577          13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
578          14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
579
580          15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
581          16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
582          17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
583          18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
584          19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } := "large map key 1",
585
586       #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
587          11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
588          12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
589          13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
590          14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
591
592          15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
593          k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
594          17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
595          18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
596          19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } := "large map key 2" } = M5,
597
598    95 = map_size(M5),
599    95 = maps:size(M5),
600
601    %% remember
602
603    #{10:=a0,20:=b0,30:="c0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M0,
604    #{11:=a1,21:=b1,31:="c1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M0,
605    #{12:=a2,22:=b2,32:="c2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M0,
606    #{13:=a3,23:=b3,33:="c3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M0,
607    #{14:=a4,24:=b4,34:="c4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M0,
608
609    #{10:=na0,20:=nb0,30:="nc0","40":="nd0",<<"50">>:="ne0",{["00"]}:="n10"} = M1,
610    #{11:=na1,21:=nb1,31:="nc1","41":="nd1",<<"51">>:="ne1",{["01"]}:="n11"} = M1,
611    #{12:=na2,22:=nb2,32:="nc2","42":="nd2",<<"52">>:="ne2",{["02"]}:="n12"} = M1,
612    #{13:=na3,23:=nb3,33:="nc3","43":="nd3",<<"53">>:="ne3",{["03"]}:="n13"} = M1,
613    #{14:=na4,24:=nb4,34:="nc4","44":="nd4",<<"54">>:="ne4",{["04"]}:="n14"} = M1,
614
615    #{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M1,
616    #{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M1,
617    #{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M1,
618    #{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M1,
619    #{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M1,
620
621    #{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M2,
622    #{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M2,
623    #{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M2,
624    #{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M2,
625    #{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M2,
626
627    #{10.0:=fa0,20.0:=fb0,30.0:="fc0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M2,
628    #{11.0:=fa1,21.0:=fb1,31.0:="fc1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M2,
629    #{12.0:=fa2,22.0:=fb2,32.0:="fc2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M2,
630    #{13.0:=fa3,23.0:=fb3,33.0:="fc3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M2,
631    #{14.0:=fa4,24.0:=fb4,34.0:="fc4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M2,
632
633    #{15:=a5,25:=b5,35:="c5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M3,
634    #{16:=a6,26:=b6,36:="c6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M3,
635    #{17:=a7,27:=b7,37:="c7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M3,
636    #{18:=a8,28:=b8,38:="c8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M3,
637    #{19:=a9,29:=b9,39:="c9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M3,
638
639    #{10.0:=fa0,20.0:=fb0,30.0:="fc0","40":="d0",<<"50">>:="e0",{["00"]}:="10"} = M3,
640    #{11.0:=fa1,21.0:=fb1,31.0:="fc1","41":="d1",<<"51">>:="e1",{["01"]}:="11"} = M3,
641    #{12.0:=fa2,22.0:=fb2,32.0:="fc2","42":="d2",<<"52">>:="e2",{["02"]}:="12"} = M3,
642    #{13.0:=fa3,23.0:=fb3,33.0:="fc3","43":="d3",<<"53">>:="e3",{["03"]}:="13"} = M3,
643    #{14.0:=fa4,24.0:=fb4,34.0:="fc4","44":="d4",<<"54">>:="e4",{["04"]}:="14"} = M3,
644
645    #{15.0:=fa5,25.0:=fb5,35.0:="fc5","45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M3,
646    #{16.0:=fa6,26.0:=fb6,36.0:="fc6","46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M3,
647    #{17.0:=fa7,27.0:=fb7,37.0:="fc7","47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M3,
648    #{18.0:=fa8,28.0:=fb8,38.0:="fc8","48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M3,
649    #{19.0:=fa9,29.0:=fb9,39.0:="fc9","49":="d9",<<"59">>:="e9",{["09"]}:="19"} = M3,
650
651    #{36893488147419103232:=big1,67108863:=big8,"45":="d5",<<"55">>:="e5",{["05"]}:="15"} = M3,
652    #{147573952589676412928:=big3,8589934592:=big6,"46":="d6",<<"56">>:="e6",{["06"]}:="16"} = M3,
653    #{4294967296:=big5,18446744073709551616:=big4,"47":="d7",<<"57">>:="e7",{["07"]}:="17"} = M3,
654    #{4294967295:=big7,73786976294838206464:=big2,"48":="d8",<<"58">>:="e8",{["08"]}:="18"} = M3,
655
656    ok.
657
658
659t_build_and_match_aliasing(Config) when is_list(Config) ->
660    M1 = id(#{a=>1,b=>2,c=>3,d=>4}),
661    #{c:=C1=_=_=C2} = M1,
662    true = C1 =:= C2,
663    #{a:=A,a:=A,a:=A,b:=B,b:=B} = M1,
664    #{a:=A,a:=A,a:=A,b:=B,b:=B,b:=2} = M1,
665    #{a:=A=1,a:=A,a:=A,b:=B=2,b:=B,b:=2} = M1,
666    #{c:=C1, c:=_, c:=3, c:=_, c:=C2} = M1,
667    #{c:=C=_=3=_=C} = M1,
668
669    M2 = id(#{"a"=>1,"b"=>2,"c"=>3,"d"=>4}),
670    #{"a":=A2,"a":=A2,"a":=A2,"b":=B2,"b":=B2,"b":=2} = M2,
671    #{"a":=_,"a":=_,"a":=_,"b":=_,"b":=_,"b":=2} = M2,
672
673    #{a:=A1,a:=A1,a:=A1,b:=B1,b:=B1} = #{a:=A1,a:=A1,a:=A1,b:=B1,b:=B1,b:=2} = M1,
674    #{"a":=A3,"b":=B3} = #{"a":=A3,"a":=A3} = #{"b":=B3,"b":=2} = M2,
675
676    #{"a":=1,"b":=2,"c":=3,"d":=4} = #{"a":=A4,"b":=B4} = #{"a":=A4,"a":=A4} = #{"b":=B4,"d":=4} = M2,
677    #{"a":=A5,"b":=B5} = #{"a":=A5,"a":=A5} = #{"b":=B5,"d":=4} = #{"a":=1,"b":=2,"c":=3,"d":=4} = M2,
678    #{"a":=_,"b":=_} = #{"a":=_,"a":=_} = #{"b":=_,"d":=4} = #{"a":=1,"b":=2,"c":=3,"d":=4} = M2,
679
680    M3 = id(#{<<12:300>>=>1,<<13:300>>=>2}),
681    #{<<12:300>> := V1, <<13:300>> := V2} = #{<<13:300>> := V2, <<12:300>> := V1} = M3,
682    #{<<12:300>> := 1, <<13:300>> := 2} = #{<<13:300>> := _, <<12:300>> := _} = M3,
683    #{<<13:300>> := _, <<12:300>> := _} = #{<<12:300>> := 1, <<13:300>> := 2} = M3,
684
685    ok.
686
687t_map_size(Config) when is_list(Config) ->
688    0 = map_size(id(#{})),
689    1 = map_size(id(#{a=>1})),
690    1 = map_size(id(#{a=>"wat"})),
691    2 = map_size(id(#{a=>1, b=>2})),
692    3 = map_size(id(#{a=>1, b=>2, b=>"3","33"=><<"n">>})),
693
694    true = map_is_size(#{a=>1}, 1),
695    true = map_is_size(#{a=>1, a=>2}, 1),
696    M = #{ "a" => 1, "b" => 2},
697    true  = map_is_size(M, 2),
698    false = map_is_size(M, 3),
699    true  = map_is_size(M#{ "a" => 2}, 2),
700    false = map_is_size(M#{ "c" => 2}, 2),
701
702    %% Error cases.
703    {'EXIT',{{badmap,[]},_}} = (catch map_size([])),
704    {'EXIT',{{badmap,<<1,2,3>>},_}} = (catch map_size(<<1,2,3>>)),
705    {'EXIT',{{badmap,1},_}} = (catch map_size(1)),
706    ok.
707
708map_is_size(M,N) when map_size(M) =:= N -> true;
709map_is_size(_,_) -> false.
710
711t_map_get(Config) when is_list(Config) ->
712    1 = map_get(a, id(#{a=>1})),
713
714    {'EXIT',{{badkey,a},_}} = (catch map_get(a, #{})),
715    {'EXIT',{{badkey,a},_}} = (catch map_get(a, #{b=>1})),
716
717    M = #{"a"=>1, "b" => 2},
718    true = check_map_value(M, "a", 1),
719    false = check_map_value(M, "b", 1),
720    true = check_map_value(M#{"c"=>2}, "c", 2),
721    false = check_map_value(M#{"a"=>5}, "a", 1),
722
723    {'EXIT',{{badmap,[]},_}} = (catch map_get(a, [])),
724    {'EXIT',{{badmap,<<1,2,3>>},_}} = (catch map_get(a, <<1,2,3>>)),
725    {'EXIT',{{badmap,1},_}} = (catch map_get(a, 1)),
726
727    %% Test that beam_validator understands that NewMap is
728    %% a map after seeing map_get(a, NewMap).
729    NewMap = id(#{a=>b}),
730    b = map_get(a, NewMap),
731    #{a:=z} = NewMap#{a:=z},
732    ok.
733
734check_map_value(Map, Key, Value) when map_get(Key, Map) =:= Value -> true;
735check_map_value(_, _, _) -> false.
736
737t_is_map(Config) when is_list(Config) ->
738    true = is_map(#{}),
739    true = is_map(#{a=>1}),
740    false = is_map({a,b}),
741    false = is_map(x),
742    if is_map(#{}) -> ok end,
743    if is_map(#{b=>1}) -> ok end,
744    if not is_map([1,2,3]) -> ok end,
745    if not is_map(x) -> ok end,
746
747    ok = do_t_is_map(map, #{}),
748    error = do_t_is_map(map, {a,b,c}),
749    ok = do_t_is_map(number, 42),
750    ok = do_t_is_map(number, 42.0),
751    error = do_t_is_map(number, {a,b,c}),
752    ok.
753
754do_t_is_map(What, X) ->
755    B = case What of
756            map ->
757                %% Cover conversion of is_map/1 BIF to test instruction
758                %% in beam_utils:bif_to_test/3.
759                is_map(X);
760            number ->
761                is_number(X)
762        end,
763    case B of
764        true -> ok;
765        false -> error
766    end.
767
768% test map updates without matching
769t_update_literals(Config) when is_list(Config) ->
770    Map = #{x=>1,y=>2,z=>3,q=>4},
771    #{x:="d",q:="4"} = loop_update_literals_x_q(Map, [
772		{"a","1"},{"b","2"},{"c","3"},{"d","4"}
773	]),
774    ok.
775
776t_update_literals_large(Config) when is_list(Config) ->
777    Map = id(#{ 10=>id(a0),20=>b0,30=>id("c0"),"40"=>"d0",<<"50">>=>id("e0"),{["00"]}=>"10",
778                11=>id(a1),21=>b1,31=>id("c1"),"41"=>"d1",<<"51">>=>id("e1"),{["01"]}=>"11",
779                12=>id(a2),22=>b2,32=>id("c2"),"42"=>"d2",<<"52">>=>id("e2"),{["02"]}=>"12",
780                13=>id(a3),23=>b3,33=>id("c3"),"43"=>"d3",<<"53">>=>id("e3"),{["03"]}=>"13",
781                14=>id(a4),24=>b4,34=>id("c4"),"44"=>"d4",<<"54">>=>id("e4"),{["04"]}=>"14",
782
783                15=>id(a5),25=>b5,35=>id("c5"),"45"=>"d5",<<"55">>=>id("e5"),{["05"]}=>"15",
784                16=>id(a6),26=>b6,36=>id("c6"),"46"=>"d6",<<"56">>=>id("e6"),{["06"]}=>"16",
785                17=>id(a7),27=>b7,37=>id("c7"),"47"=>"d7",<<"57">>=>id("e7"),{["07"]}=>"17",
786                18=>id(a8),28=>b8,38=>id("c8"),"48"=>"d8",<<"58">>=>id("e8"),{["08"]}=>"18",
787                19=>id(a9),29=>b9,39=>id("c9"),"49"=>"d9",<<"59">>=>id("e9"),{["09"]}=>"19",
788
789                10.0=>fa0,20.0=>id(fb0),30.0=>id("fc0"),
790                11.0=>fa1,21.0=>id(fb1),31.0=>id("fc1"),
791                12.0=>fa2,22.0=>id(fb2),32.0=>id("fc2"),
792                13.0=>fa3,23.0=>id(fb3),33.0=>id("fc3"),
793                14.0=>fa4,24.0=>id(fb4),34.0=>id("fc4"),
794
795                15.0=>fa5,25.0=>id(fb5),35.0=>id("fc5"),
796                16.0=>fa6,26.0=>id(fb6),36.0=>id("fc6"),
797                17.0=>fa7,27.0=>id(fb7),37.0=>id("fc7"),
798                18.0=>fa8,28.0=>id(fb8),38.0=>id("fc8"),
799                19.0=>fa9,29.0=>id(fb9),39.0=>id("fc9"),
800
801                #{ one => small, map => key } => id("small map key 1"),
802                #{ second => small, map => key } => "small map key 2",
803                #{ third => small, map => key } => "small map key 3",
804
805                #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
806                   11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
807                   12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
808                   13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
809                   14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
810
811                   15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
812                   16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
813                   17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
814                   18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
815                   19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
816
817                #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
818                   11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
819                   12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
820                   13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
821                   14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
822
823                   15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
824                   k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
825                   17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
826                   18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
827                   19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => id("large map key 2") }),
828
829    #{x:="d",q:="4"} = loop_update_literals_x_q(Map, [
830		{"a","1"},{"b","2"},{"c","3"},{"d","4"}
831	]),
832    ok.
833
834
835
836loop_update_literals_x_q(Map, []) -> Map;
837loop_update_literals_x_q(Map, [{X,Q}|Vs]) ->
838    loop_update_literals_x_q(Map#{q=>Q,x=>X},Vs).
839
840% test map updates with matching
841t_match_and_update_literals(Config) when is_list(Config) ->
842    Map = #{ x=>0,y=>"untouched",z=>"also untouched",q=>1,
843             #{ "one" => small, map => key } => "small map key 1" },
844
845    #{x:=16,q:=21,y:="untouched",z:="also untouched"} = loop_match_and_update_literals_x_q(Map, [
846	    {1,2},{3,4},{5,6},{7,8}
847	]),
848    M0 = id(#{ "hi" => "hello", int => 3, <<"key">> => <<"value">>,
849	    4 => number, 18446744073709551629 => wat}),
850    M1 = id(#{}),
851    M2 = M1#{ "hi" => "hello", int => 3, <<"key">> => <<"value">>,
852	4 => number, 18446744073709551629 => wat},
853    M0 = M2,
854
855    #{ 4 := another_number, int := 3 } = M2#{ 4 => another_number },
856    ok.
857
858t_match_and_update_literals_large(Config) when is_list(Config) ->
859    Map = id(#{ 10=>id(a0),20=>b0,30=>id("c0"),"40"=>"d0",<<"50">>=>id("e0"),{["00"]}=>"10",
860                11=>id(a1),21=>b1,31=>id("c1"),"41"=>"d1",<<"51">>=>id("e1"),{["01"]}=>"11",
861                12=>id(a2),22=>b2,32=>id("c2"),"42"=>"d2",<<"52">>=>id("e2"),{["02"]}=>"12",
862                13=>id(a3),23=>b3,33=>id("c3"),"43"=>"d3",<<"53">>=>id("e3"),{["03"]}=>"13",
863                14=>id(a4),24=>b4,34=>id("c4"),"44"=>"d4",<<"54">>=>id("e4"),{["04"]}=>"14",
864
865                15=>id(a5),25=>b5,35=>id("c5"),"45"=>"d5",<<"55">>=>id("e5"),{["05"]}=>"15",
866                16=>id(a6),26=>b6,36=>id("c6"),"46"=>"d6",<<"56">>=>id("e6"),{["06"]}=>"16",
867                17=>id(a7),27=>b7,37=>id("c7"),"47"=>"d7",<<"57">>=>id("e7"),{["07"]}=>"17",
868                18=>id(a8),28=>b8,38=>id("c8"),"48"=>"d8",<<"58">>=>id("e8"),{["08"]}=>"18",
869                19=>id(a9),29=>b9,39=>id("c9"),"49"=>"d9",<<"59">>=>id("e9"),{["09"]}=>"19",
870
871                10.0=>fa0,20.0=>id(fb0),30.0=>id("fc0"),
872                11.0=>fa1,21.0=>id(fb1),31.0=>id("fc1"),
873                12.0=>fa2,22.0=>id(fb2),32.0=>id("fc2"),
874                13.0=>fa3,23.0=>id(fb3),33.0=>id("fc3"),
875                14.0=>fa4,24.0=>id(fb4),34.0=>id("fc4"),
876
877                15.0=>fa5,25.0=>id(fb5),35.0=>id("fc5"),
878                16.0=>fa6,26.0=>id(fb6),36.0=>id("fc6"),
879                17.0=>fa7,27.0=>id(fb7),37.0=>id("fc7"),
880                18.0=>fa8,28.0=>id(fb8),38.0=>id("fc8"),
881                19.0=>fa9,29.0=>id(fb9),39.0=>id("fc9"),
882
883                x=>0,y=>"untouched",z=>"also untouched",q=>1,
884
885                #{ "one" => small, map => key } => id("small map key 1"),
886                #{ second => small, map => key } => "small map key 2",
887                #{ third => small, map => key } => "small map key 3",
888
889                #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
890                   11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
891                   12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
892                   13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
893                   14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
894
895                   15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
896                   16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
897                   17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
898                   18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
899                   19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
900
901                #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
902                   11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
903                   12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
904                   13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
905                   14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
906
907                   15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
908                   k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
909                   17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
910                   18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
911                   19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => id("large map key 2") }),
912
913    #{x:=16,q:=21,y:="untouched",z:="also untouched"} = loop_match_and_update_literals_x_q(Map, [
914	    {1,2},{3,4},{5,6},{7,8}
915	]),
916    M0 = id(Map#{ "hi" => "hello", int => 3, <<"key">> => <<"value">>,
917                  4 => number, 18446744073709551629 => wat}),
918    M1 = id(Map#{}),
919    M2 = M1#{ "hi" => "hello", int => 3, <<"key">> => <<"value">>,
920              4 => number, 18446744073709551629 => wat},
921    M0 = M2,
922
923    #{ 4 := another_number, int := 3 } = M2#{ 4 => another_number },
924    ok.
925
926loop_match_and_update_literals_x_q(Map, []) -> Map;
927loop_match_and_update_literals_x_q(#{ q:=Q0, x:=X0,
928                                     #{ "one" => small, map => key } := "small map key 1" } = Map, [{X,Q}|Vs]) ->
929    loop_match_and_update_literals_x_q(Map#{q=>Q0+Q,x=>X0+X},Vs).
930
931
932t_update_map_expressions(Config) when is_list(Config) ->
933    M = maps:new(),
934    X = id(fondue),
935    M1 = #{ a := 1 } = M#{a => 1},
936    #{ b := {X} } = M1#{ a := 1, b => {X} },
937
938    #{ b := 2 } = (maps:new())#{ b => 2 },
939
940    #{ a :=42, b:=42, c:=42 } = (maps:from_list([{a,1},{b,2},{c,3}]))#{ a := 42, b := 42, c := 42 },
941    #{ "a" :=1, "b":=42, "c":=42 } = (maps:from_list([{"a",1},{"b",2}]))#{ "b" := 42, "c" => 42 },
942
943    %% Test need to be in a fun.
944    %% This tests that let expr optimisation in sys_core_fold
945    %% covers maps correctly.
946    F = fun() ->
947	    M0 = id(#{ "a" => [1,2,3] }),
948	    #{ "a" := _ } = M0,
949	    M0#{ "a" := b }
950    end,
951
952    #{ "a" := b } = F(),
953
954    %% Error cases.
955    {'EXIT',{{badmap,<<>>},_}} = (catch (id(<<>>))#{ a := 42, b => 2 }),
956    {'EXIT',{{badmap,[]},_}} = (catch (id([]))#{ a := 42, b => 2 }),
957    {'EXIT',{{badmap,_},_}} =
958	(catch (fun t_update_map_expressions/1)#{u => 42}),
959
960    ok.
961
962
963t_update_assoc(Config) when is_list(Config) ->
964    M0 = id(#{1=>a,2=>b,3.0=>c,4=>d,5=>e}),
965
966    M1 = M0#{1=>42,2=>100,4=>[a,b,c]},
967    #{1:=42,2:=100,3.0:=c,4:=[a,b,c],5:=e} = M1,
968    #{1:=42,2:=b,4:=d,5:=e,2.0:=100,3.0:=c,4.0:=[a,b,c]} = M0#{1.0=>float,1:=42,2.0=>wrong,2.0=>100,4.0=>[a,b,c]},
969
970    M2 = M0#{3.0=>new},
971    #{1:=a,2:=b,3.0:=new,4:=d,5:=e} = M2,
972    M2 = M0#{3.0:=wrong,3.0=>new},
973
974    % Can't handle directly yet
975    Bin = <<0:257>>,
976    #{ Bin := val } = id(M0#{<<0:257>> => val}), %% binary limitation
977
978    %% Errors cases.
979    BadMap = id(badmap),
980    {'EXIT',{{badmap,BadMap},_}} = (catch BadMap#{nonexisting=>val}),
981    {'EXIT',{{badmap,<<>>},_}} = (catch <<>>#{nonexisting=>val}),
982    F1 = fun() ->
983                 0 #{part => V = false},
984                 V
985         end,
986    {'EXIT',{{badmap,0},_}} = (catch F1()),
987    F2 = fun() ->
988                 case 42 of
989                     V ->
990                         [];
991                     power ->
992                         []#{key =>
993                                 receive
994                                     V -> false
995                                 end}
996                 end,
997                 V
998         end,
999    42 = F2(),
1000
1001    %% Evaluation order.
1002    {'EXIT',{blurf,_}} =
1003	(catch BadMap#{whatever=>id(error(blurf))}),
1004    {'EXIT',{blurf,_}} =
1005	(catch BadMap#{id(error(blurf))=>whatever}),
1006    ok.
1007
1008t_update_assoc_large(Config) when is_list(Config) ->
1009    M0 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
1010               11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
1011               12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
1012               13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
1013               14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
1014
1015               15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
1016               16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
1017               17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
1018               18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
1019               19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19",
1020
1021               10.0=>fa0,20.0=>fb0,30.0=>"fc0",
1022               11.0=>fa1,21.0=>fb1,31.0=>"fc1",
1023               12.0=>fa2,22.0=>fb2,32.0=>"fc2",
1024               13.0=>fa3,23.0=>fb3,33.0=>"fc3",
1025               14.0=>fa4,24.0=>fb4,34.0=>"fc4",
1026
1027               15.0=>fa5,25.0=>fb5,35.0=>"fc5",
1028               16.0=>fa6,26.0=>fb6,36.0=>"fc6",
1029               17.0=>fa7,27.0=>fb7,37.0=>"fc7",
1030               18.0=>fa8,28.0=>fb8,38.0=>"fc8",
1031               19.0=>fa9,29.0=>fb9,39.0=>"fc9",
1032
1033               #{ one => small, map => key } => "small map key 1",
1034               #{ second => small, map => key } => "small map key 2",
1035               #{ third => small, map => key } => "small map key 3",
1036
1037               #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
1038                  11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
1039                  12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
1040                  13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
1041                  14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
1042
1043                  15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
1044                  16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
1045                  17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
1046                  18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
1047                  19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
1048
1049               #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
1050                  11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
1051                  12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
1052                  13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
1053                  14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
1054
1055                  15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
1056                  k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
1057                  17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
1058                  18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
1059                  19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 2" }),
1060
1061
1062    M1 = M0#{1=>42,2=>100,4=>[a,b,c]},
1063    #{1:=42,2:=100,10.0:=fa0,4:=[a,b,c],25:=b5} = M1,
1064    #{ 10:=43, 24:=b4, 15:=a5, 35:="c5", 2.0:=100, 13.0:=fa3, 4.0:=[a,b,c]} =
1065        M0#{1.0=>float,10:=43,2.0=>wrong,2.0=>100,4.0=>[a,b,c]},
1066
1067    M2 = M0#{13.0=>new},
1068    #{10:=a0,20:=b0,13.0:=new,"40":="d0",<<"50">>:="e0"} = M2,
1069    M2 = M0#{13.0:=wrong,13.0=>new},
1070
1071    %% Errors cases.
1072    BadMap = id({no,map}),
1073    {'EXIT',{{badmap,BadMap},_}} = (catch BadMap#{nonexisting=>M0}),
1074    ok.
1075
1076
1077
1078t_update_exact(Config) when is_list(Config) ->
1079    M0 = id(#{1=>a,2=>b,3.0=>c,4=>d,5=>e}),
1080
1081    M1 = M0#{1:=42,2:=100,4:=[a,b,c]},
1082    #{1:=42,2:=100,3.0:=c,4:=[a,b,c],5:=e} = M1,
1083    M1 = M0#{1:=wrong,1=>42,2=>wrong,2:=100,4:=[a,b,c]},
1084
1085    M2 = M0#{3.0:=new},
1086    #{1:=a,2:=b,3.0:=new,4:=d,5:=e} = M2,
1087    M2 = M0#{3.0=>wrong,3.0:=new},
1088    true = M2 =/= M0#{3=>right,3.0:=new},
1089    #{ 3 := right, 3.0 := new } = M0#{3=>right,3.0:=new},
1090
1091    M3 = id(#{ 1 => val}),
1092    #{1 := update2,1.0 := new_val4} = M3#{
1093	1.0 => new_val1, 1 := update, 1=> update3,
1094	1 := update2, 1.0 := new_val2, 1.0 => new_val3,
1095	1.0 => new_val4 },
1096
1097    %% Errors cases.
1098    {'EXIT',{{badmap,nil},_}} = (catch ((id(nil))#{ a := b })),
1099    {'EXIT',{{badkey,nonexisting},_}} = (catch M0#{nonexisting:=val}),
1100    {'EXIT',{{badkey,1.0},_}} = (catch M0#{1.0:=v,1.0=>v2}),
1101    {'EXIT',{{badkey,42},_}} = (catch M0#{42.0:=v,42:=v2}),
1102    {'EXIT',{{badkey,42.0},_}} = (catch M0#{42=>v1,42.0:=v2,42:=v3}),
1103    {'EXIT',{{badmap,<<>>},_}} = (catch <<>>#{nonexisting:=val}),
1104    {'EXIT',{{badkey,<<0:257>>},_}} =
1105	(catch M0#{<<0:257>> := val}),		%limitation
1106
1107    %% A workaround for a bug allowed an empty map to be updated.
1108    {'EXIT',{{badkey,a},_}} = (catch (id(#{}))#{a:=1}),
1109    {'EXIT',{{badkey,a},_}} = (catch #{}#{a:=1}),
1110    Empty = #{},
1111    {'EXIT',{{badkey,a},_}} = (catch Empty#{a:=1}),
1112
1113    %% Evaluation order.
1114    BadMap = id([no,map]),
1115    {'EXIT',{blurf,_}} =
1116	(catch BadMap#{whatever:=id(error(blurf))}),
1117    {'EXIT',{blurf,_}} =
1118	(catch BadMap#{id(error(blurf)):=whatever}),
1119    {'EXIT',{{badmap,BadMap},_}} =
1120	(catch BadMap#{id(nonexisting):=whatever}),
1121    ok.
1122
1123t_update_exact_large(Config) when is_list(Config) ->
1124    M0 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
1125               11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
1126               12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
1127               13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
1128               14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
1129
1130               15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
1131               16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
1132               17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
1133               18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
1134               19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19",
1135
1136               10.0=>fa0,20.0=>fb0,30.0=>"fc0",
1137               11.0=>fa1,21.0=>fb1,31.0=>"fc1",
1138               12.0=>fa2,22.0=>fb2,32.0=>"fc2",
1139               13.0=>fa3,23.0=>fb3,33.0=>"fc3",
1140               14.0=>fa4,24.0=>fb4,34.0=>"fc4",
1141
1142               15.0=>fa5,25.0=>fb5,35.0=>"fc5",
1143               16.0=>fa6,26.0=>fb6,36.0=>"fc6",
1144               17.0=>fa7,27.0=>fb7,37.0=>"fc7",
1145               18.0=>fa8,28.0=>fb8,38.0=>"fc8",
1146               19.0=>fa9,29.0=>fb9,39.0=>"fc9",
1147
1148               #{ one => small, map => key } => "small map key 1",
1149               #{ second => small, map => key } => "small map key 2",
1150               #{ third => small, map => key } => "small map key 3",
1151
1152               #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
1153                  11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
1154                  12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
1155                  13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
1156                  14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
1157
1158                  15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
1159                  16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
1160                  17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
1161                  18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
1162                  19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
1163
1164               #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
1165                  11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
1166                  12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
1167                  13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
1168                  14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
1169
1170                  15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
1171                  k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
1172                  17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
1173                  18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
1174                  19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 2" }),
1175
1176
1177    M1 = M0#{10:=42,<<"55">>:=100,10.0:=[a,b,c]},
1178    #{ 10:=42,<<"55">>:=100,{["05"]}:="15",10.0:=[a,b,c],
1179       #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
1180          11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
1181          12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
1182          13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
1183          14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
1184
1185          15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
1186          16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
1187          17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
1188          18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
1189          19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } := "large map key 1" } = M1,
1190
1191    M1 = M0#{10:=wrong,10=>42,<<"55">>=>wrong,<<"55">>:=100,10.0:=[a,b,c]},
1192
1193    M2 = M0#{13.0:=new},
1194    #{10:=a0,20:=b0,13.0:=new} = M2,
1195    M2 = M0#{13.0=>wrong,13.0:=new},
1196
1197    %% Errors cases.
1198    {'EXIT',{{badkey,nonexisting},_}} = (catch M0#{nonexisting:=val}),
1199    {'EXIT',{{badkey,1.0},_}} = (catch M0#{1.0:=v,1.0=>v2}),
1200    {'EXIT',{{badkey,42},_}} = (catch M0#{42.0:=v,42:=v2}),
1201    {'EXIT',{{badkey,42.0},_}} = (catch M0#{42=>v1,42.0:=v2,42:=v3}),
1202
1203    ok.
1204
1205t_update_values(Config) when is_list(Config) ->
1206    V0 = id(1337),
1207    M0 = #{ a => 1, val => V0},
1208    V1 = get_val(M0),
1209    M1 = id(M0#{ val := [V0,V1], "wazzup" => 42 }),
1210    [1337, {some_val, 1337}] = get_val(M1),
1211    M2 = id(M1#{ <<42:333>> => 1337 }),
1212    {bin_key,1337} = get_val(M2),
1213
1214    N = 110,
1215    List = [{[I,1,2,3,I],{1,2,3,"wat",I}}|| I <- lists:seq(1,N)],
1216
1217    {_,_,#{val2 := {1,2,3,"wat",N}, val1 := [N,1,2,3,N]}} = lists:foldl(fun
1218	    ({V2,V3},{Old2,Old3,Mi}) ->
1219		ok = check_val(Mi,Old2,Old3),
1220		#{ val1 := Old2, val2 := Old3 } = Mi,
1221		{V2,V3, Mi#{ val1 := id(V2), val2 := V1, val2 => id(V3)}}
1222	end, {none, none, #{val1=>none,val2=>none}},List),
1223    ok.
1224
1225t_expand_map_update(Config) when is_list(Config) ->
1226    M = #{<<"hello">> => <<"world">>}#{<<"hello">> := <<"les gens">>},
1227    #{<<"hello">> := <<"les gens">>} = M,
1228    ok.
1229
1230t_export(Config) when is_list(Config) ->
1231    Raclette = id(#{}),
1232    case brie of brie -> Fromage = Raclette end,
1233    Raclette = Fromage#{},
1234    ok.
1235
1236check_val(#{val1:=V1, val2:=V2},V1,V2) -> ok.
1237
1238get_val(#{ <<42:333>> := V }) -> {bin_key, V};
1239get_val(#{ "wazzup" := _, val := V}) -> V;
1240get_val(#{ val := V }) -> {some_val, V}.
1241
1242t_guard_bifs(Config) when is_list(Config) ->
1243    true   = map_guard_empty(),
1244    true   = map_guard_empty_2(),
1245    true   = map_guard_head(#{a=>1}),
1246    false  = map_guard_head([]),
1247
1248    true   = map_get_head(#{a=>1}),
1249    false  = map_get_head(#{}),
1250    false  = map_get_head([]),
1251
1252    true   = map_get_head_not(#{a=>false}),
1253    false  = map_get_head_not(#{a=>true}),
1254    false  = map_get_head(#{}),
1255    false  = map_get_head([]),
1256
1257    true   = map_is_key_head(#{a=>1}),
1258    false  = map_is_key_head(#{}),
1259    false  = map_is_key_head(not_a_map),
1260
1261    false  = map_is_key_head_not(#{a=>1}),
1262    true   = map_is_key_head_not(#{b=>1}),
1263    true   = map_is_key_head_not(#{}),
1264    false  = map_is_key_head_not(not_a_map),
1265
1266    b = map_get_head_badmap1(),
1267    b = map_get_head_badmap2(),
1268    b = map_get_head_badmap3(),
1269
1270    true   = map_guard_body(#{a=>1}),
1271    false  = map_guard_body({}),
1272    true   = map_guard_pattern(#{a=>1, <<"hi">> => "hi" }),
1273    false  = map_guard_pattern("list"),
1274    true   = map_guard_tautology(),
1275    true   = map_guard_ill_map_size(),
1276    true   = map_field_check_sequence(#{a=>1}),
1277    false  = map_field_check_sequence(#{}),
1278
1279    %% The guard BIFs used in a body.
1280
1281    v = map_get(a, id(#{a=>v})),
1282    {'EXIT',{{badkey,a},_}} =
1283        (catch map_get(a, id(#{}))),
1284    {'EXIT',{{badmap,not_a_map},_}} =
1285        (catch map_get(a, id(not_a_map))),
1286
1287    true   = is_map_key(a, id(#{a=>1})),
1288    false  = is_map_key(b, id(#{a=>1})),
1289    false  = is_map_key(b, id(#{})),
1290    {'EXIT',{{badmap,not_a_map},_}} =
1291        (catch is_map_key(b, id(not_a_map))),
1292
1293    {true,v} = erl_699(#{k=>v}),
1294    {'EXIT',{{badkey,k},_}} = (catch erl_699(#{})),
1295    {'EXIT',{{badmap,not_a_map},_}} = (catch erl_699(not_a_map)),
1296
1297    %% Cover optimizations in beam_dead.
1298
1299    ok = beam_dead_1(#{a=>any,k=>true}),
1300    error = beam_dead_1(#{a=>any,k=>false}),
1301    error = beam_dead_1(#{a=>any}),
1302    error = beam_dead_1(#{}),
1303
1304    ok = beam_dead_2(#{a=>any,k=>true}),
1305    error = beam_dead_2(#{a=>any,k=>false}),
1306    error = beam_dead_2(#{a=>any}),
1307    error = beam_dead_2(#{}),
1308
1309    ok = beam_dead_3(#{k=>true}),
1310    error = beam_dead_3(#{k=>false}),
1311    error = beam_dead_3(#{}),
1312
1313    ok = beam_dead_4(#{k=>true}),
1314    error = beam_dead_4(#{k=>false}),
1315    error = beam_dead_4(#{}),
1316    error = beam_dead_4(not_a_map),
1317
1318    ok = beam_dead_5(#{k=>true}),
1319    error = beam_dead_5(#{k=>false}),
1320    error = beam_dead_3(#{}),
1321
1322    %% Test is_map_key/2 followed by map update.
1323
1324    Used0 = map_usage(var, #{other=>value}),
1325    Used0 = #{other=>value,var=>dead},
1326    Used1 = map_usage(var, #{var=>live}),
1327    Used1 = #{var=>live},
1328
1329    ok.
1330
1331map_guard_empty() when is_map(#{}); false -> true.
1332
1333map_guard_empty_2() when true; #{} andalso false -> true.
1334
1335map_guard_head(M) when is_map(M) -> true;
1336map_guard_head(_) -> false.
1337
1338map_get_head(M) when map_get(a, M) =:= 1 -> true;
1339map_get_head(_) -> false.
1340
1341map_get_head_not(M) when not map_get(a, M) -> true;
1342map_get_head_not(_) -> false.
1343
1344map_get_head_badmap1() when map_get(key, not_a_map), false -> a;
1345map_get_head_badmap1() -> b.
1346
1347map_get_head_badmap2() when map_get(key, not_a_map), true -> a;
1348map_get_head_badmap2() -> b.
1349
1350map_get_head_badmap3() when map_get(key, not_a_map) -> a;
1351map_get_head_badmap3() -> b.
1352
1353map_is_key_head(M) when is_map_key(a, M) -> true;
1354map_is_key_head(_) -> false.
1355
1356map_is_key_head_not(M) when not is_map_key(a, M) -> true;
1357map_is_key_head_not(_) -> false.
1358
1359map_guard_body(M) -> is_map(M).
1360
1361map_guard_pattern(#{}) -> true;
1362map_guard_pattern(_)   -> false.
1363
1364map_guard_tautology() when #{} =:= #{}; true -> true.
1365
1366map_guard_ill_map_size() when true; map_size(0) -> true.
1367
1368map_field_check_sequence(M)
1369  when is_map(M) andalso is_map_key(a, M) andalso (map_get(a, M) == 1) ->
1370    true;
1371map_field_check_sequence(_) ->
1372    false.
1373
1374erl_699(M) ->
1375    %% Used to cause an internal consistency failure.
1376    {is_map_key(k, M),maps:get(k, M)}.
1377
1378beam_dead_1(#{a:=_,k:=_}=M) when map_get(k, M) ->
1379    ok;
1380beam_dead_1(#{}) ->
1381    error.
1382
1383beam_dead_2(M) ->
1384    case M of
1385        #{a:=_,k:=_} when map_get(k, M) ->
1386            ok;
1387        #{} ->
1388            error
1389    end.
1390
1391beam_dead_3(M) ->
1392    case M of
1393        #{k:=_} when map_get(k, M) ->
1394            ok;
1395        #{} ->
1396            error
1397    end.
1398
1399beam_dead_4(M) ->
1400    case M of
1401        #{} when map_get(k, M) ->
1402            ok;
1403        _ ->
1404            error
1405    end.
1406
1407beam_dead_5(#{}=M) when map_get(k, M) ->
1408    ok;
1409beam_dead_5(#{}) ->
1410    error.
1411
1412%% Test is_map_key/2, followed by an update of the map.
1413map_usage(Def, Used) ->
1414    case is_map_key(Def, Used) of
1415        true -> Used;
1416        false -> Used#{Def=>dead}
1417    end.
1418
1419
1420t_guard_sequence(Config) when is_list(Config) ->
1421    {1, "a"} = map_guard_sequence_1(#{seq=>1,val=>id("a")}),
1422    {2, "b"} = map_guard_sequence_1(#{seq=>2,val=>id("b")}),
1423    {3, "c"} = map_guard_sequence_1(#{seq=>3,val=>id("c")}),
1424    {4, "d"} = map_guard_sequence_1(#{seq=>4,val=>id("d")}),
1425    {5, "e"} = map_guard_sequence_1(#{seq=>5,val=>id("e")}),
1426
1427    {1,M1}       = map_guard_sequence_2(M1 = id(#{a=>3})),
1428    {2,M2}       = map_guard_sequence_2(M2 = id(#{a=>4, b=>4})),
1429    {3,gg,M3}    = map_guard_sequence_2(M3 = id(#{a=>gg, b=>4})),
1430    {4,sc,sc,M4} = map_guard_sequence_2(M4 = id(#{a=>sc, b=>3, c=>sc2})),
1431    {5,kk,kk,M5} = map_guard_sequence_2(M5 = id(#{a=>kk, b=>other, c=>sc2})),
1432
1433    %% error case
1434    {'EXIT',{function_clause,_}} = (catch map_guard_sequence_1(#{seq=>6,val=>id("e")})),
1435    {'EXIT',{function_clause,_}} = (catch map_guard_sequence_2(#{b=>5})),
1436    ok.
1437
1438t_guard_sequence_large(Config) when is_list(Config) ->
1439    M0 = id(#{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00",03]}=>"10",
1440               11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01",03]}=>"11",
1441               12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02",03]}=>"12",
1442               13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03",03]}=>"13",
1443               14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04",03]}=>"14",
1444
1445               15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05",03]}=>"15",
1446               16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06",03]}=>"16",
1447               17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07",03]}=>"17",
1448               18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08",03]}=>"18",
1449               19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09",03]}=>"19",
1450
1451               10.0=>fa0,20.0=>fb0,30.0=>"fc0",
1452               11.0=>fa1,21.0=>fb1,31.0=>"fc1",
1453               12.0=>fa2,22.0=>fb2,32.0=>"fc2",
1454               13.0=>fa3,23.0=>fb3,33.0=>"fc3",
1455               14.0=>fa4,24.0=>fb4,34.0=>"fc4",
1456
1457               15.0=>fa5,25.0=>fb5,35.0=>"fc5",
1458               16.0=>fa6,26.0=>fb6,36.0=>"fc6",
1459               17.0=>fa7,27.0=>fb7,37.0=>"fc7",
1460               18.0=>fa8,28.0=>fb8,38.0=>"fc8",
1461               19.0=>fa9,29.0=>fb9,39.0=>"fc9",
1462
1463               #{ one => small, map => key } => "small map key 1",
1464               #{ second => small, map => key } => "small map key 2",
1465               #{ third => small, map => key } => "small map key 3",
1466
1467               #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
1468                  11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
1469                  12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
1470                  13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
1471                  14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
1472
1473                  15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
1474                  16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
1475                  17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
1476                  18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
1477                  19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
1478
1479               #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
1480                  11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
1481                  12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
1482                  13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
1483                  14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
1484
1485                  15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
1486                  k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
1487                  17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
1488                  18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
1489                  19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 2" }),
1490
1491    {1, "a"} = map_guard_sequence_1(M0#{seq=>1,val=>id("a")}),
1492    {2, "b"} = map_guard_sequence_1(M0#{seq=>2,val=>id("b")}),
1493    {3, "c"} = map_guard_sequence_1(M0#{seq=>3,val=>id("c")}),
1494    {4, "d"} = map_guard_sequence_1(M0#{seq=>4,val=>id("d")}),
1495    {5, "e"} = map_guard_sequence_1(M0#{seq=>5,val=>id("e")}),
1496
1497    {1,M1}       = map_guard_sequence_2(M1 = id(M0#{a=>3})),
1498    {2,M2}       = map_guard_sequence_2(M2 = id(M0#{a=>4, b=>4})),
1499    {3,gg,M3}    = map_guard_sequence_2(M3 = id(M0#{a=>gg, b=>4})),
1500    {4,sc,sc,M4} = map_guard_sequence_2(M4 = id(M0#{a=>sc, b=>3, c=>sc2})),
1501    {5,kk,kk,M5} = map_guard_sequence_2(M5 = id(M0#{a=>kk, b=>other, c=>sc2})),
1502
1503    {'EXIT',{function_clause,_}} = (catch map_guard_sequence_1(M0#{seq=>6,val=>id("e")})),
1504    {'EXIT',{function_clause,_}} = (catch map_guard_sequence_2(M0#{b=>5})),
1505    ok.
1506
1507map_guard_sequence_1(#{seq:=1=Seq, val:=Val}) -> {Seq,Val};
1508map_guard_sequence_1(#{seq:=2=Seq, val:=Val}) -> {Seq,Val};
1509map_guard_sequence_1(#{seq:=3=Seq, val:=Val}) -> {Seq,Val};
1510map_guard_sequence_1(#{seq:=4=Seq, val:=Val}) -> {Seq,Val};
1511map_guard_sequence_1(#{seq:=5=Seq, val:=Val}) -> {Seq,Val}.
1512
1513map_guard_sequence_2(#{ a:=3 }=M) -> {1, M};
1514map_guard_sequence_2(#{ a:=4 }=M) -> {2, M};
1515map_guard_sequence_2(#{ a:=X, a:=X, b:=4 }=M) -> {3,X,M};
1516map_guard_sequence_2(#{ a:=X, a:=Y, b:=3 }=M) when X =:= Y -> {4,X,Y,M};
1517map_guard_sequence_2(#{ a:=X, a:=Y }=M) when X =:= Y -> {5,X,Y,M}.
1518
1519
1520t_guard_update(Config) when is_list(Config) ->
1521    error  = map_guard_update(#{},#{}),
1522    first  = map_guard_update(#{}, #{x=>first}),
1523    second = map_guard_update(#{y=>old}, #{x=>second,y=>old}),
1524    third  = map_guard_update(#{x=>old,y=>old}, #{x=>third,y=>old}),
1525    bad_map_guard_update(),
1526    ok.
1527
1528t_guard_update_large(Config) when is_list(Config) ->
1529    M0 = id(#{ 70=>a0,80=>b0,90=>"c0","40"=>"d0",<<"50">>=>"e0",{["00",03]}=>"10",
1530               71=>a1,81=>b1,91=>"c1","41"=>"d1",<<"51">>=>"e1",{["01",03]}=>"11",
1531               72=>a2,82=>b2,92=>"c2","42"=>"d2",<<"52">>=>"e2",{["02",03]}=>"12",
1532               73=>a3,83=>b3,93=>"c3","43"=>"d3",<<"53">>=>"e3",{["03",03]}=>"13",
1533               74=>a4,84=>b4,94=>"c4","44"=>"d4",<<"54">>=>"e4",{["04",03]}=>"14",
1534
1535               75=>a5,85=>b5,95=>"c5","45"=>"d5",<<"55">>=>"e5",{["05",03]}=>"15",
1536               76=>a6,86=>b6,96=>"c6","46"=>"d6",<<"56">>=>"e6",{["06",03]}=>"16",
1537               77=>a7,87=>b7,97=>"c7","47"=>"d7",<<"57">>=>"e7",{["07",03]}=>"17",
1538               78=>a8,88=>b8,98=>"c8","48"=>"d8",<<"58">>=>"e8",{["08",03]}=>"18",
1539               79=>a9,89=>b9,99=>"c9","49"=>"d9",<<"59">>=>"e9",{["09",03]}=>"19",
1540
1541               70.0=>fa0,80.0=>fb0,90.0=>"fc0",
1542               71.0=>fa1,81.0=>fb1,91.0=>"fc1",
1543               72.0=>fa2,82.0=>fb2,92.0=>"fc2",
1544               73.0=>fa3,83.0=>fb3,93.0=>"fc3",
1545               74.0=>fa4,84.0=>fb4,94.0=>"fc4",
1546
1547               75.0=>fa5,85.0=>fb5,95.0=>"fc5",
1548               76.0=>fa6,86.0=>fb6,96.0=>"fc6",
1549               77.0=>fa7,87.0=>fb7,97.0=>"fc7",
1550               78.0=>fa8,88.0=>fb8,98.0=>"fc8",
1551               79.0=>fa9,89.0=>fb9,99.0=>"fc9",
1552
1553               #{ one => small, map => key } => "small map key 1",
1554               #{ second => small, map => key } => "small map key 2",
1555               #{ third => small, map => key } => "small map key 3",
1556
1557               #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
1558                  11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
1559                  12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
1560                  13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
1561                  14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
1562
1563                  15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
1564                  16=>a6,26=>b6,36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
1565                  17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
1566                  18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
1567                  19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 1",
1568
1569               #{ 10=>a0,20=>b0,30=>"c0","40"=>"d0",<<"50">>=>"e0",{["00"]}=>"10",
1570                  11=>a1,21=>b1,31=>"c1","41"=>"d1",<<"51">>=>"e1",{["01"]}=>"11",
1571                  12=>a2,22=>b2,32=>"c2","42"=>"d2",<<"52">>=>"e2",{["02"]}=>"12",
1572                  13=>a3,23=>b3,33=>"c3","43"=>"d3",<<"53">>=>"e3",{["03"]}=>"13",
1573                  14=>a4,24=>b4,34=>"c4","44"=>"d4",<<"54">>=>"e4",{["04"]}=>"14",
1574
1575                  15=>a5,25=>b5,35=>"c5","45"=>"d5",<<"55">>=>"e5",{["05"]}=>"15",
1576                  k16=>a6,k26=>b6,k36=>"c6","46"=>"d6",<<"56">>=>"e6",{["06"]}=>"16",
1577                  17=>a7,27=>b7,37=>"c7","47"=>"d7",<<"57">>=>"e7",{["07"]}=>"17",
1578                  18=>a8,28=>b8,38=>"c8","48"=>"d8",<<"58">>=>"e8",{["08"]}=>"18",
1579                  19=>a9,29=>b9,39=>"c9","49"=>"d9",<<"59">>=>"e9",{["09"]}=>"19" } => "large map key 2" }),
1580
1581
1582    error  = map_guard_update(M0#{},M0#{}),
1583    first  = map_guard_update(M0#{},M0#{x=>first}),
1584    second = map_guard_update(M0#{y=>old}, M0#{x=>second,y=>old}),
1585    ok.
1586
1587map_guard_update(M1, M2) when M1#{x=>first}  =:= M2 -> first;
1588map_guard_update(M1, M2) when M1#{x=>second} =:= M2 -> second;
1589map_guard_update(M1, M2) when M1#{x:=third}  =:= M2 -> third;
1590map_guard_update(_, _) -> error.
1591
1592bad_map_guard_update() ->
1593    do_bad_map_guard_update(fun burns/1),
1594    do_bad_map_guard_update(fun turns/1),
1595    ok.
1596
1597do_bad_map_guard_update(Fun) ->
1598    do_bad_map_guard_update_1(Fun, #{}),
1599    do_bad_map_guard_update_1(Fun, #{true=>1}),
1600    ok.
1601
1602do_bad_map_guard_update_1(Fun, Value) ->
1603    %% Note: The business with the seemingly redundant fun
1604    %% disables inlining, which would otherwise change the
1605    %% EXIT reason.
1606    {'EXIT',{function_clause,_}} = (catch Fun(Value)),
1607    ok.
1608
1609burns(Richmond) when not (Richmond#{true := 0}); [Richmond] ->
1610    specification.
1611
1612turns(Richmond) when not (Richmond#{true => 0}); [Richmond] ->
1613    specification.
1614
1615t_guard_receive(Config) when is_list(Config) ->
1616    M0  = #{ id => 0 },
1617    Pid = spawn_link(fun() -> guard_receive_loop() end),
1618    Big = 36893488147419103229,
1619    B1  = <<"some text">>,
1620    B2  = <<"was appended">>,
1621    B3  = <<B1/binary, B2/binary>>,
1622
1623    #{id:=1, res:=Big} = M1 = call(Pid, M0#{op=>sub,in=>{1 bsl 65, 3}}),
1624    #{id:=2, res:=26}  = M2 = call(Pid, M1#{op=>idiv,in=>{53,2}}),
1625    #{id:=3, res:=832} = M3 = call(Pid, M2#{op=>imul,in=>{26,32}}),
1626    #{id:=4, res:=4}   = M4 = call(Pid, M3#{op=>add,in=>{1,3}}),
1627    #{id:=5, res:=Big} = M5 = call(Pid, M4#{op=>sub,in=>{1 bsl 65, 3}}),
1628    #{id:=6, res:=B3}  = M6 = call(Pid, M5#{op=>"append",in=>{B1,B2}}),
1629    #{id:=7, res:=4}   = _  = call(Pid, M6#{op=>add,in=>{1,3}}),
1630
1631
1632    %% update old maps and check id update
1633    #{id:=2, res:=B3} = call(Pid, M1#{op=>"append",in=>{B1,B2}}),
1634    #{id:=5, res:=99} = call(Pid, M4#{op=>add,in=>{33, 66}}),
1635
1636    %% cleanup
1637    done = call(Pid, done),
1638    ok.
1639
1640-define(t_guard_receive_large_procs, 1500).
1641
1642t_guard_receive_large(Config) when is_list(Config) ->
1643    M = lists:foldl(fun(_,#{procs := Ps } = M) ->
1644                            M#{ procs := Ps#{ spawn_link(fun() -> grecv_loop() end) => 0 }}
1645                    end, #{procs => #{}, done => 0}, lists:seq(1,?t_guard_receive_large_procs)),
1646    lists:foreach(fun(Pid) ->
1647                          Pid ! {self(), hello}
1648                  end, maps:keys(maps:get(procs,M))),
1649    ok = guard_receive_large_loop(M),
1650    ok.
1651
1652guard_receive_large_loop(#{done := ?t_guard_receive_large_procs}) ->
1653    ok;
1654guard_receive_large_loop(M) ->
1655    receive
1656        #{pid := Pid, msg := hello} ->
1657            case M of
1658                #{done := Count, procs := #{Pid := 150}} ->
1659                    Pid ! {self(), done},
1660                    guard_receive_large_loop(M#{done := Count + 1});
1661                #{procs := #{Pid := Count} = Ps} ->
1662                    Pid ! {self(), hello},
1663                    guard_receive_large_loop(M#{procs := Ps#{Pid := Count + 1}})
1664            end
1665    end.
1666
1667grecv_loop() ->
1668    receive
1669        {_, done} ->
1670            ok;
1671        {Pid, hello} ->
1672            Pid ! #{pid=>self(), msg=>hello},
1673            grecv_loop()
1674    end.
1675
1676
1677call(Pid, M) ->
1678    Pid ! {self(), M}, receive {Pid, Res} -> Res end.
1679
1680guard_receive_loop() ->
1681    receive
1682	{Pid, #{ id:=Id, op:="append", in:={X,Y}}=M} when is_binary(X), is_binary(Y) ->
1683	    Pid ! {self(), M#{ id=>Id+1, res=><<X/binary,Y/binary>>}},
1684	    guard_receive_loop();
1685	{Pid, #{ id:=Id, op:=add, in:={X,Y}}} ->
1686	    Pid ! {self(), #{ id=>Id+1, res=>X+Y}},
1687	    guard_receive_loop();
1688	{Pid, #{ id:=Id, op:=sub,  in:={X,Y}}=M} ->
1689	    Pid ! {self(), M#{ id=>Id+1, res=>X-Y}},
1690	    guard_receive_loop();
1691	{Pid, #{ id:=Id, op:=idiv, in:={X,Y}}=M} ->
1692	    Pid ! {self(), M#{ id=>Id+1, res=>X div Y}},
1693	    guard_receive_loop();
1694	{Pid, #{ id:=Id, op:=imul, in:={X,Y}}=M} ->
1695	    Pid ! {self(), M#{ id=>Id+1, res=>X * Y}},
1696	    guard_receive_loop();
1697	{Pid, done} ->
1698	    Pid ! {self(), done};
1699	{Pid, Other} ->
1700	    Pid ! {error, Other},
1701	    guard_receive_loop()
1702    end.
1703
1704
1705t_list_comprehension(Config) when is_list(Config) ->
1706    [#{k:=1},#{k:=2},#{k:=3}] = id([#{k=>I} || I <- [1,2,3]]),
1707    Ls = id([#{<<2:301>> => I, "wat" => I + 1} || I <- [1,2,3]]),
1708    [#{<<2:301>>:=1,"wat":=2},#{<<2:301>>:=2,"wat":=3},#{<<2:301>>:=3,"wat":=4}] = Ls,
1709    [{1,2},{2,3},{3,4}] = id([{I2,I1} || #{"wat" := I1, <<2:301>> := I2} <- Ls]),
1710
1711    Ks = lists:seq($a,$z),
1712    Ms = [#{[K1,K2]=>{K1,K2}} || K1 <- Ks, K2 <- Ks],
1713    [#{"aa" := {$a,$a}},#{"ab":={$a,$b}}|_] = Ms,
1714    [#{"zz" := {$z,$z}},#{"zy":={$z,$y}}|_] = lists:reverse(Ms),
1715    ok.
1716
1717t_guard_fun(Config) when is_list(Config) ->
1718    F1 = fun
1719	    (#{s:=v,v:=V})     -> {v,V};
1720	    (#{s:=t,v:={V,V}}) -> {t,V};
1721	    (#{s:=l,v:=[V,V]}) -> {l,V}
1722    end,
1723
1724    F2 = fun
1725	    (#{s:=T,v:={V,V}}) -> {T,V};
1726	    (#{s:=T,v:=[V,V]}) -> {T,V};
1727	    (#{s:=T,v:=V})     -> {T,V}
1728    end,
1729    V = <<"hi">>,
1730
1731    {v,V} = F1(#{s=>v,v=>V}),
1732    {t,V} = F1(#{s=>t,v=>{V,V}}),
1733    {l,V} = F1(#{s=>l,v=>[V,V]}),
1734
1735    {v,V} = F2(#{s=>v,v=>V}),
1736    {t,V} = F2(#{s=>t,v=>{V,V}}),
1737    {l,V} = F2(#{s=>l,v=>[V,V]}),
1738
1739    %% error case
1740    case (catch F1(#{s=>none,v=>none})) of
1741	{'EXIT', {function_clause,[{?MODULE,_,[#{s:=none,v:=none}],_}|_]}} -> ok;
1742	{'EXIT', {{case_clause,_},_}} -> {comment,inlined};
1743	Other ->
1744	    ct:fail({no_match, Other})
1745    end.
1746
1747
1748t_map_sort_literals(Config) when is_list(Config) ->
1749    % test relation
1750
1751    %% size order
1752    true  = #{ a => 1, b => 2} < id(#{ a => 1, b => 1, c => 1}),
1753    true  = #{ b => 1, a => 1} < id(#{ c => 1, a => 1, b => 1}),
1754    false = #{ c => 1, b => 1, a => 1} < id(#{ c => 1, a => 1}),
1755
1756    %% key order
1757    true  = id(#{ a => 1 }) < id(#{ b => 1}),
1758    false = id(#{ b => 1 }) < id(#{ a => 1}),
1759    true  = id(#{ a => 1, b => 1, c => 1 }) < id(#{ b => 1, c => 1, d => 1}),
1760    true  = id(#{ b => 1, c => 1, d => 1 }) > id(#{ a => 1, b => 1, c => 1}),
1761    true  = id(#{ c => 1, b => 1, a => 1 }) < id(#{ b => 1, c => 1, d => 1}),
1762    true  = id(#{ "a" => 1 }) < id(#{ <<"a">> => 1}),
1763    false = id(#{ <<"a">> => 1 }) < id(#{ "a" => 1}),
1764    true = id(#{ 1 => 1 }) < id(#{ 1.0 => 1}),
1765    false = id(#{ 1.0 => 1 }) < id(#{ 1 => 1}),
1766
1767    %% value order
1768    true  = id(#{ a => 1 }) < id(#{ a => 2}),
1769    false = id(#{ a => 2 }) < id(#{ a => 1}),
1770    false = id(#{ a => 2, b => 1 }) < id(#{ a => 1, b => 3}),
1771    true  = id(#{ a => 1, b => 1 }) < id(#{ a => 1, b => 3}),
1772
1773    true  = id(#{ "a" => "hi", b => 134 }) == id(#{ b => 134,"a" => "hi"}),
1774
1775    %% lists:sort
1776
1777    SortVs = [#{"a"=>1},#{a=>2},#{1=>3},#{<<"a">>=>4}],
1778    [#{1:=ok},#{a:=ok},#{"a":=ok},#{<<"a">>:=ok}] = lists:sort([#{"a"=>ok},#{a=>ok},#{1=>ok},#{<<"a">>=>ok}]),
1779    [#{1:=3},#{a:=2},#{"a":=1},#{<<"a">>:=4}] = lists:sort(SortVs),
1780    [#{1:=3},#{a:=2},#{"a":=1},#{<<"a">>:=4}] = lists:sort(lists:reverse(SortVs)),
1781
1782    ok.
1783
1784t_warn_pair_key_overloaded(Config) when is_list(Config) ->
1785    #{ "hi1" := 42 } = id(#{ "hi1" => 1, "hi1" => 42 }),
1786
1787    #{ "hi1" := 1337, "hi2" := [2], "hi3" := 3 } = id(#{
1788	    "hi1" => erlang:atom_to_binary(?MODULE,utf8),
1789	    "hi1" => erlang:binary_to_atom(<<"wazzup">>,utf8),
1790	    "hi1" => erlang:binary_to_float(<<"3.1416">>),
1791	    "hi1" => erlang:float_to_binary(3.1416),
1792	    "hi2" => erlang:pid_to_list(self()),
1793	    "hi3" => erlang:float_to_binary(3.1416),
1794	    "hi2" => lists:subtract([1,2],[1]),
1795	    "hi3" => +3,
1796	    "hi1" => erlang:min(1,2),
1797	    "hi1" => erlang:phash({1,2},33),
1798	    "hi1" => erlang:phash2({1,2},34),
1799	    "hi1" => erlang:integer_to_binary(1337),
1800	    "hi1" => erlang:binary_to_integer(<<"1337">>),
1801	    "hi4" => erlang:float_to_binary(3.1416)
1802	}),
1803    ok.
1804
1805t_warn_useless_build(Config) when is_list(Config) ->
1806    [#{ a => id(I)} || I <- [1,2,3]],
1807    ok.
1808
1809t_build_and_match_over_alloc(Config) when is_list(Config) ->
1810    Ls = id([1,2,3]),
1811    V0 = [a|Ls],
1812    M0 = id(#{ "a" => V0 }),
1813    #{ "a" := V1 } = M0,
1814    V2 = id([c|Ls]),
1815    M2 = id(#{ "a" => V2 }),
1816    #{ "a" := V3 } = M2,
1817    {[a,1,2,3],[c,1,2,3]} = id({V1,V3}),
1818    ok.
1819
1820t_build_and_match_empty_val(Config) when is_list(Config) ->
1821    F = fun(#{ "hi":=_,{1,2}:=_,1337:=_}) -> ok end,
1822    ok = F(id(#{"hi"=>ok,{1,2}=>ok,1337=>ok})),
1823
1824    %% error case
1825    case (catch (F(id(#{"hi"=>ok})))) of
1826	{'EXIT',{function_clause,_}} -> ok;
1827	{'EXIT', {{case_clause,_},_}} -> {comment,inlined};
1828	Other ->
1829	    ct:fail({no_match, Other})
1830    end.
1831
1832t_build_and_match_val(Config) when is_list(Config) ->
1833    F = fun
1834	(#{ "hi" := first,  v := V}) -> {1,V};
1835	(#{ "hi" := second, v := V}) -> {2,V}
1836    end,
1837
1838
1839    {1,"hello"}  = F(id(#{"hi"=>first,v=>"hello"})),
1840    {2,"second"} = F(id(#{"hi"=>second,v=>"second"})),
1841
1842    %% error case
1843    case (catch (F(id(#{"hi"=>ok})))) of
1844	{'EXIT',{function_clause,_}} -> ok;
1845	{'EXIT', {{case_clause,_},_}} -> {comment,inlined};
1846	Other ->
1847	    ct:fail({no_match, Other})
1848    end.
1849
1850t_build_and_match_nil(Config) when is_list(Config) ->
1851    %% literals removed the coverage
1852    V1 = id(cookie),
1853    V2 = id(cake),
1854    V3 = id(crisps),
1855
1856    #{ [] := V1, "treat" := V2, {your,treat} := V3 } = id(#{
1857	    {your,treat} => V3,
1858	    "treat" => V2,
1859	    [] => V1 }),
1860    #{ [] := V3, [] := V3 } = id(#{ [] => V1, [] => V3 }),
1861    #{ <<1>> := V3, [] := V1 } = id(#{ [] => V1, <<1>> => V3 }),
1862    ok.
1863
1864t_build_and_match_structure(Config) when is_list(Config) ->
1865    V2 = id("it"),
1866    S = id([42,{"hi", "=)", #{ "a" => 42, any => any, val => "get_" ++ V2}}]),
1867
1868    %% match deep map values
1869    V2 = case S of
1870	[42,{"hi",_, #{ "a" := 42, val := "get_" ++ V1, any := _ }}] -> V1
1871    end,
1872    %% match deep map
1873    ok = case S of
1874	[42,{"hi",_, #{ }}] -> ok
1875    end,
1876    ok.
1877
1878%% simple build and match variables
1879t_build_and_match_variables(Config) when is_list(Config) ->
1880    K0 = id(#{}),
1881    K1 = id(1),       V1 = id(a),
1882    K2 = id(2),       V2 = id(b),
1883    K3 = id(3),       V3 = id("c"),
1884    K4 = id("4"),     V4 = id("d"),
1885    K5 = id(<<"5">>), V5 = id(<<"e">>),
1886    K6 = id({"6",7}), V6 = id("f"),
1887    K7 = id(#{ "a" => 3 }),
1888    #{K1:=V1} = id(#{K1=>V1}),
1889    #{K1:=V1,K2:=V2} = id(#{K1=>V1,K2=>V2}),
1890    #{K1:=V1,K2:=V2,K3:=V3} = id(#{K1=>V1,K2=>V2,K3=>V3}),
1891    #{K1:=V1,K2:=V2,K3:=V3,K4:=V4} = id(#{K1=>V1,K2=>V2,K3=>V3,K4=>V4}),
1892    #{K1:=V1,K2:=V2,K3:=V3,K4:=V4,K5:=V5} = id(#{K1=>V1,K2=>V2,K3=>V3,K4=>V4,K5=>V5}),
1893    #{K1:=V1,K2:=V2,K3:=V3,K4:=V4,K5:=V5,K6:=V6} = id(#{K1=>V1,K2=>V2,K3=>V3,K4=>V4,K5=>V5,K6=>V6}),
1894
1895    #{K5:=X,K5:=X=3,K4:=4} = id(#{K5=>3,K4=>4}),
1896    #{K5:=X,<<"5">>:=X=3,K4:=4} = id(#{K5=>3,K4=>4}),
1897    #{K5:=X,<<"5">>:=X=3,K4:=4} = id(#{<<"5">>=>3,K4=>4}),
1898
1899    #{ K4:=#{ K3:=#{K1:=V1, K2:=V2}}, K5:=V5} =
1900	id(#{ K5=>V5, K4=>#{ K3=>#{K2 => V2, K1 => V1}}}),
1901    #{ K4 := #{ K5 := Res }, K6 := Res} = id(#{K4=>#{K5 => 99}, K6 => 99}),
1902
1903    %% has keys
1904    #{a :=_,b :=_,K1:=_,K2:=_,K3:=V3,K4:=ResKey,K4:=ResKey,"4":=ResKey,"4":="ok"} =
1905	id(#{ a=>1, b=>1, K1=>V1, K2=>V2, K3=>V3, K4=>"nope", "4"=>"ok" }),
1906
1907    %% function
1908    ok = match_function_map_neg_keys(#{ -1 => a, -2 => b, -3 => c }),
1909
1910    %% map key
1911    #{ K0 := 42 } = id(#{ K0 => 42 }),
1912    #{ K7 := 42 } = id(#{ K7 => 42 }),
1913
1914    %% nil key
1915    KNIL = id([]),
1916    #{KNIL:=ok,1:=2} = id(#{KNIL=>ok,1=>2}),
1917
1918    Bin = <<0:258>>,
1919    #{ Bin := "three" } = id(#{<<0:258>> =>"three"}),
1920
1921    %% error case
1922    {'EXIT',{{badmatch,_},_}} = (catch (#{K5:=3,x:=2} = id(#{K5=>3}))),
1923    {'EXIT',{{badmatch,_},_}} = (catch (#{K5:=2} = id(#{K5=>3}))),
1924    {'EXIT',{{badmatch,_},_}} = (catch (#{K5:=3} = id({a,b,c}))),
1925    {'EXIT',{{badmatch,_},_}} = (catch (#{K5:=3} = id(#{K6=>3}))),
1926    {'EXIT',{{badmatch,_},_}} = (catch (#{K5:=3} = id(K7))),
1927    {'EXIT',{{badmatch,_},_}} = (catch (#{K7:=3} = id(#{K7=>42}))),
1928    ok.
1929
1930
1931match_function_map_neg_keys(#{ -1 := a, -2 := b, -3 := c }) -> ok.
1932
1933t_update_assoc_variables(Config) when is_list(Config) ->
1934    K1 = id(1),
1935    K2 = id(2),
1936    K3 = id(3.0),
1937    K4 = id(4),
1938    K5 = id(5),
1939    K6 = id(2.0),
1940
1941    M0 = #{K1=>a,K2=>b,K3=>c,K4=>d,K5=>e},
1942
1943    M1 = M0#{K1=>42,K2=>100,K4=>[a,b,c]},
1944    #{1:=42,2:=100,3.0:=c,4:=[a,b,c],5:=e} = M1,
1945    #{1:=42,2:=b,4:=d,5:=e,2.0:=100,K3:=c,4.0:=[a,b,c]} = M0#{1.0=>float,1:=42,2.0=>wrong,K6=>100,4.0=>[a,b,c]},
1946
1947    M2 = M0#{K3=>new},
1948    #{1:=a,2:=b,K3:=new,4:=d,5:=e} = M2,
1949    M2 = M0#{3.0:=wrong,K3=>new},
1950
1951    #{ <<0:258>> := val } = id(M0#{<<0:258>> => val}), %% binary limitation
1952
1953    %% Errors cases.
1954    BadMap = id(badmap),
1955    {'EXIT',{{badmap,BadMap},_}} = (catch BadMap#{nonexisting=>val}),
1956    {'EXIT',{{badmap,<<>>},_}} = (catch <<>>#{nonexisting=>val}),
1957    ok.
1958
1959t_update_exact_variables(Config) when is_list(Config) ->
1960    K1 = id(1),
1961    K2 = id(2),
1962    K3 = id(3.0),
1963    K4 = id(4),
1964
1965    M0 = id(#{1=>a,2=>b,3.0=>c,4=>d,5=>e}),
1966
1967    M1 = M0#{K1:=42,K2:=100,K4:=[a,b,c]},
1968    #{1:=42,2:=100,3.0:=c,K4:=[a,b,c],5:=e} = M1,
1969    M1 = M0#{K1:=wrong,1:=also_wrong,K1=>42,2=>wrong,K2:=100,4:=[a,b,c]},
1970
1971    M2 = M0#{K3:=new},
1972    #{1:=a,K2:=b,3.0:=new,K4:=d,5:=e} = M2,
1973    M2 = M0#{3.0=>wrong,K3:=new},
1974    true = M2 =/= M0#{3=>right,3.0:=new},
1975    #{ 3 := right, 3.0 := new } = M0#{3=>right,K3:=new},
1976
1977    M3 = id(#{ 1 => val}),
1978    #{1 := update2,1.0 := new_val4} = M3#{
1979	1.0 => new_val1, K1 := update, K1=> update3,
1980	K1 := update2, 1.0 := new_val2, 1.0 => new_val3,
1981	1.0 => new_val4 },
1982
1983    #{ "wat" := 3, 2 := a } = id(#{ "wat" => 1, K2 => 2 }#{ K2 := a, "wat" := 3 }),
1984
1985    %% Errors cases.
1986    {'EXIT',{{badmap,nil},_}} = (catch ((id(nil))#{ a := b })),
1987    {'EXIT',{{badkey,nonexisting},_}} = (catch M0#{nonexisting:=val}),
1988    {'EXIT',{{badkey,1.0},_}} = (catch M0#{1.0:=v,1.0=>v2}),
1989    {'EXIT',{{badkey,42},_}} = (catch M0#{42.0:=v,42:=v2}),
1990    {'EXIT',{{badkey,42.0},_}} = (catch M0#{42=>v1,42.0:=v2,42:=v3}),
1991    {'EXIT',{{badmap,<<>>},_}} = (catch <<>>#{nonexisting:=val}),
1992    {'EXIT',{{badkey,<<0:257>>},_}} =
1993	(catch M0#{<<0:257>> := val}),		%limitation
1994    ok.
1995
1996t_nested_pattern_expressions(Config) when is_list(Config) ->
1997    K1 = id("hello"),
1998    %K2 = id({ok}),
1999    [_,_,#{ <<"hi">> := wat, K1 := 42 }|_] = id([k,k,#{<<"hi">> => wat, K1 => 42}]),
2000    [_,_,#{ -1 := wat, K1 := 42 }|_] = id([k,k,#{-1 => wat, K1 => 42}]),
2001    [_,_,{#{ -1 := #{ {-3,<<0:300>>} := V1 }, K1 := 42 },3}|_] = id([k,k,{#{-1 => #{{-3,<<0:300>>}=>"hi"}, K1 => 42},3}]),
2002    "hi" = V1,
2003    %[k,#{ {-1,K1,[]} := {wat,K1}, K2 := 42 }|_] = id([k,#{{-1,K1,[]} => {wat,K1}, K2 => 42}]),
2004    %[k,#{ [-1,K2,[]] := {wat,K1}, K1 := 42 }|_] = id([k,#{[-1,K2,[]] => {wat,K1}, K1 => 42}]),
2005
2006    M0 = id(#{ <<33:333>> => 1, <<332:333>> => ok, a => ok, wat => yep, watzor => ok }),
2007    F0 = map_nested_pattern_funs(M0),
2008    F1 = F0(wat),
2009    F2 = F1(watzor),
2010    {yep,ok} = F2(M0),
2011
2012    %% Test matching of nested maps. There used to be an unsafe optimization in beam_peep.
2013    #{ <<"result">> := #{<<"foo">> := <<"6">> } } =
2014        nested_map(),
2015
2016    InnerMap = #{a => id({a,value})},
2017    OuterMap = #{inner_map => InnerMap},
2018    #{inner_map := #{a := {a,value}}} = OuterMap,
2019
2020    ok.
2021
2022map_nested_pattern_funs(M) ->
2023    K0 = id(a),
2024    fun(K1) ->
2025	    case M of
2026		#{ K0 := ok, K1 := yep, <<33:333>> := 1 } ->
2027		    fun(K2) ->
2028			    case M of
2029				#{ K2 := ok, K1 := yep, <<33:333>> := 1 } ->
2030				    fun
2031					(#{ <<332:333>> := ok, K1 := V1, K2 := V2 }) ->
2032					    {V1,V2}
2033				    end
2034			    end
2035		    end
2036	    end
2037    end.
2038
2039nested_map() ->
2040    #{ <<"result">> := #{<<"foo">> := <<"6">> } } =
2041        #{ <<"result">> => #{<<"foo">> => <<"6">> } }.
2042
2043t_guard_update_variables(Config) when is_list(Config) ->
2044    error  = map_guard_update_variables(n,#{},#{}),
2045    first  = map_guard_update_variables(x,#{}, #{x=>first}),
2046    second = map_guard_update_variables(x,#{y=>old}, #{x=>second,y=>old}),
2047    third  = map_guard_update_variables(x,#{x=>old,y=>old}, #{x=>third,y=>old}),
2048    fourth = map_guard_update_variables(x,#{x=>old,y=>old}, #{x=>4,y=>new}),
2049    ok.
2050
2051map_guard_update_variables(K,M1,M2) when M1#{K=>first}    =:= M2 -> first;
2052map_guard_update_variables(K,M1,M2) when M1#{K=>second}   =:= M2 -> second;
2053map_guard_update_variables(K,M1,M2) when M1#{K:=third}    =:= M2 -> third;
2054map_guard_update_variables(K,M1,M2) when M1#{K:=4,y=>new} =:= M2 -> fourth;
2055map_guard_update_variables(_,_,_) -> error.
2056
2057t_guard_sequence_variables(Config) when is_list(Config) ->
2058    {1,"a"} = map_guard_sequence_var_1(a,#{seq=>1,a=>id("a"),b=>no}),
2059    {2,"b"} = map_guard_sequence_var_1(b,#{seq=>2,b=>id("b"),a=>no}),
2060    {3,"c"} = map_guard_sequence_var_1(a,#{seq=>3,a=>id("c"),b=>no}),
2061    {4,"d"} = map_guard_sequence_var_1(b,#{seq=>4,b=>id("d"),a=>no}),
2062    {4,4}   = map_guard_sequence_var_1(seq,#{seq=>4}),
2063    {4,4,y} = map_guard_sequence_var_1(seq,#{seq=>4,b=>id("d"),a=>y}),
2064    {5,"d"} = map_guard_sequence_var_1(b,#{seq=>5,b=>id("d"),a=>y}),
2065
2066    %% error case
2067    {'EXIT',{{case_clause,_},_}} = (catch map_guard_sequence_var_1("a",#{seq=>4,val=>id("e")})),
2068    ok.
2069
2070
2071map_guard_sequence_var_1(K,M) ->
2072    case M of
2073	#{seq:=1=Seq, K:=Val} -> {Seq,Val};
2074	#{seq:=2=Seq, K:=Val} -> {Seq,Val};
2075	#{seq:=3=Seq, K:=Val} -> {Seq,Val};
2076	#{K:=4=Seq,   K:=Val1,a:=Val2} -> {Seq,Val1,Val2};
2077	#{seq:=4=Seq, K:=Val} -> {Seq,Val};
2078	#{K:=4=Seq,   K:=Val} -> {Seq,Val};
2079	#{seq:=5=Seq, K:=Val} -> {Seq,Val}
2080    end.
2081
2082
2083t_guard_sequence_mixed(Config) when is_list(Config) ->
2084    M0 = id(#{ a=>1, b=>1, c=>1, d=>1, e=>1, f=>1, g=>1, h=>1 }),
2085    M1 = id(M0#{ d := 3 }),
2086    1 = map_guard_sequence_mixed(a,d,M1),
2087    M2 = id(M1#{ b := 2, d := 4, h := 2 }),
2088    2 = map_guard_sequence_mixed(a,d,M2),
2089    M3 = id(M2#{ b := 3, e := 5, g := 3 }),
2090    3 = map_guard_sequence_mixed(a,e,M3),
2091    M4 = id(M3#{ c := 4, e := 6, h := 1 }),
2092    4 = map_guard_sequence_mixed(a,e,M4),
2093    M5 = id(M4#{ c := 5, f := 7, g := 2 }),
2094    5 = map_guard_sequence_mixed(a,f,M5),
2095    M6 = id(M5#{ c := 6, f := 8, h := 3 }),
2096    6 = map_guard_sequence_mixed(a,f,M6),
2097
2098    %% error case
2099    {'EXIT',{{case_clause,_},_}} = (catch map_guard_sequence_mixed(a,b,M0)),
2100    ok.
2101
2102map_guard_sequence_mixed(K1,K2,M) ->
2103    case M of
2104	#{ K1 := 1, b := 1, K2 := 3, g := 1} -> 1;
2105	#{ K1 := 1, b := 2, K2 := 4, h := 2} -> 2;
2106	#{ K1 := 1, b := 3, K2 := 5, g := 3} -> 3;
2107	#{ K1 := 1, c := 4, K2 := 6, h := 1} -> 4;
2108	#{ K1 := 1, c := 5, K2 := 7, g := 2} -> 5;
2109	#{ K1 := 1, c := 6, K2 := 8, h := 3} -> 6
2110    end.
2111
2112%% register corruption discovered in 18 due to
2113%% get_map_elements might destroys registers when fail-label is taken.
2114%% Only seen when patterns have two targets,
2115%% specifically: we copy one register, and then jump.
2116%%    {test,is_map,{f,5},[{x,1}]}.
2117%%
2118%%    {get_map_elements,{f,7},{x,1},{list,[{atom,a},{x,1},{atom,b},{x,2}]}}.
2119%%    %% if 'a' exists but not 'b' {x,1} is overwritten, jump {f,7}
2120%%
2121%%    {move,{integer,1},{x,0}}.
2122%%    {call_only,3,{f,10}}.
2123%%
2124%%  {label,7}.
2125%%    {get_map_elements,{f,8},{x,1},{list,[{atom,b},{x,2}]}}.
2126%%    %% {x,1} (src) is now corrupt
2127%%
2128%%    {move,{x,0},{x,1}}.
2129%%    {move,{integer,2},{x,0}}.
2130%%    {call_only,3,{f,10}}.
2131%%
2132%% Only happens in beam_block opt_move pass with two destinations.
2133
2134t_register_corruption(Config) when is_list(Config) ->
2135    M = #{a=> <<"value">>, c=>3},
2136    {3,wanted,<<"value">>} = register_corruption_bar(M,wanted),
2137    {3,wanted,<<"value">>} = register_corruption_foo(wanted,M),
2138    ok.
2139
2140register_corruption_foo(_,#{a := V1, b := V2}) ->
2141    register_corruption_dummy_call(1,V1,V2);
2142register_corruption_foo(A,#{b := V}) ->
2143    register_corruption_dummy_call(2,A,V);
2144register_corruption_foo(A,#{a := V}) ->
2145    register_corruption_dummy_call(3,A,V).
2146
2147register_corruption_bar(M,A) ->
2148    case M of
2149        #{a := V1, b := V2} ->
2150            register_corruption_dummy_call(1,V1,V2);
2151        #{b := V} ->
2152            register_corruption_dummy_call(2,A,V);
2153        #{a := V} ->
2154            register_corruption_dummy_call(3,A,V)
2155    end.
2156
2157
2158register_corruption_dummy_call(A,B,C) -> {A,B,C}.
2159
2160
2161t_frequency_table(Config) when is_list(Config) ->
2162    rand:seed(exsplus, {13,1337,54}),		% pseudo random
2163    N = 100000,
2164    Ts = rand_terms(N),
2165    #{ n:=N, tf := Tf } = frequency_table(Ts,#{ n=>0, tf => #{}}),
2166    ok = check_frequency(Ts,Tf),
2167    ok.
2168
2169
2170frequency_table([T|Ts], M) ->
2171    case M of
2172	#{ n := N, tf := #{ T := C } = F } ->
2173	    frequency_table(Ts,M#{ n := N + 1, tf := F#{ T := C + 1 }});
2174	#{ n := N, tf := F } ->
2175	    frequency_table(Ts,M#{ n := N + 1, tf := F#{ T => 1 }})
2176    end;
2177frequency_table([], M) -> M.
2178
2179
2180check_frequency(Ts,Tf) ->
2181    check_frequency(Ts,Tf,dict:new()).
2182
2183check_frequency([T|Ts],Tf,D) ->
2184    case dict:find(T,D) of
2185	error  -> check_frequency(Ts,Tf,dict:store(T,1,D));
2186	{ok,C} -> check_frequency(Ts,Tf,dict:store(T,C+1,D))
2187    end;
2188check_frequency([],Tf,D) ->
2189    validate_frequency(dict:to_list(D),Tf).
2190
2191validate_frequency([{T,C}|Fs],Tf) ->
2192    case Tf of
2193	#{ T := C } -> validate_frequency(Fs,Tf);
2194	_ -> error
2195    end;
2196validate_frequency([], _) -> ok.
2197
2198
2199t_bad_update(_Config) ->
2200    {#{0.0:=Id},#{}} = properly(#{}),
2201    42 = Id(42),
2202    {'EXIT',{{badmap,_},_}} = (catch increase(0)),
2203    ok.
2204
2205properly(Item) ->
2206    {Item#{0.0 => fun id/1},Item}.
2207
2208increase(Allows) ->
2209    catch fun() -> Allows end#{[] => +Allows, "warranty" => fun id/1}.
2210
2211t_reused_key_variable(Config) when is_list(Config) ->
2212    Key = id(key),
2213    Map1 = id(#{Key=>Config}),
2214    Map2 = id(#{Key=>Config}),
2215    case {Map1,Map2} of
2216        %% core_lint treated Key as pattern variables, not input variables,
2217        %% and complained about the variable being duplicated.
2218        {#{Key:=Same},#{Key:=Same}} ->
2219            ok
2220    end.
2221
2222t_mixed_clause(_Config) ->
2223    put(fool_inliner, x),
2224    K = get(fool_inliner),
2225    {42,100} = case #{K=>42,y=>100} of
2226                   #{x:=X,y:=Y} ->
2227                       {X,Y}
2228               end,
2229    nomatch = case #{K=>42,y=>100} of
2230                  #{x:=X,y:=0} ->
2231                      {X,Y};
2232                  #{} ->
2233                      nomatch
2234              end,
2235    ok.
2236
2237cover_beam_trim(_Config) ->
2238    val = do_cover_beam_trim(id, max, max, id, #{id=>val}),
2239    ok.
2240
2241do_cover_beam_trim(Id, OldMax, Max, Id, M) ->
2242    OldMax = id(Max),
2243    #{Id:=Val} = id(M),
2244    Val.
2245
2246t_key_expressions(_Config) ->
2247    Int = id(42),
2248    #{{tag,Int} := 42} = id(#{{tag,Int} => 42}),
2249    #{{tag,Int+1} := 42} = id(#{{tag,Int+1} => 42}),
2250    #{{a,b} := x, {tag,Int} := 42, Int := 0} =
2251        id(#{{a,b} => x, {tag,Int} => 42, Int => 0}),
2252
2253    F1 = fun(#{Int + 1 := Val}) -> Val end,
2254    val = F1(#{43 => val}),
2255    {'EXIT',_} = (catch F1(a)),
2256
2257    F2 = fun(M, X, Y) ->
2258                 case M of
2259                     #{element(X, Y) := <<Sz:16,Bin:Sz/binary>>} ->
2260                         Bin;
2261                     #{} ->
2262                         not_found;
2263                     {A,B} ->
2264                         A + B
2265                 end
2266         end,
2267    <<"xyz">> = F2(#{b => <<3:16,"xyz">>}, 2, {a,b,c}),
2268    not_found = F2(#{b => <<3:16,"xyz">>}, 999, {a,b,c}),
2269    13 = F2({6,7}, 1, 2),
2270
2271    #{<<"Спутник"/utf8>> := 1} = id(#{<<"Спутник"/utf8>> => 1}),
2272
2273    F3 = fun(Arg) ->
2274                 erase(once),
2275                 RunOnce = fun(I) ->
2276                                   undefined = put(once, twice),
2277                                   id(I)
2278                           end,
2279                 case RunOnce(Arg) of
2280                     #{{tag,<<Int:42>>} := Value} -> Value;
2281                     {X,Y} -> X + Y
2282                 end
2283         end,
2284    10 = F3({7,3}),
2285    whatever = F3(#{{tag,<<Int:42>>} => whatever}),
2286
2287    F4 = fun(K1, K2, M) ->
2288                 case M of
2289                     #{K1 div K2 := V} -> V;
2290                     #{} -> no_match
2291                 end
2292         end,
2293    value = F4(42, 21, #{2 => value}),
2294    no_match = F4(42, 21, #{}),
2295    no_match = F4(42, 0, #{2 => value}),
2296    no_match = F4(42, a, #{2 => value}),
2297
2298    F5 = fun(Term) ->
2299                 self() ! Term,
2300                 receive
2301                     #{[<<(3 bsr 30 + 2):0,$k:[]/signed-integer>>] := _} ->
2302                         ok;
2303                     0.5 ->
2304                         error
2305                 end
2306         end,
2307    error = F5(0.5),
2308
2309    F6 = fun(Term) ->
2310                 self() ! Term,
2311                 receive
2312                     #{<<a/utf8>> := {a,b,c}} -> ok;
2313                     Other -> {error,Other}
2314                 end
2315         end,
2316    {error,any} = F6(any),
2317
2318    F7 = fun(Term) ->
2319                 self() ! Term,
2320                 (?MODULE:all()):a(catch
2321                                       receive
2322                                           <<1.14:{<<"a":(tuple_size(1))>>}>> ->
2323                                               4;
2324                                           Other ->
2325                                               Other
2326                                       end)
2327         end,
2328    {'EXIT',{badarg,_}} = (catch F7(whatever)),
2329
2330    ok.
2331
2332t_duplicate_keys(Config) when is_list(Config) ->
2333    Map = #{ gurka => gaffel },
2334    Map = dup_keys_1(id(Map)),
2335
2336    ok = dup_keys_1(#{ '__struct__' => ok }),
2337
2338    ok.
2339
2340dup_keys_1(Map) ->
2341    case Map of
2342        #{'__struct__' := _} ->
2343            case Map of
2344                #{'__struct__' := _} ->
2345                    ok;
2346                O1 ->
2347                    O1
2348            end;
2349        O2 ->
2350            O2
2351    end.
2352
2353%% aux
2354
2355rand_terms(0) -> [];
2356rand_terms(N) -> [rand_term()|rand_terms(N-1)].
2357
2358rand_term() ->
2359    case rand:uniform(6) of
2360	1 -> rand_binary();
2361	2 -> rand_number();
2362	3 -> rand_atom();
2363	4 -> rand_tuple();
2364	5 -> rand_list();
2365	6 -> rand_map()
2366    end.
2367
2368rand_binary() ->
2369    case rand:uniform(3) of
2370	1 -> <<>>;
2371	2 -> <<"hi">>;
2372	3 -> <<"message text larger than 64 bytes. yep, message text larger than 64 bytes.">>
2373    end.
2374
2375rand_number() ->
2376    case rand:uniform(3) of
2377	1 -> rand:uniform(5);
2378	2 -> float(rand:uniform(5));
2379	3 -> 1 bsl (63 + rand:uniform(3))
2380    end.
2381
2382rand_atom() ->
2383    case rand:uniform(3) of
2384	1 -> hi;
2385	2 -> some_atom;
2386	3 -> some_other_atom
2387    end.
2388
2389
2390rand_tuple() ->
2391    case rand:uniform(3) of
2392	1 -> {ok, rand_term()}; % careful
2393	2 -> {1, 2, 3};
2394	3 -> {<<"yep">>, 1337}
2395    end.
2396
2397rand_list() ->
2398    case rand:uniform(3) of
2399	1 -> "hi";
2400	2 -> [1,rand_term()]; % careful
2401	3 -> [improper|list]
2402    end.
2403
2404rand_map() ->
2405    case rand:uniform(3) of
2406	1 -> #{ hi => 3 };
2407	2 -> #{ wat => rand_term(), other => 3 };  % careful
2408	3 -> #{ hi => 42, other => 42, yet_anoter => 1337 }
2409    end.
2410
2411
2412
2413%% Use this function to avoid compile-time evaluation of an expression.
2414id(I) -> I.
2415