From 3c5067eab057391e101845b03c1ba7b76d2b3562 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 1 Oct 2013 23:42:17 +0200 Subject: compiler: Implement support for exact Op in Maps The syntax is handled upto v3_kernel where it is reduced to previous behaviour for construction and updates. Meaning, the ':=' operator is handled exactly as '=>' operator. --- lib/compiler/src/core_lib.erl | 4 +++- lib/compiler/src/sys_core_dsetel.erl | 10 +++++++--- lib/compiler/src/sys_core_fold.erl | 22 ++++++++++++++++------ lib/compiler/src/v3_core.erl | 35 +++++++++++++++++++++++------------ lib/compiler/src/v3_kernel.erl | 18 ++++++++++++------ 5 files changed, 61 insertions(+), 28 deletions(-) diff --git a/lib/compiler/src/core_lib.erl b/lib/compiler/src/core_lib.erl index f506901099..d6221a22bb 100644 --- a/lib/compiler/src/core_lib.erl +++ b/lib/compiler/src/core_lib.erl @@ -107,7 +107,9 @@ vu_expr(V, #c_tuple{es=Es}) -> vu_expr_list(V, Es); vu_expr(V, #c_map{es=Es}) -> vu_expr_list(V, Es); -vu_expr(V, #c_map_pair{key=Key,val=Val}) -> +vu_expr(V, #c_map_pair_assoc{key=Key,val=Val}) -> + vu_expr_list(V, [Key,Val]); +vu_expr(V, #c_map_pair_exact{key=Key,val=Val}) -> vu_expr_list(V, [Key,Val]); vu_expr(V, #c_binary{segments=Ss}) -> vu_seg_list(V, Ss); diff --git a/lib/compiler/src/sys_core_dsetel.erl b/lib/compiler/src/sys_core_dsetel.erl index c7c8343c35..f921429409 100644 --- a/lib/compiler/src/sys_core_dsetel.erl +++ b/lib/compiler/src/sys_core_dsetel.erl @@ -105,10 +105,14 @@ visit(Env0, #c_tuple{es=Es0}=R) -> visit(Env0, #c_map{es=Es0}=R) -> {Es1,Env1} = visit_list(Env0, Es0), {R#c_map{es=Es1}, Env1}; -visit(Env0, #c_map_pair{key=K0,val=V0}=R) -> +visit(Env0, #c_map_pair_assoc{key=K0,val=V0}=R) -> {K,Env1} = visit(Env0, K0), {V,Env2} = visit(Env1, V0), - {R#c_map_pair{key=K,val=V}, Env2}; + {R#c_map_pair_assoc{key=K,val=V}, Env2}; +visit(Env0, #c_map_pair_exact{key=K0,val=V0}=R) -> + {K,Env1} = visit(Env0, K0), + {V,Env2} = visit(Env1, V0), + {R#c_map_pair_exact{key=K,val=V}, Env2}; visit(Env0, #c_cons{hd=H0,tl=T0}=R) -> {H1,Env1} = visit(Env0, H0), {T1,Env2} = visit(Env1, T0), @@ -221,7 +225,7 @@ visit_pat(Env0, #c_tuple{es=Es}, Vs) -> visit_pats(Es, Env0, Vs); visit_pat(Env0, #c_map{es=Es}, Vs) -> visit_pats(Es, Env0, Vs); -visit_pat(Env0, #c_map_pair{key=V,val=K}, Vs0) -> +visit_pat(Env0, #c_map_pair_exact{key=V,val=K}, Vs0) -> {Vs1, Env1} = visit_pat(Env0, V, Vs0), visit_pat(Env1, K, Vs1); visit_pat(Env0, #c_cons{hd=H,tl=T}, Vs0) -> diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index cdbe2d0753..2cd6ea0e53 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -438,18 +438,28 @@ pair_list_reversed([E|Es],Ctxt,Sub,Out,Keys) -> %% check if key already is present in map, i.e. #{ a=>1, a=>2 } %% where 'a' is duplicate. Update maps set with the key if not present. -map_has_key(#c_map_pair{key=#c_literal{val=K}},Ks) -> +map_has_key(MapPair,Ks) -> + K = map_get_literal_key_from_pair(MapPair), case gb_sets:is_element(K,Ks) of false -> {false, gb_sets:add(K,Ks)}; true -> {true, K} end. -pair(#c_map_pair{key=K,val=V}, effect, Sub) -> +map_get_literal_key_from_pair(#c_map_pair_assoc{key=#c_literal{val=K}}) -> K; +map_get_literal_key_from_pair(#c_map_pair_exact{key=#c_literal{val=K}}) -> K. + +pair(#c_map_pair_assoc{key=K,val=V}, effect, Sub) -> + make_effect_seq([K,V], Sub); +pair(#c_map_pair_exact{key=K,val=V}, effect, Sub) -> make_effect_seq([K,V], Sub); -pair(#c_map_pair{key=K0,val=V0}=Pair, value=Ctxt, Sub) -> +pair(#c_map_pair_assoc{key=K0,val=V0}=Pair, value=Ctxt, Sub) -> + K = expr(K0, Ctxt, Sub), + V = expr(V0, Ctxt, Sub), + Pair#c_map_pair_assoc{key=K,val=V}; +pair(#c_map_pair_exact{key=K0,val=V0}=Pair, value=Ctxt, Sub) -> K = expr(K0, Ctxt, Sub), V = expr(V0, Ctxt, Sub), - Pair#c_map_pair{key=K,val=V}. + Pair#c_map_pair_exact{key=K,val=V}. bitstr_list(Es, Sub) -> [bitstr(E, Sub) || E <- Es]. @@ -1559,10 +1569,10 @@ map_pair_pattern_list(Ps0, Isub, Osub0) -> {Ps,{_,Osub}} = mapfoldl(fun map_pair_pattern/2, {Isub,Osub0}, Ps0), {Ps,Osub}. -map_pair_pattern(#c_map_pair{key=K0,val=V0}=Pair, {Isub,Osub0}) -> +map_pair_pattern(#c_map_pair_exact{key=K0,val=V0}=Pair, {Isub,Osub0}) -> {K,Osub1} = pattern(K0, Isub, Osub0), {V,Osub} = pattern(V0, Isub, Osub1), - {Pair#c_map_pair{key=K,val=V},{Isub,Osub}}. + {Pair#c_map_pair_exact{key=K,val=V},{Isub,Osub}}. bin_pattern_list(Ps0, Isub, Osub0) -> {Ps,{_,Osub}} = mapfoldl(fun bin_pattern/2, {Isub,Osub0}, Ps0), diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index 32b65333a4..b33799275b 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -488,6 +488,8 @@ expr({tuple,L,Es0}, St0) -> A = lineno_anno(L, St1), {ann_c_tuple(A, Es1),Eps,St1}; expr({map,L,Es0}, St0) -> + % erl_lint should make sure only #{ K => V } are allowed + % in map construction. {Es1,Eps,St1} = map_pair_list(Es0, St0), A = lineno_anno(L, St1), {#c_map{anno=A,es=Es1},Eps,St1}; @@ -705,13 +707,20 @@ make_bool_switch_guard(L, E, V, T, F) -> ]}. map_pair_list(Es, St) -> - foldr(fun ({map_field,L,K0,V0}, {Ces,Esp,St0}) -> - {K,Ep0,St1} = safe(K0, St0), - {V,Ep1,St2} = safe(V0, St1), - A = lineno_anno(L, St2), - Pair = #c_map_pair{anno=A,key=K,val=V}, - {[Pair|Ces],Ep0 ++ Ep1 ++ Esp,St2} - end, {[],[],St}, Es). + foldr(fun + ({map_field_assoc,L,K0,V0}, {Ces,Esp,St0}) -> + {K,Ep0,St1} = safe(K0, St0), + {V,Ep1,St2} = safe(V0, St1), + A = lineno_anno(L, St2), + Pair = #c_map_pair_assoc{anno=A,key=K,val=V}, + {[Pair|Ces],Ep0 ++ Ep1 ++ Esp,St2}; + ({map_field_exact,L,K0,V0}, {Ces,Esp,St0}) -> + {K,Ep0,St1} = safe(K0, St0), + {V,Ep1,St2} = safe(V0, St1), + A = lineno_anno(L, St2), + Pair = #c_map_pair_exact{anno=A,key=K,val=V}, + {[Pair|Ces],Ep0 ++ Ep1 ++ Esp,St2} + end, {[],[],St}, Es). %% try_exception([ExcpClause], St) -> {[ExcpVar],Handler,St}. @@ -1497,7 +1506,7 @@ pattern({tuple,L,Ps}, St) -> ann_c_tuple(lineno_anno(L, St), pattern_list(Ps, St)); pattern({map,L,Ps}, St) -> #c_map{anno=lineno_anno(L, St),es=sort(pattern_list(Ps, St))}; -pattern({map_field,L,K,V}, St) -> +pattern({map_field_exact,L,K,V}, St) -> %% FIXME: Better way to construct literals? or missing case %% {Key,_,_} = expr(K, St), Key = case K of @@ -1511,7 +1520,7 @@ pattern({map_field,L,K,V}, St) -> _ -> pattern(K,St) end, - #c_map_pair{anno=lineno_anno(L, St), + #c_map_pair_exact{anno=lineno_anno(L, St), key=Key, val=pattern(V, St)}; pattern({bin,L,Ps}, St) -> @@ -1862,9 +1871,9 @@ upattern(#c_tuple{es=Es0}=Tuple, Ks, St0) -> upattern(#c_map{es=Es0}=Map, Ks, St0) -> {Es1,Esg,Esv,Eus,St1} = upattern_list(Es0, Ks, St0), {Map#c_map{es=Es1},Esg,Esv,Eus,St1}; -upattern(#c_map_pair{val=V0}=MapPair, Ks, St0) -> +upattern(#c_map_pair_exact{val=V0}=MapPair, Ks, St0) -> {V,Vg,Vv,Vu,St1} = upattern(V0, Ks, St0), - {MapPair#c_map_pair{val=V},Vg,Vv,Vu,St1}; + {MapPair#c_map_pair_exact{val=V},Vg,Vv,Vu,St1}; upattern(#c_binary{segments=Es0}=Bin, Ks, St0) -> {Es1,Esg,Esv,Eus,St1} = upat_bin(Es0, Ks, St0), {Bin#c_binary{segments=Es1},Esg,Esv,Eus,St1}; @@ -2195,7 +2204,9 @@ is_simple(#c_cons{hd=H,tl=T}) -> is_simple(H) andalso is_simple(T); is_simple(#c_tuple{es=Es}) -> is_simple_list(Es); is_simple(#c_map{es=Es}) -> is_simple_list(Es); -is_simple(#c_map_pair{key=K,val=V}) -> +is_simple(#c_map_pair_assoc{key=K,val=V}) -> + is_simple(K) andalso is_simple(V); +is_simple(#c_map_pair_exact{key=K,val=V}) -> is_simple(K) andalso is_simple(V); is_simple(_) -> false. diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl index f4ba60e529..44f853ec2b 100644 --- a/lib/compiler/src/v3_kernel.erl +++ b/lib/compiler/src/v3_kernel.erl @@ -497,12 +497,18 @@ translate_match_fail_1(Anno, As, Sub, #kern{ff=FF}) -> translate_fc(Args) -> [#c_literal{val=function_clause},make_list(Args)]. +%% FIXME: Not completed map_pairs(Es, Sub, St) -> - foldr(fun(#c_map_pair{key=K0,val=V0}, {Kes,Esp,St0}) -> - {K,[],St1} = expr(K0, Sub, St0), - {V,Ep,St2} = atomic(V0, Sub, St1), - {[#k_map_pair{key=K,val=V}|Kes],Ep ++ Esp,St2} - end, {[],[],St}, Es). + foldr(fun + (#c_map_pair_assoc{key=K0,val=V0}, {Kes,Esp,St0}) -> + {K,[],St1} = expr(K0, Sub, St0), + {V,Ep,St2} = atomic(V0, Sub, St1), + {[#k_map_pair{key=K,val=V}|Kes],Ep ++ Esp,St2}; + (#c_map_pair_exact{key=K0,val=V0}, {Kes,Esp,St0}) -> + {K,[],St1} = expr(K0, Sub, St0), + {V,Ep,St2} = atomic(V0, Sub, St1), + {[#k_map_pair{key=K,val=V}|Kes],Ep ++ Esp,St2} + end, {[],[],St}, Es). %% call_type(Module, Function, Arity) -> call | bif | apply | error. %% Classify the call. @@ -662,7 +668,7 @@ pattern(#c_tuple{anno=A,es=Ces}, Isub, Osub0, St0) -> pattern(#c_map{anno=A,es=Ces}, Isub, Osub0, St0) -> {Kes,Osub1,St1} = pattern_list(Ces, Isub, Osub0, St0), {#k_map{anno=A,es=Kes},Osub1,St1}; -pattern(#c_map_pair{anno=A,key=Ck,val=Cv},Isub, Osub0, St0) -> +pattern(#c_map_pair_exact{anno=A,key=Ck,val=Cv},Isub, Osub0, St0) -> {Kk,Osub1,St1} = pattern(Ck, Isub, Osub0, St0), {Kv,Osub2,St2} = pattern(Cv, Isub, Osub1, St1), {#k_map_pair{anno=A,key=Kk,val=Kv},Osub2,St2}; -- cgit v1.2.3