aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src/v3_kernel.erl
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2014-03-18 12:20:19 +0100
committerBjörn-Egil Dahlberg <[email protected]>2014-03-18 12:20:19 +0100
commita4d314a5298d9725fdd1874763e43b33a39252a0 (patch)
tree3beaa441407a6ec335e7bae501443e67a1c9e24e /lib/compiler/src/v3_kernel.erl
parent8d66a2823c29cbe44cf80e4de0c58f2ed5c29bd4 (diff)
parent5638ca15d05e9b05d64ade0e03492c13d020439b (diff)
downloadotp-a4d314a5298d9725fdd1874763e43b33a39252a0.tar.gz
otp-a4d314a5298d9725fdd1874763e43b33a39252a0.tar.bz2
otp-a4d314a5298d9725fdd1874763e43b33a39252a0.zip
Merge branch 'egil/maps-literals'
* egil/maps-literals: compiler: Transform M#{} to is_map(M) dialyzer: Do not native compile modules with Maps code hipe: Properly identify map() type form terms stdlib: Test Map key linting stdlib: Accept records as Map keys stdlib: Accept Maps as Map keys stdlib: Move map type to proper definition stdlib: Properly lint map key expressions compiler: Change #c_map{var} to #c_map{arg} compiler: Constant fold Maps that are safe compiler: Validate Map src compiler: Support literal maps in cerl_clauses:match/2 compiler: Guard BIF is_map/1 is pure erts: Handle literals in is_map/1 compiler: Change Maps Core Format compiler: Create literal Maps in creation if possible
Diffstat (limited to 'lib/compiler/src/v3_kernel.erl')
-rw-r--r--lib/compiler/src/v3_kernel.erl34
1 files changed, 30 insertions, 4 deletions
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index d00dd56f30..d3b785aa14 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -272,9 +272,18 @@ expr(#c_cons{anno=A,hd=Ch,tl=Ct}, Sub, St0) ->
expr(#c_tuple{anno=A,es=Ces}, Sub, St0) ->
{Kes,Ep,St1} = atomic_list(Ces, Sub, St0),
{#k_tuple{anno=A,es=Kes},Ep,St1};
-expr(#c_map{anno=A,var=Var0,es=Ces}, Sub, St0) ->
- {Var,[],St1} = expr(Var0, Sub, St0),
- map_split_pairs(A, Var, Ces, Sub, St1);
+expr(#c_map{anno=A,arg=Var,es=Ces}, Sub, St0) ->
+ try expr_map(A,Var,Ces,Sub,St0) of
+ {_,_,_}=Res -> Res
+ catch
+ throw:bad_map ->
+ St1 = add_warning(get_line(A), bad_map, A, St0),
+ Erl = #c_literal{val=erlang},
+ Name = #c_literal{val=error},
+ Args = [#c_literal{val=badarg}],
+ Error = #c_call{anno=A,module=Erl,name=Name,args=Args},
+ expr(Error, Sub, St1)
+ end;
expr(#c_binary{anno=A,segments=Cv}, Sub, St0) ->
try atomic_bin(Cv, Sub, St0) of
{Kv,Ep,St1} ->
@@ -496,6 +505,21 @@ translate_match_fail_1(Anno, As, Sub, #kern{ff=FF}) ->
translate_fc(Args) ->
[#c_literal{val=function_clause},make_list(Args)].
+expr_map(A,Var0,Ces,Sub,St0) ->
+ %% An extra pass of validation of Map src because of inlining
+ {Var,Mps,St1} = expr(Var0, Sub, St0),
+ case is_valid_map_src(Var) of
+ true ->
+ {Km,Eps,St2} = map_split_pairs(A, Var, Ces, Sub, St1),
+ {Km,Eps++Mps,St2};
+ false -> throw(bad_map)
+ end.
+
+is_valid_map_src(#k_map{}) -> true;
+is_valid_map_src(#k_literal{val=M}) when is_map(M) -> true;
+is_valid_map_src(#k_var{}) -> true;
+is_valid_map_src(_) -> false.
+
map_split_pairs(A, Var, Ces, Sub, St0) ->
%% two steps
%% 1. force variables
@@ -1986,7 +2010,9 @@ format_error(nomatch_shadow) ->
format_error(bad_call) ->
"invalid module and/or function name; this call will always fail";
format_error(bad_segment_size) ->
- "binary construction will fail because of a type mismatch".
+ "binary construction will fail because of a type mismatch";
+format_error(bad_map) ->
+ "map construction will fail because of a type mismatch".
add_warning(none, Term, Anno, #kern{ws=Ws}=St) ->
File = get_file(Anno),