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