From d4379900790b37498fefa237cd03ab2d5781bb6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 6 Nov 2013 08:58:32 +0100 Subject: compiler: Teach Maps understanding to inliner --- lib/compiler/src/cerl.erl | 107 +++++++++++++++++++++++++++++++++++++--- lib/compiler/src/cerl_trees.erl | 49 +++++++++++++++++- lib/compiler/src/core_lint.erl | 23 ++++++++- 3 files changed, 170 insertions(+), 9 deletions(-) diff --git a/lib/compiler/src/cerl.erl b/lib/compiler/src/cerl.erl index 4b74d60e9f..30bb4c5d96 100644 --- a/lib/compiler/src/cerl.erl +++ b/lib/compiler/src/cerl.erl @@ -120,7 +120,16 @@ update_c_bitstr/5, update_c_bitstr/6, ann_c_bitstr/5, ann_c_bitstr/6, is_c_bitstr/1, bitstr_val/1, bitstr_size/1, bitstr_bitsize/1, bitstr_unit/1, bitstr_type/1, - bitstr_flags/1]). + bitstr_flags/1, + + %% keep map exports here for now + map_es/1, + update_c_map_skel/2, + update_c_map_pair_assoc_skel/2, update_c_map_pair_exact_skel/2, + ann_c_map_skel/2, + ann_c_map_pair_assoc_skel/2, ann_c_map_pair_exact_skel/2, + map_pair_es/1, map_pair_assoc_es/1, map_pair_exact_es/1 + ]). -export_type([c_binary/0, c_call/0, c_clause/0, c_cons/0, c_fun/0, c_literal/0, c_module/0, c_tuple/0, c_values/0, c_var/0, cerl/0, var_name/0]). @@ -250,8 +259,8 @@ -type ctype() :: 'alias' | 'apply' | 'binary' | 'bitrst' | 'call' | 'case' | 'catch' | 'clause' | 'cons' | 'fun' | 'let' | 'letrec' - | 'literal' | 'module' | 'primop' | 'receive' | 'seq' | 'try' - | 'tuple' | 'values' | 'var'. + | 'literal' | 'map' | 'module' | 'primop' | 'receive' | 'seq' + | 'try' | 'tuple' | 'values' | 'var'. -spec type(cerl()) -> ctype(). @@ -268,6 +277,9 @@ type(#c_fun{}) -> 'fun'; type(#c_let{}) -> 'let'; type(#c_letrec{}) -> letrec; type(#c_literal{}) -> literal; +type(#c_map{}) -> map; +type(#c_map_pair_assoc{}) -> map_pair_assoc; +type(#c_map_pair_exact{}) -> map_pair_exact; type(#c_module{}) -> module; type(#c_primop{}) -> primop; type(#c_receive{}) -> 'receive'; @@ -1557,6 +1569,58 @@ ann_make_list(_, [], Node) -> Node. +%% --------------------------------------------------------------------- +%% maps + +map_es(#c_map{es = Es}) -> + Es. + +map_pair_assoc_es(#c_map_pair_assoc{key=K,val=V}) -> [K,V]. +map_pair_exact_es(#c_map_pair_exact{key=K,val=V}) -> [K,V]. +map_pair_es(#c_map_pair_assoc{key=K,val=V}) -> [K,V]; +map_pair_es(#c_map_pair_exact{key=K,val=V}) -> [K,V]. + +update_c_map_pair_assoc_skel(Old, [K,V]) -> + #c_map_pair_assoc{key=K, val=V, anno = get_ann(Old)}. + +update_c_map_pair_exact_skel(Old, [K,V]) -> + #c_map_pair_exact{key=K, val=V, anno = get_ann(Old)}. + +ann_c_map_pair_assoc_skel(As, [K,V]) -> + #c_map_pair_assoc{key = K, val=V, anno = As}. + +ann_c_map_pair_exact_skel(As, [K,V]) -> + #c_map_pair_exact{key = K, val=V, anno = As}. + +%c_map_skel(Es) -> +% #c_map{es = Es}. +% + +ann_c_map(As, Es) -> + #c_map{es = Es, anno = As }. +%% TODO: when we have map literals use a variant of +%% case is_lit_list(Es) of +%% false -> +%% #c_map{es = Es, anno = As}; +%% true -> +%% #c_literal{val = maps:from_list(lit_list_vals(Es)), anno = As} +%% end. + + +ann_c_map_pair_assoc(As, [K,V]) -> + #c_map_pair_assoc{key = K, val=V, anno = As}. + +ann_c_map_pair_exact(As, [K,V]) -> + #c_map_pair_exact{key = K, val=V, anno = As}. + + +ann_c_map_skel(As, Es) -> + #c_map{es = Es, anno = As}. + +update_c_map_skel(Old, Es) -> + #c_map{es = Es, anno = get_ann(Old)}. + + %% --------------------------------------------------------------------- %% @spec c_tuple(Elements::[cerl()]) -> cerl() @@ -2945,6 +3009,10 @@ pat_vars(Node, Vs) -> pat_vars(cons_hd(Node), pat_vars(cons_tl(Node), Vs)); tuple -> pat_list_vars(tuple_es(Node), Vs); + map -> + pat_list_vars(map_es(Node), Vs); + map_pair_exact -> + pat_list_vars(map_pair_exact_es(Node), Vs); binary -> pat_list_vars(binary_segments(Node), Vs); bitstr -> @@ -3756,6 +3824,12 @@ is_data(#c_cons{}) -> true; is_data(#c_tuple{}) -> true; +is_data(#c_map{}) -> + true; +is_data(#c_map_pair_assoc{}) -> + true; +is_data(#c_map_pair_exact{}) -> + true; is_data(_) -> false. @@ -3801,7 +3875,13 @@ data_type(#c_literal{val = V}) -> data_type(#c_cons{}) -> cons; data_type(#c_tuple{}) -> - tuple. + tuple; +data_type(#c_map{}) -> + map; +data_type(#c_map_pair_assoc{}) -> + map_pair_assoc; +data_type(#c_map_pair_exact{}) -> + map_pair_exact. %% @spec data_es(Node::cerl()) -> [cerl()] @@ -3833,7 +3913,13 @@ data_es(#c_literal{val = V}) -> data_es(#c_cons{hd = H, tl = T}) -> [H, T]; data_es(#c_tuple{es = Es}) -> - Es. + Es; +data_es(#c_map{es=Es}) -> + Es; +data_es(#c_map_pair_assoc{key=K,val=V}) -> + [K,V]; +data_es(#c_map_pair_exact{key=K,val=V}) -> + [K,V]. %% @spec data_arity(Node::cerl()) -> integer() @@ -3890,7 +3976,10 @@ make_data(CType, Es) -> ann_make_data(As, {atomic, V}, []) -> #c_literal{val = V, anno = As}; ann_make_data(As, cons, [H, T]) -> ann_c_cons(As, H, T); -ann_make_data(As, tuple, Es) -> ann_c_tuple(As, Es). +ann_make_data(As, tuple, Es) -> ann_c_tuple(As, Es); +ann_make_data(As, map, Es) -> ann_c_map(As, Es); +ann_make_data(As, map_pair_assoc, Es) -> ann_c_map_pair_assoc(As, Es); +ann_make_data(As, map_pair_exact, Es) -> ann_c_map_pair_exact(As, Es). %% @spec update_data(Old::cerl(), Type::dtype(), @@ -4022,6 +4111,12 @@ subtrees(T) -> [[cons_hd(T)], [cons_tl(T)]]; tuple -> [tuple_es(T)]; + map -> + [map_es(T)]; + map_pair_assoc -> + [map_pair_assoc_es(T)]; + map_pair_exact -> + [map_pair_exact_es(T)]; 'let' -> [let_vars(T), [let_arg(T)], [let_body(T)]]; seq -> diff --git a/lib/compiler/src/cerl_trees.erl b/lib/compiler/src/cerl_trees.erl index 1e3755025f..dc1cc606b3 100644 --- a/lib/compiler/src/cerl_trees.erl +++ b/lib/compiler/src/cerl_trees.erl @@ -55,7 +55,15 @@ update_c_let/4, update_c_letrec/3, update_c_module/5, update_c_primop/3, update_c_receive/4, update_c_seq/3, update_c_try/6, update_c_tuple/2, update_c_tuple_skel/2, - update_c_values/2, values_es/1, var_name/1]). + update_c_values/2, values_es/1, var_name/1, + + map_es/1, + update_c_map_skel/2, + update_c_map_pair_assoc_skel/2, update_c_map_pair_exact_skel/2, + ann_c_map_skel/2, + ann_c_map_pair_assoc_skel/2, ann_c_map_pair_exact_skel/2, + map_pair_assoc_es/1, map_pair_exact_es/1 + ]). %% --------------------------------------------------------------------- @@ -129,6 +137,12 @@ map_1(F, T) -> map(F, cons_tl(T))); tuple -> update_c_tuple_skel(T, map_list(F, tuple_es(T))); + map -> + update_c_map_skel(T, map_list(F, map_es(T))); + map_pair_assoc -> + update_c_map_pair_assoc_skel(T, map_list(F, map_pair_assoc_es(T))); + map_pair_exact -> + update_c_map_pair_exact_skel(T, map_list(F, map_pair_exact_es(T))); 'let' -> update_c_let(T, map_list(F, let_vars(T)), map(F, let_arg(T)), @@ -235,6 +249,12 @@ fold_1(F, S, T) -> fold(F, fold(F, S, cons_hd(T)), cons_tl(T)); tuple -> fold_list(F, S, tuple_es(T)); + map -> + fold_list(F, S, map_es(T)); + map_pair_assoc -> + fold_list(F, S, map_pair_assoc_es(T)); + map_pair_exact -> + fold_list(F, S, map_pair_exact_es(T)); 'let' -> fold(F, fold(F, fold_list(F, S, let_vars(T)), let_arg(T)), @@ -349,6 +369,15 @@ mapfold(F, S0, T) -> tuple -> {Ts, S1} = mapfold_list(F, S0, tuple_es(T)), F(update_c_tuple_skel(T, Ts), S1); + map -> + {Ts, S1} = mapfold_list(F, S0, map_es(T)), + F(update_c_map_skel(T, Ts), S1); + map_pair_assoc -> + {Ts, S1} = mapfold_list(F, S0, map_pair_assoc_es(T)), + F(update_c_map_pair_assoc_skel(T,Ts), S1); + map_pair_exact -> + {Ts, S1} = mapfold_list(F, S0, map_pair_exact_es(T)), + F(update_c_map_pair_exact_skel(T,Ts), S1); 'let' -> {Vs, S1} = mapfold_list(F, S0, let_vars(T)), {A, S2} = mapfold(F, S1, let_arg(T)), @@ -488,6 +517,12 @@ variables(T, S) -> variables(cons_tl(T), S)); tuple -> vars_in_list(tuple_es(T), S); + map -> + vars_in_list(map_es(T), S); + map_pair_assoc -> + vars_in_list(map_pair_assoc_es(T), S); + map_pair_exact -> + vars_in_list(map_pair_exact_es(T), S); 'let' -> Vs = variables(let_body(T), S), Vs1 = var_list_names(let_vars(T)), @@ -688,6 +723,18 @@ label(T, N, Env) -> {Ts, N1} = label_list(tuple_es(T), N, Env), {As, N2} = label_ann(T, N1), {ann_c_tuple_skel(As, Ts), N2}; + map -> + {Ts, N1} = label_list(map_es(T), N, Env), + {As, N2} = label_ann(T, N1), + {ann_c_map_skel(As, Ts), N2}; + map_pair_assoc -> + {Ts, N1} = label_list(map_pair_assoc_es(T), N, Env), + {As, N2} = label_ann(T, N1), + {ann_c_map_pair_assoc_skel(As, Ts), N2}; + map_pair_exact -> + {Ts, N1} = label_list(map_pair_exact_es(T), N, Env), + {As, N2} = label_ann(T, N1), + {ann_c_map_pair_exact_skel(As, Ts), N2}; 'let' -> {A, N1} = label(let_arg(T), N, Env), {Vs, N2, Env1} = label_vars(let_vars(T), N1, Env), diff --git a/lib/compiler/src/core_lint.erl b/lib/compiler/src/core_lint.erl index 67d37ff1fc..185193e45d 100644 --- a/lib/compiler/src/core_lint.erl +++ b/lib/compiler/src/core_lint.erl @@ -254,6 +254,12 @@ gexpr(#c_cons{hd=H,tl=T}, Def, _Rt, St) -> gexpr_list([H,T], Def, St); gexpr(#c_tuple{es=Es}, Def, _Rt, St) -> gexpr_list(Es, Def, St); +gexpr(#c_map{es=Es}, Def, _Rt, St) -> + gexpr_list(Es, Def, St); +gexpr(#c_map_pair_assoc{key=K,val=V}, Def, _Rt, St) -> + gexpr_list([K,V], Def, St); +gexpr(#c_map_pair_exact{key=K,val=V}, Def, _Rt, St) -> + gexpr_list([K,V], Def, St); gexpr(#c_binary{segments=Ss}, Def, _Rt, St) -> gbitstr_list(Ss, Def, St); gexpr(#c_seq{arg=Arg,body=B}, Def, Rt, St0) -> @@ -278,6 +284,7 @@ gexpr(#c_case{arg=Arg,clauses=Cs}, Def, Rt, St0) -> St1 = gbody(Arg, Def, PatCount, St0), clauses(Cs, Def, PatCount, Rt, St1); gexpr(_Core, _, _, St) -> + %%io:fwrite("clint gexpr: ~p~n", [_Core]), add_error({illegal_guard,St#lint.func}, St). %% gexpr_list([Expr], Defined, State) -> State. @@ -303,6 +310,12 @@ expr(#c_cons{hd=H,tl=T}, Def, _Rt, St) -> expr_list([H,T], Def, St); expr(#c_tuple{es=Es}, Def, _Rt, St) -> expr_list(Es, Def, St); +expr(#c_map{es=Es}, Def, _Rt, St) -> + expr_list(Es, Def, St); +expr(#c_map_pair_assoc{key=K,val=V},Def,_Rt,St) -> + expr_list([K,V],Def,St); +expr(#c_map_pair_exact{key=K,val=V},Def,_Rt,St) -> + expr_list([K,V],Def,St); expr(#c_binary{segments=Ss}, Def, _Rt, St) -> bitstr_list(Ss, Def, St); expr(#c_fun{vars=Vs,body=B}, Def, Rt, St0) -> @@ -355,7 +368,7 @@ expr(#c_try{arg=A,vars=Vs,body=B,evars=Evs,handler=H}, Def, Rt, St0) -> {Ens,St5} = variable_list(Evs, St4), body(H, union(Ens, Def), Rt, St5); expr(_Other, _, _, St) -> - %%io:fwrite("clint: ~p~n", [_Other]), + %%io:fwrite("clint expr: ~p~n", [_Other]), add_error({illegal_expr,St#lint.func}, St). %% expr_list([Expr], Defined, State) -> State. @@ -454,13 +467,19 @@ pattern(#c_cons{hd=H,tl=T}, Def, Ps, St) -> pattern_list([H,T], Def, Ps, St); pattern(#c_tuple{es=Es}, Def, Ps, St) -> pattern_list(Es, Def, Ps, St); +pattern(#c_map{es=Es}, Def, Ps, St) -> + pattern_list(Es, Def, Ps, St); +pattern(#c_map_pair_exact{key=K,val=V},Def,Ps,St) -> + pattern_list([K,V],Def,Ps,St); pattern(#c_binary{segments=Ss}, Def, Ps, St0) -> St = pat_bin_tail_check(Ss, St0), pat_bin(Ss, Def, Ps, St); pattern(#c_alias{var=V,pat=P}, Def, Ps, St0) -> {Vvs,St1} = variable(V, Ps, St0), pattern(P, Def, union(Vvs, Ps), St1); -pattern(_, _, Ps, St) -> {Ps,add_error({not_pattern,St#lint.func}, St)}. +pattern(_Other, _, Ps, St) -> + %%io:fwrite("clint pattern: ~p~n", [_Other]), + {Ps,add_error({not_pattern,St#lint.func}, St)}. pat_var(N, _Def, Ps, St) -> case is_element(N, Ps) of -- cgit v1.2.3