aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2014-04-04 12:00:07 +0200
committerBjörn-Egil Dahlberg <[email protected]>2014-04-04 12:00:07 +0200
commit89eef897c6564c72d9717228a73959339e486bdb (patch)
treeebb39bfd3e9bbd3526b2996e36f1d57ee1f0b2c8 /lib/compiler
parent76c73b9554a3d74b027bc2e1fdace7192b7a8de6 (diff)
parente26dbc750fdd207c852bf9006668c5771f465dcf (diff)
downloadotp-89eef897c6564c72d9717228a73959339e486bdb.tar.gz
otp-89eef897c6564c72d9717228a73959339e486bdb.tar.bz2
otp-89eef897c6564c72d9717228a73959339e486bdb.zip
Merge branch 'egil/maps-fix-map-key-patterns'
* egil/maps-fix-map-key-patterns: stdlib: Fix erl_id_trans example stdlib: Deny map keys defined as #{ .. := .. } in patterns compiler: Fix compiling map keys in patterns from core compiler,stdlib: Fix Map literals as keys for Maps in patterns
Diffstat (limited to 'lib/compiler')
-rw-r--r--lib/compiler/src/cerl.erl2
-rw-r--r--lib/compiler/src/core_lib.erl11
-rw-r--r--lib/compiler/src/core_pp.erl6
-rw-r--r--lib/compiler/src/sys_core_fold.erl12
-rw-r--r--lib/compiler/src/sys_pre_expand.erl2
-rw-r--r--lib/compiler/src/v3_core.erl29
-rw-r--r--lib/compiler/test/map_SUITE.erl5
7 files changed, 33 insertions, 34 deletions
diff --git a/lib/compiler/src/cerl.erl b/lib/compiler/src/cerl.erl
index ed11c8de4d..54eac20ac4 100644
--- a/lib/compiler/src/cerl.erl
+++ b/lib/compiler/src/cerl.erl
@@ -133,7 +133,7 @@
]).
-export_type([c_binary/0, c_bitstr/0, c_call/0, c_clause/0, c_cons/0, c_fun/0,
- c_literal/0, c_map_pair/0, c_module/0, c_tuple/0,
+ c_literal/0, c_map/0, c_map_pair/0, c_module/0, c_tuple/0,
c_values/0, c_var/0, cerl/0, var_name/0]).
-include("core_parse.hrl").
diff --git a/lib/compiler/src/core_lib.erl b/lib/compiler/src/core_lib.erl
index 93ec3bbad5..2792fd8fa5 100644
--- a/lib/compiler/src/core_lib.erl
+++ b/lib/compiler/src/core_lib.erl
@@ -59,7 +59,7 @@ is_lit_bin(Es) ->
%% Return the value of LitExpr.
-spec literal_value(cerl:c_literal() | cerl:c_binary() |
- cerl:c_cons() | cerl:c_tuple()) -> term().
+ cerl:c_map() | cerl:c_cons() | cerl:c_tuple()) -> term().
literal_value(#c_literal{val=V}) -> V;
literal_value(#c_binary{segments=Es}) ->
@@ -67,7 +67,14 @@ literal_value(#c_binary{segments=Es}) ->
literal_value(#c_cons{hd=H,tl=T}) ->
[literal_value(H)|literal_value(T)];
literal_value(#c_tuple{es=Es}) ->
- list_to_tuple(literal_value_list(Es)).
+ list_to_tuple(literal_value_list(Es));
+literal_value(#c_map{arg=Cm,es=Cmps}) ->
+ M = literal_value(Cm),
+ lists:foldl(fun(#c_map_pair{ key=Ck, val=Cv },Mi) ->
+ K = literal_value(Ck),
+ V = literal_value(Cv),
+ maps:put(K,V,Mi)
+ end, M, Cmps).
literal_value_list(Vals) -> [literal_value(V) || V <- Vals].
diff --git a/lib/compiler/src/core_pp.erl b/lib/compiler/src/core_pp.erl
index a76327457d..83412ecdd7 100644
--- a/lib/compiler/src/core_pp.erl
+++ b/lib/compiler/src/core_pp.erl
@@ -120,7 +120,11 @@ format_1(#c_literal{anno=A,val=Bitstring}, Ctxt) when is_bitstring(Bitstring) ->
format_1(#c_binary{anno=A,segments=Segs}, Ctxt);
format_1(#c_literal{anno=A,val=M},Ctxt) when is_map(M) ->
Pairs = maps:to_list(M),
- Cpairs = [#c_map_pair{op=#c_literal{val=assoc},
+ Op = case Ctxt of
+ #ctxt{ class = clause } -> exact;
+ _ -> assoc
+ end,
+ Cpairs = [#c_map_pair{op=#c_literal{val=Op},
key=#c_literal{val=V},
val=#c_literal{val=K}} || {K,V} <- Pairs],
format_1(#c_map{anno=A,arg=#c_literal{val=#{}},es=Cpairs},Ctxt);
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index b7422318b2..ce40213bad 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -1556,16 +1556,8 @@ map_pair_pattern_list(Ps0, Isub, Osub0) ->
{Ps,Osub}.
map_pair_pattern(#c_map_pair{op=#c_literal{val=exact},key=K0,val=V0}=Pair,{Isub,Osub0}) ->
- {K,Osub1} = case cerl:type(K0) of
- binary ->
- K1 = eval_binary(K0),
- case cerl:type(K1) of
- literal -> {K1,Osub0};
- _ -> pattern(K0,Isub,Osub0)
- end;
- _ -> pattern(K0,Isub,Osub0)
- end,
- {V,Osub} = pattern(V0,Isub,Osub1),
+ K = expr(K0, Isub),
+ {V,Osub} = pattern(V0,Isub,Osub0),
{Pair#c_map_pair{key=K,val=V},{Isub,Osub}}.
bin_pattern_list(Ps0, Isub, Osub0) ->
diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl
index 91a46a20fe..761ae8409c 100644
--- a/lib/compiler/src/sys_pre_expand.erl
+++ b/lib/compiler/src/sys_pre_expand.erl
@@ -232,7 +232,7 @@ pattern({map,Line,Ps}, St0) ->
{TPs,St1} = pattern_list(Ps, St0),
{{map,Line,TPs},St1};
pattern({map_field_exact,Line,K0,V0}, St0) ->
- {K,St1} = pattern(K0, St0),
+ {K,St1} = expr(K0, St0),
{V,St2} = pattern(V0, St1),
{{map_field_exact,Line,K,V},St2};
%%pattern({struct,Line,Tag,Ps}, St0) ->
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index a548ba2f7c..8c18f6a9f7 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -1605,26 +1605,17 @@ pattern_alias_map_pair_patterns([Cv1,Cv2|Cvs]) ->
pattern_alias_map_pair_patterns([pat_alias(Cv1,Cv2)|Cvs]).
pattern_map_pair({map_field_exact,L,K,V}, St) ->
- %% FIXME: Better way to construct literals? or missing case
- %% {Key,_,_} = expr(K, St),
- Key = case K of
- {bin,L,Es0} ->
- case constant_bin(Es0) of
- error ->
- %% this will throw a cryptic error message
- %% but it is better than nothing
- throw(nomatch);
- Bin ->
- #c_literal{anno=lineno_anno(L,St),val=Bin}
- end;
+ case expr(K,St) of
+ {#c_literal{}=Key,_,_} ->
+ #c_map_pair{anno=lineno_anno(L, St),
+ op=#c_literal{val=exact},
+ key=Key,
+ val=pattern(V, St)};
_ ->
- pattern(K,St)
- end,
- #c_map_pair{anno=lineno_anno(L, St),
- op=#c_literal{val=exact},
- key=Key,
- val=pattern(V, St)}.
-
+ %% this will throw a cryptic error message
+ %% but it is better than nothing
+ throw(nomatch)
+ end.
%% pat_bin([BinElement], State) -> [BinSeg].
diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl
index cc018e4305..403b7e8405 100644
--- a/lib/compiler/test/map_SUITE.erl
+++ b/lib/compiler/test/map_SUITE.erl
@@ -113,6 +113,10 @@ t_build_and_match_literals(Config) when is_list(Config) ->
M = #{ map_1:=#{ map_2:=#{value_3 := third}, value_2:= second}, value_1:=first} =
id(#{ map_1=>#{ map_2=>#{value_3 => third}, value_2=> second}, value_1=>first}),
+ %% map key
+ #{ #{} := 42 } = id(#{ #{} => 42 }),
+ #{ #{ "a" => 3 } := 42 } = id(#{ #{ "a" => 3} => 42 }),
+
%% nil key
#{[]:=ok,1:=2} = id(#{[]=>ok,1=>2}),
@@ -123,6 +127,7 @@ t_build_and_match_literals(Config) when is_list(Config) ->
{'EXIT',{{badmatch,_},_}} = (catch (#{x:=3} = id(#{y=>3}))),
{'EXIT',{{badmatch,_},_}} = (catch (#{x:=3} = id(#{x=>"three"}))),
{'EXIT',{badarg,_}} = (catch id(#{<<0:258>> =>"three"})),
+ {'EXIT',{{badmatch,_},_}} = (catch (#{#{"a"=>42} := 3}=id(#{#{"a"=>3}=>42}))),
ok.
t_build_and_match_aliasing(Config) when is_list(Config) ->