aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib')
-rw-r--r--lib/stdlib/src/erl_eval.erl30
-rw-r--r--lib/stdlib/src/erl_pp.erl19
-rw-r--r--lib/stdlib/src/re.erl3
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl19
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl23
5 files changed, 79 insertions, 15 deletions
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index 5f96795d92..63e7be4b74 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -241,23 +241,15 @@ expr({record,_,_,Name,_}, _Bs, _Lf, _Ef, _RBs) ->
erlang:raise(error, {undef_record,Name}, stacktrace());
%% map
-expr({map_field_assoc,_,EK, EV}, Bs0, Lf, Ef, RBs) ->
- {value,K,Bs1} = expr(EK, Bs0, Lf, Ef, none),
- {value,V,Bs2} = expr(EV, Bs0, Lf, Ef, none),
- ret_expr({map_assoc,K,V}, merge_bindings(Bs1,Bs2), RBs);
-expr({map_field_exact,_,EK, EV}, Bs0, Lf, Ef, RBs) ->
- {value,K,Bs1} = expr(EK, Bs0, Lf, Ef, none),
- {value,V,Bs2} = expr(EV, Bs0, Lf, Ef, none),
- ret_expr({map_exact,K,V}, merge_bindings(Bs1,Bs2), RBs);
expr({map,_, Binding,Es}, Bs0, Lf, Ef, RBs) ->
{value, Map0, Bs1} = expr(Binding, Bs0, Lf, Ef, RBs),
- {Vs,Bs} = expr_list(Es, Bs1, Lf, Ef),
+ {Vs,Bs} = eval_map_fields(Es, Bs1, Lf, Ef),
ret_expr(lists:foldl(fun
({map_assoc,K,V}, Mi) -> maps:put(K,V,Mi);
({map_exact,K,V}, Mi) -> maps:update(K,V,Mi)
end, Map0, Vs), Bs, RBs);
expr({map,_,Es}, Bs0, Lf, Ef, RBs) ->
- {Vs,Bs} = expr_list(Es, Bs0, Lf, Ef),
+ {Vs,Bs} = eval_map_fields(Es, Bs0, Lf, Ef),
ret_expr(lists:foldl(fun
({map_assoc,K,V}, Mi) -> maps:put(K,V,Mi)
end, maps:new(), Vs), Bs, RBs);
@@ -749,6 +741,24 @@ eval_filter(F, Bs0, Lf, Ef, CompFun, Acc) ->
end
end.
+%% eval_map_fields([Field], Bindings, LocalFunctionHandler,
+%% ExternalFuncHandler) ->
+%% {[{map_assoc | map_exact,Key,Value}],Bindings}
+
+eval_map_fields(Fs, Bs, Lf, Ef) ->
+ eval_map_fields(Fs, Bs, Lf, Ef, []).
+
+eval_map_fields([{map_field_assoc,_,K0,V0}|Fs], Bs0, Lf, Ef, Acc) ->
+ {value,K1,Bs1} = expr(K0, Bs0, Lf, Ef, none),
+ {value,V1,Bs2} = expr(V0, Bs1, Lf, Ef, none),
+ eval_map_fields(Fs, Bs2, Lf, Ef, [{map_assoc,K1,V1}|Acc]);
+eval_map_fields([{map_field_exact,_,K0,V0}|Fs], Bs0, Lf, Ef, Acc) ->
+ {value,K1,Bs1} = expr(K0, Bs0, Lf, Ef, none),
+ {value,V1,Bs2} = expr(V0, Bs1, Lf, Ef, none),
+ eval_map_fields(Fs, Bs2, Lf, Ef, [{map_exact,K1,V1}|Acc]);
+eval_map_fields([], Bs, _Lf, _Ef, Acc) ->
+ {lists:reverse(Acc),Bs}.
+
%% RBs is the bindings to return when the evalution of a function
%% (fun) has finished. If RBs =:= none, then the evalution took place
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index 8a1d8e0440..9dbe89da91 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -479,6 +479,15 @@ lexpr({record_field, _, Rec, F}, Prec, Opts) ->
{L,P,R} = inop_prec('.'),
El = [lexpr(Rec, L, Opts),$.,lexpr(F, R, Opts)],
maybe_paren(P, Prec, El);
+lexpr({map, _, Fs}, Prec, Opts) ->
+ {P,_R} = preop_prec('#'),
+ El = {first,leaf("#"),map_fields(Fs, Opts)},
+ maybe_paren(P, Prec, El);
+lexpr({map, _, Map, Fs}, Prec, Opts) ->
+ {L,P,_R} = inop_prec('#'),
+ Rl = lexpr(Map, L, Opts),
+ El = {first,[Rl,leaf("#")],map_fields(Fs, Opts)},
+ maybe_paren(P, Prec, El);
lexpr({block,_,Es}, _, Opts) ->
{list,[{step,'begin',body(Es, Opts)},'end']};
lexpr({'if',_,Cs}, _, Opts) ->
@@ -671,6 +680,16 @@ record_field({typed_record_field,Field,Type}, Opts) ->
record_field({record_field,_,F}, Opts) ->
lexpr(F, 0, Opts).
+map_fields(Fs, Opts) ->
+ tuple(Fs, fun map_field/2, Opts).
+
+map_field({map_field_assoc,_,K,V}, Opts) ->
+ Pl = lexpr(K, 0, Opts),
+ {list,[{step,[Pl,leaf(" =>")],lexpr(V, 0, Opts)}]};
+map_field({map_field_exact,_,K,V}, Opts) ->
+ Pl = lexpr(K, 0, Opts),
+ {list,[{step,[Pl,leaf(" :=")],lexpr(V, 0, Opts)}]}.
+
list({cons,_,H,T}, Es, Opts) ->
list(T, [H|Es], Opts);
list({nil,_}, Es, Opts) ->
diff --git a/lib/stdlib/src/re.erl b/lib/stdlib/src/re.erl
index afc63496d0..7f3cd8f592 100644
--- a/lib/stdlib/src/re.erl
+++ b/lib/stdlib/src/re.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2014. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -19,7 +19,6 @@
-module(re).
-export([grun/3,urun/3,ucompile/2,replace/3,replace/4,split/2,split/3]).
-%-opaque mp() :: {re_pattern, _, _, _, _}.
-type mp() :: {re_pattern, _, _, _, _}.
-type nl_spec() :: cr | crlf | lf | anycrlf | any.
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index c4b6b35e72..b194c7cb41 100644
--- a/lib/stdlib/test/erl_eval_SUITE.erl
+++ b/lib/stdlib/test/erl_eval_SUITE.erl
@@ -42,7 +42,8 @@
try_catch/1,
eval_expr_5/1,
zero_width/1,
- eep37/1]).
+ eep37/1,
+ eep43/1]).
%%
%% Define to run outside of test server
@@ -82,7 +83,7 @@ all() ->
simple_cases, unary_plus, apply_atom, otp_5269,
otp_6539, otp_6543, otp_6787, otp_6977, otp_7550,
otp_8133, otp_10622, funs, try_catch, eval_expr_5, zero_width,
- eep37].
+ eep37, eep43].
groups() ->
[].
@@ -1424,6 +1425,20 @@ eep37(Config) when is_list(Config) ->
720),
ok.
+eep43(Config) when is_list(Config) ->
+ check(fun () -> #{} end, " #{}.", #{}),
+ check(fun () -> #{a => b} end, "#{a => b}.", #{a => b}),
+ check(fun () ->
+ Map = #{a => b},
+ {Map#{a := b},Map#{a => c},Map#{d => e}}
+ end,
+ "begin "
+ " Map = #{a => B=b}, "
+ " {Map#{a := B},Map#{a => c},Map#{d => e}} "
+ "end.",
+ {#{a => b},#{a => c},#{a => b,d => e}}),
+ ok.
+
%% Check the string in different contexts: as is; in fun; from compiled code.
check(F, String, Result) ->
check1(F, String, Result),
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index cc744ee76b..390322a5fa 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -46,6 +46,7 @@
import_export/1, misc_attrs/1, dialyzer_attrs/1,
hook/1,
neg_indent/1,
+ maps_syntax/1,
otp_6321/1, otp_6911/1, otp_6914/1, otp_8150/1, otp_8238/1,
otp_8473/1, otp_8522/1, otp_8567/1, otp_8664/1, otp_9147/1,
@@ -76,7 +77,8 @@ groups() ->
[{expr, [],
[func, call, recs, try_catch, if_then, receive_after,
bits, head_tail, cond1, block, case1, ops,
- messages, old_mnemosyne_syntax]},
+ messages, old_mnemosyne_syntax, maps_syntax
+ ]},
{attributes, [], [misc_attrs, import_export, dialyzer_attrs]},
{tickets, [],
[otp_6321, otp_6911, otp_6914, otp_8150, otp_8238,
@@ -975,6 +977,25 @@ count_atom(L, A) when is_list(L) ->
count_atom(_, _) ->
0.
+maps_syntax(doc) -> "Maps syntax";
+maps_syntax(suite) -> [];
+maps_syntax(Config) when is_list(Config) ->
+ Ts = [{map_fun_1,
+ <<"t() ->\n"
+ " M0 = #{ 1 => hi, hi => 42, 1.0 => {hi,world}},\n"
+ " M1 = M0#{ 1 := hello, new_val => 1337 },\n"
+ " map_fun_2:val(M1).\n">>},
+ {map_fun_2,
+ <<"val(#{ 1 := V1, hi := V2, new_val := V3}) -> {V1,V2,V3}.\n">>}],
+ compile(Config, Ts),
+
+ ok = pp_expr(<<"#{}">>),
+ ok = pp_expr(<<"#{ a => 1, <<\"hi\">> => \"world\", 33 => 1.0 }">>),
+ ok = pp_expr(<<"#{ a := V1, <<\"hi\">> := V2 } = M">>),
+ ok = pp_expr(<<"M#{ a => V1, <<\"hi\">> := V2 }">>),
+ ok.
+
+
otp_8567(doc) ->
"OTP_8567. Avoid duplicated 'undefined' in record field types.";
otp_8567(suite) -> [];