aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2013-11-06 08:58:32 +0100
committerBjörn-Egil Dahlberg <[email protected]>2014-01-28 15:56:28 +0100
commitd4379900790b37498fefa237cd03ab2d5781bb6a (patch)
tree325ed00fd12baa5bef7f5712baa605c06f3f6695 /lib
parent813f61de8e7872481a0369de3297596c1b11881d (diff)
downloadotp-d4379900790b37498fefa237cd03ab2d5781bb6a.tar.gz
otp-d4379900790b37498fefa237cd03ab2d5781bb6a.tar.bz2
otp-d4379900790b37498fefa237cd03ab2d5781bb6a.zip
compiler: Teach Maps understanding to inliner
Diffstat (limited to 'lib')
-rw-r--r--lib/compiler/src/cerl.erl107
-rw-r--r--lib/compiler/src/cerl_trees.erl49
-rw-r--r--lib/compiler/src/core_lint.erl23
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';
@@ -1558,6 +1570,58 @@ ann_make_list(_, [], 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