diff options
Diffstat (limited to 'lib/stdlib/src')
-rw-r--r-- | lib/stdlib/src/array.erl | 102 | ||||
-rw-r--r-- | lib/stdlib/src/dict.erl | 124 | ||||
-rw-r--r-- | lib/stdlib/src/digraph.erl | 98 | ||||
-rw-r--r-- | lib/stdlib/src/digraph_utils.erl | 44 | ||||
-rw-r--r-- | lib/stdlib/src/edlin_expand.erl | 8 | ||||
-rw-r--r-- | lib/stdlib/src/epp.erl | 8 | ||||
-rw-r--r-- | lib/stdlib/src/erl_eval.erl | 30 | ||||
-rw-r--r-- | lib/stdlib/src/erl_expand_records.erl | 14 | ||||
-rw-r--r-- | lib/stdlib/src/erl_lint.erl | 102 | ||||
-rw-r--r-- | lib/stdlib/src/erl_pp.erl | 19 | ||||
-rw-r--r-- | lib/stdlib/src/ets.erl | 4 | ||||
-rw-r--r-- | lib/stdlib/src/gb_sets.erl | 167 | ||||
-rw-r--r-- | lib/stdlib/src/gb_trees.erl | 139 | ||||
-rw-r--r-- | lib/stdlib/src/lists.erl | 15 | ||||
-rw-r--r-- | lib/stdlib/src/otp_internal.erl | 18 | ||||
-rw-r--r-- | lib/stdlib/src/queue.erl | 75 | ||||
-rw-r--r-- | lib/stdlib/src/re.erl | 3 | ||||
-rw-r--r-- | lib/stdlib/src/sets.erl | 114 | ||||
-rw-r--r-- | lib/stdlib/src/sofs.erl | 10 | ||||
-rw-r--r-- | lib/stdlib/src/stdlib.appup.src | 12 | ||||
-rw-r--r-- | lib/stdlib/src/supervisor.erl | 52 | ||||
-rw-r--r-- | lib/stdlib/src/supervisor_bridge.erl | 11 |
22 files changed, 618 insertions, 551 deletions
diff --git a/lib/stdlib/src/array.erl b/lib/stdlib/src/array.erl index 2f69e2b0a4..10d2ccea45 100644 --- a/lib/stdlib/src/array.erl +++ b/lib/stdlib/src/array.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-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 @@ -86,6 +86,8 @@ foldr/3, sparse_foldl/3, sparse_foldr/3, fix/1, relax/1, is_fix/1, resize/1, resize/2]). +-export_type([array/0, array/1]). + %%-define(TEST,1). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). @@ -144,18 +146,28 @@ %%-------------------------------------------------------------------------- +-type element_tuple(T) :: + {T, T, T, T, T, T, T, T, T, T} + | {element_tuple(T), element_tuple(T), element_tuple(T), + element_tuple(T), element_tuple(T), element_tuple(T), + element_tuple(T), element_tuple(T), element_tuple(T), + element_tuple(T), non_neg_integer()}. + +-type elements(T) :: non_neg_integer() + | element_tuple(T) + | nil(). % kill reference, for GC + -record(array, {size :: non_neg_integer(), %% number of defined entries max :: non_neg_integer(), %% maximum number of entries %% in current tree default, %% the default value (usually 'undefined') - elements %% the tuple tree + elements :: elements(_) %% the tuple tree }). -%% A declaration equivalent to the following one is hard-coded in erl_types. -%% That declaration contains hard-coded information about the #array{} -%% structure and the types of its fields. So, please make sure that any -%% changes to its structure are also propagated to erl_types.erl. -%% -%% -opaque array() :: #array{}. + +-opaque array() :: array(term()). + +-opaque array(Type) :: + #array{default :: Type, elements :: elements(Type)}. %% %% Types @@ -164,13 +176,13 @@ -type array_indx() :: non_neg_integer(). -type array_opt() :: {'fixed', boolean()} | 'fixed' - | {'default', Value :: term()} + | {'default', Type :: term()} | {'size', N :: non_neg_integer()} | (N :: non_neg_integer()). -type array_opts() :: array_opt() | [array_opt()]. --type indx_pair() :: {Index :: array_indx(), Value :: term()}. --type indx_pairs() :: [indx_pair()]. +-type indx_pair(Type) :: {Index :: array_indx(), Type}. +-type indx_pairs(Type) :: [indx_pair(Type)]. %%-------------------------------------------------------------------------- @@ -321,7 +333,7 @@ size(_) -> erlang:error(badarg). %% %% @see new/2 --spec default(Array :: array()) -> term(). +-spec default(Array :: array(Type)) -> Value :: Type. default(#array{default = D}) -> D; default(_) -> erlang:error(badarg). @@ -404,7 +416,7 @@ new_test_() -> %% automatically upon insertion; see also {@link set/3}. %% @see relax/1 --spec fix(Array :: array()) -> array(). +-spec fix(Array :: array(Type)) -> array(Type). fix(#array{}=A) -> A#array{max = 0}. @@ -452,7 +464,7 @@ fix_test_() -> %% fix/1}.) %% @see fix/1 --spec relax(Array :: array()) -> array(). +-spec relax(Array :: array(Type)) -> array(Type). relax(#array{size = N}=A) -> A#array{max = find_max(N-1, ?LEAFSIZE)}. @@ -477,7 +489,8 @@ relax_test_() -> %% integer, the call fails with reason `badarg'. If the given array has %% fixed size, the resulting array will also have fixed size. --spec resize(Size :: non_neg_integer(), Array :: array()) -> array(). +-spec resize(Size :: non_neg_integer(), Array :: array(Type)) -> + array(Type). resize(Size, #array{size = N, max = M, elements = E}=A) when is_integer(Size), Size >= 0 -> @@ -508,7 +521,7 @@ resize(_Size, _) -> %% @see resize/2 %% @see sparse_size/1 --spec resize(Array :: array()) -> array(). +-spec resize(Array :: array(Type)) -> array(Type). resize(Array) -> resize(sparse_size(Array), Array). @@ -558,7 +571,7 @@ resize_test_() -> %% @see get/2 %% @see reset/2 --spec set(I :: array_indx(), Value :: term(), Array :: array()) -> array(). +-spec set(I :: array_indx(), Value :: Type, Array :: array(Type)) -> array(Type). set(I, Value, #array{size = N, max = M, default = D, elements = E}=A) when is_integer(I), I >= 0 -> @@ -621,7 +634,7 @@ expand(I, _S, X, D) -> %% @see set/3 --spec get(I :: array_indx(), Array :: array()) -> term(). +-spec get(I :: array_indx(), Array :: array(Type)) -> Value :: Type. get(I, #array{size = N, max = M, elements = E, default = D}) when is_integer(I), I >= 0 -> @@ -661,7 +674,7 @@ get_1(I, E, _D) -> %% TODO: a reset_range function --spec reset(I :: array_indx(), Array :: array()) -> array(). +-spec reset(I :: array_indx(), Array :: array(Type)) -> array(Type). reset(I, #array{size = N, max = M, default = D, elements = E}=A) when is_integer(I), I >= 0 -> @@ -747,7 +760,7 @@ set_get_test_() -> %% @see from_list/2 %% @see sparse_to_list/1 --spec to_list(Array :: array()) -> list(). +-spec to_list(Array :: array(Type)) -> list(Value :: Type). to_list(#array{size = 0}) -> []; @@ -820,7 +833,7 @@ to_list_test_() -> %% %% @see to_list/1 --spec sparse_to_list(Array :: array()) -> list(). +-spec sparse_to_list(Array :: array(Type)) -> list(Value :: Type). sparse_to_list(#array{size = 0}) -> []; @@ -887,7 +900,7 @@ sparse_to_list_test_() -> %% @equiv from_list(List, undefined) --spec from_list(List :: list()) -> array(). +-spec from_list(List :: list(Value :: Type)) -> array(Type). from_list(List) -> from_list(List, undefined). @@ -899,7 +912,7 @@ from_list(List) -> %% @see new/2 %% @see to_list/1 --spec from_list(List :: list(), Default :: term()) -> array(). +-spec from_list(List :: list(Value :: Type), Default :: term()) -> array(Type). from_list([], Default) -> new({default,Default}); @@ -998,7 +1011,7 @@ from_list_test_() -> %% @see from_orddict/2 %% @see sparse_to_orddict/1 --spec to_orddict(Array :: array()) -> indx_pairs(). +-spec to_orddict(Array :: array(Type)) -> indx_pairs(Value :: Type). to_orddict(#array{size = 0}) -> []; @@ -1035,16 +1048,16 @@ to_orddict_3(N, R, D, L, E, S) -> to_orddict_2(element(N, E), R, D, L), E, S). --spec push_pairs(non_neg_integer(), array_indx(), term(), indx_pairs()) -> - indx_pairs(). +-spec push_pairs(non_neg_integer(), array_indx(), term(), indx_pairs(Type)) -> + indx_pairs(Type). push_pairs(0, _I, _E, L) -> L; push_pairs(N, I, E, L) -> push_pairs(N-1, I-1, E, [{I, E} | L]). --spec push_tuple_pairs(non_neg_integer(), array_indx(), term(), indx_pairs()) -> - indx_pairs(). +-spec push_tuple_pairs(non_neg_integer(), array_indx(), term(), indx_pairs(Type)) -> + indx_pairs(Type). push_tuple_pairs(0, _I, _T, L) -> L; @@ -1090,7 +1103,7 @@ to_orddict_test_() -> %% %% @see to_orddict/1 --spec sparse_to_orddict(Array :: array()) -> indx_pairs(). +-spec sparse_to_orddict(Array :: array(Type)) -> indx_pairs(Value :: Type). sparse_to_orddict(#array{size = 0}) -> []; @@ -1128,7 +1141,7 @@ sparse_to_orddict_3(N, R, D, L, E, S) -> E, S). -spec sparse_push_tuple_pairs(non_neg_integer(), array_indx(), - _, _, indx_pairs()) -> indx_pairs(). + _, _, indx_pairs(Type)) -> indx_pairs(Type). sparse_push_tuple_pairs(0, _I, _D, _T, L) -> L; @@ -1170,7 +1183,7 @@ sparse_to_orddict_test_() -> %% @equiv from_orddict(Orddict, undefined) --spec from_orddict(Orddict :: indx_pairs()) -> array(). +-spec from_orddict(Orddict :: indx_pairs(Value :: Type)) -> array(Type). from_orddict(Orddict) -> from_orddict(Orddict, undefined). @@ -1184,7 +1197,8 @@ from_orddict(Orddict) -> %% @see new/2 %% @see to_orddict/1 --spec from_orddict(Orddict :: indx_pairs(), Default :: term()) -> array(). +-spec from_orddict(Orddict :: indx_pairs(Value :: Type), Default :: Type) -> + array(Type). from_orddict([], Default) -> new({default,Default}); @@ -1379,8 +1393,8 @@ from_orddict_test_() -> %% @see foldr/3 %% @see sparse_map/2 --spec map(Function, Array :: array()) -> array() when - Function :: fun((Index :: array_indx(), Value :: _) -> _). +-spec map(Function, Array :: array(Type1)) -> array(Type2) when + Function :: fun((Index :: array_indx(), Type1) -> Type2). map(Function, Array=#array{size = N, elements = E, default = D}) when is_function(Function, 2) -> @@ -1471,8 +1485,8 @@ map_test_() -> %% %% @see map/2 --spec sparse_map(Function, Array :: array()) -> array() when - Function :: fun((Index :: array_indx(), Value :: _) -> _). +-spec sparse_map(Function, Array :: array(Type1)) -> array(Type2) when + Function :: fun((Index :: array_indx(), Type1) -> Type2). sparse_map(Function, Array=#array{size = N, elements = E, default = D}) when is_function(Function, 2) -> @@ -1567,8 +1581,8 @@ sparse_map_test_() -> %% @see map/2 %% @see sparse_foldl/3 --spec foldl(Function, InitialAcc :: A, Array :: array()) -> B when - Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B). +-spec foldl(Function, InitialAcc :: A, Array :: array(Type)) -> B when + Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B). foldl(Function, A, #array{size = N, elements = E, default = D}) when is_function(Function, 3) -> @@ -1640,8 +1654,8 @@ foldl_test_() -> %% @see foldl/3 %% @see sparse_foldr/3 --spec sparse_foldl(Function, InitialAcc :: A, Array :: array()) -> B when - Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B). +-spec sparse_foldl(Function, InitialAcc :: A, Array :: array(Type)) -> B when + Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B). sparse_foldl(Function, A, #array{size = N, elements = E, default = D}) when is_function(Function, 3) -> @@ -1717,8 +1731,8 @@ sparse_foldl_test_() -> %% @see foldl/3 %% @see map/2 --spec foldr(Function, InitialAcc :: A, Array :: array()) -> B when - Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B). +-spec foldr(Function, InitialAcc :: A, Array :: array(Type)) -> B when + Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B). foldr(Function, A, #array{size = N, elements = E, default = D}) when is_function(Function, 3) -> @@ -1796,8 +1810,8 @@ foldr_test_() -> %% @see foldr/3 %% @see sparse_foldl/3 --spec sparse_foldr(Function, InitialAcc :: A, Array :: array()) -> B when - Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B). +-spec sparse_foldr(Function, InitialAcc :: A, Array :: array(Type)) -> B when + Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B). sparse_foldr(Function, A, #array{size = N, elements = E, default = D}) when is_function(Function, 3) -> diff --git a/lib/stdlib/src/dict.erl b/lib/stdlib/src/dict.erl index 7e198a2469..6088e1a2dd 100644 --- a/lib/stdlib/src/dict.erl +++ b/lib/stdlib/src/dict.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2013. All Rights Reserved. +%% Copyright Ericsson AB 2000-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 @@ -41,6 +41,8 @@ -export([store/3,append/3,append_list/3,update/3,update/4,update_counter/3]). -export([fold/3,map/2,filter/2,merge/3]). +-export_type([dict/0, dict/2]). + %% Low-level interface. %%-export([get_slot/2,get_bucket/2,on_bucket/3,fold_dict/3, %% maybe_expand/2,maybe_contract/2]). @@ -53,6 +55,9 @@ -define(exp_size, (?seg_size * ?expand_load)). -define(con_size, (?seg_size * ?contract_load)). +-type segs(K, V) :: tuple() + | {K, V}. % dummy + %% Define a hashtable. The default values are the standard ones. -record(dict, {size=0 :: non_neg_integer(), % Number of elements @@ -62,14 +67,13 @@ exp_size=?exp_size :: non_neg_integer(), % Size to expand at con_size=?con_size :: non_neg_integer(), % Size to contract at empty :: tuple(), % Empty segment - segs :: tuple() % Segments + segs :: segs(_, _) % Segments }). -%% A declaration equivalent to the following one is hard-coded in erl_types. -%% That declaration contains hard-coded information about the #dict{} -%% structure and the types of its fields. So, please make sure that any -%% changes to its structure are also propagated to erl_types.erl. -%% -%% -opaque dict() :: #dict{}. + + +-opaque dict() :: dict(_, _). + +-opaque dict(Key, Value) :: #dict{segs :: segs(Key, Value)}. -define(kv(K,V), [K|V]). % Key-Value pair format %%-define(kv(K,V), {K,V}). % Key-Value pair format @@ -81,8 +85,7 @@ new() -> #dict{empty=Empty,segs={Empty}}. -spec is_key(Key, Dict) -> boolean() when - Key :: term(), - Dict :: dict(). + Dict :: dict(Key, Value :: term()). is_key(Key, D) -> Slot = get_slot(D, Key), @@ -94,15 +97,15 @@ find_key(K, [_|Bkt]) -> find_key(K, Bkt); find_key(_, []) -> false. -spec to_list(Dict) -> List when - Dict :: dict(), - List :: [{Key :: term(), Value :: term()}]. + Dict :: dict(Key, Value), + List :: [{Key, Value}]. to_list(D) -> fold(fun (Key, Val, List) -> [{Key,Val}|List] end, [], D). -spec from_list(List) -> Dict when - List :: [{Key :: term(), Value :: term()}], - Dict :: dict(). + Dict :: dict(Key, Value), + List :: [{Key, Value}]. from_list(L) -> lists:foldl(fun ({K,V}, D) -> store(K, V, D) end, new(), L). @@ -118,9 +121,7 @@ size(#dict{size=N}) when is_integer(N), N >= 0 -> N. is_empty(#dict{size=N}) -> N =:= 0. -spec fetch(Key, Dict) -> Value when - Key :: term(), - Dict :: dict(), - Value :: term(). + Dict :: dict(Key, Value). fetch(Key, D) -> Slot = get_slot(D, Key), @@ -135,9 +136,7 @@ fetch_val(K, [_|Bkt]) -> fetch_val(K, Bkt); fetch_val(_, []) -> throw(badarg). -spec find(Key, Dict) -> {'ok', Value} | 'error' when - Key :: term(), - Dict :: dict(), - Value :: term(). + Dict :: dict(Key, Value). find(Key, D) -> Slot = get_slot(D, Key), @@ -149,16 +148,16 @@ find_val(K, [_|Bkt]) -> find_val(K, Bkt); find_val(_, []) -> error. -spec fetch_keys(Dict) -> Keys when - Dict :: dict(), - Keys :: [term()]. + Dict :: dict(Key, Value :: term()), + Keys :: [Key]. fetch_keys(D) -> fold(fun (Key, _Val, Keys) -> [Key|Keys] end, [], D). -spec erase(Key, Dict1) -> Dict2 when - Key :: term(), - Dict1 :: dict(), - Dict2 :: dict(). + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value). + %% Erase all elements with key Key. erase(Key, D0) -> @@ -174,10 +173,8 @@ erase_key(Key, [E|Bkt0]) -> erase_key(_, []) -> {[],0}. -spec store(Key, Value, Dict1) -> Dict2 when - Key :: term(), - Value :: term(), - Dict1 :: dict(), - Dict2 :: dict(). + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value). store(Key, Val, D0) -> Slot = get_slot(D0, Key), @@ -194,10 +191,8 @@ store_bkt_val(Key, New, [Other|Bkt0]) -> store_bkt_val(Key, New, []) -> {[?kv(Key,New)],1}. -spec append(Key, Value, Dict1) -> Dict2 when - Key :: term(), - Value :: term(), - Dict1 :: dict(), - Dict2 :: dict(). + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value). append(Key, Val, D0) -> Slot = get_slot(D0, Key), @@ -214,10 +209,9 @@ append_bkt(Key, Val, [Other|Bkt0]) -> append_bkt(Key, Val, []) -> {[?kv(Key,[Val])],1}. -spec append_list(Key, ValList, Dict1) -> Dict2 when - Key :: term(), - ValList :: [Value :: term()], - Dict1 :: dict(), - Dict2 :: dict(). + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value), + ValList :: [Value]. append_list(Key, L, D0) -> Slot = get_slot(D0, Key), @@ -288,10 +282,9 @@ app_list_bkt(Key, L, []) -> {[?kv(Key,L)],1}. %% {[Other|Bkt1],Dc}. -spec update(Key, Fun, Dict1) -> Dict2 when - Key :: term(), - Fun :: fun((Value1 :: term()) -> Value2 :: term()), - Dict1 :: dict(), - Dict2 :: dict(). + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value), + Fun :: fun((Value1 :: Value) -> Value2 :: Value). update(Key, F, D0) -> Slot = get_slot(D0, Key), @@ -311,11 +304,10 @@ update_bkt(_Key, _F, []) -> throw(badarg). -spec update(Key, Fun, Initial, Dict1) -> Dict2 when - Key :: term(), - Initial :: term(), - Fun :: fun((Value1 :: term()) -> Value2 :: term()), - Dict1 :: dict(), - Dict2 :: dict(). + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value), + Fun :: fun((Value1 :: Value) -> Value2 :: Value), + Initial :: Value. update(Key, F, Init, D0) -> Slot = get_slot(D0, Key), @@ -331,10 +323,9 @@ update_bkt(Key, F, I, [Other|Bkt0]) -> update_bkt(Key, F, I, []) when is_function(F, 1) -> {[?kv(Key,I)],1}. -spec update_counter(Key, Increment, Dict1) -> Dict2 when - Key :: term(), - Increment :: number(), - Dict1 :: dict(), - Dict2 :: dict(). + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value), + Increment :: number(). update_counter(Key, Incr, D0) when is_number(Incr) -> Slot = get_slot(D0, Key), @@ -351,36 +342,35 @@ counter_bkt(Key, I, []) -> {[?kv(Key,I)],1}. -spec fold(Fun, Acc0, Dict) -> Acc1 when Fun :: fun((Key, Value, AccIn) -> AccOut), - Key :: term(), - Value :: term(), - Acc0 :: term(), - Acc1 :: term(), - AccIn :: term(), - AccOut :: term(), - Dict :: dict(). + Dict :: dict(Key, Value), + Acc0 :: Acc, + Acc1 :: Acc, + AccIn :: Acc, + AccOut :: Acc. + %% Fold function Fun over all "bags" in Table and return Accumulator. fold(F, Acc, D) -> fold_dict(F, Acc, D). -spec map(Fun, Dict1) -> Dict2 when - Fun :: fun((Key :: term(), Value1 :: term()) -> Value2 :: term()), - Dict1 :: dict(), - Dict2 :: dict(). + Fun :: fun((Key, Value1) -> Value2), + Dict1 :: dict(Key, Value1), + Dict2 :: dict(Key, Value2). map(F, D) -> map_dict(F, D). -spec filter(Pred, Dict1) -> Dict2 when - Pred :: fun((Key :: term(), Value :: term()) -> boolean()), - Dict1 :: dict(), - Dict2 :: dict(). + Pred :: fun((Key , Value) -> boolean()), + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value). filter(F, D) -> filter_dict(F, D). -spec merge(Fun, Dict1, Dict2) -> Dict3 when - Fun :: fun((Key :: term(), Value1 :: term(), Value2 :: term()) -> Value :: term()), - Dict1 :: dict(), - Dict2 :: dict(), - Dict3 :: dict(). + Fun :: fun((Key, Value1, Value2) -> Value), + Dict1 :: dict(Key, Value1), + Dict2 :: dict(Key, Value2), + Dict3 :: dict(Key, Value). merge(F, D1, D2) when D1#dict.size < D2#dict.size -> fold_dict(fun (K, V1, D) -> diff --git a/lib/stdlib/src/digraph.erl b/lib/stdlib/src/digraph.erl index 78f74631dc..0c21271529 100644 --- a/lib/stdlib/src/digraph.erl +++ b/lib/stdlib/src/digraph.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-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 @@ -36,18 +36,14 @@ -export([get_short_path/3, get_short_cycle/2]). --export_type([digraph/0, d_type/0, vertex/0, edge/0]). +-export_type([graph/0, d_type/0, vertex/0, edge/0]). -record(digraph, {vtab = notable :: ets:tab(), etab = notable :: ets:tab(), ntab = notable :: ets:tab(), cyclic = true :: boolean()}). -%% A declaration equivalent to the following one is hard-coded in erl_types. -%% That declaration contains hard-coded information about the #digraph{} -%% record and the types of its fields. So, please make sure that any -%% changes to its structure are also propagated to erl_types.erl. -%% -%% -opaque digraph() :: #digraph{}. + +-opaque graph() :: #digraph{}. -type edge() :: term(). -type label() :: term(). @@ -67,11 +63,11 @@ -type d_cyclicity() :: 'acyclic' | 'cyclic'. -type d_type() :: d_cyclicity() | d_protection(). --spec new() -> digraph(). +-spec new() -> graph(). new() -> new([]). --spec new(Type) -> digraph() when +-spec new(Type) -> graph() when Type :: [d_type()]. new(Type) -> @@ -106,7 +102,7 @@ check_type(_, _, _) -> error. %% %% Set graph type %% --spec set_type([{'cyclic', boolean()}], digraph()) -> digraph(). +-spec set_type([{'cyclic', boolean()}], graph()) -> graph(). set_type([{cyclic,V} | Ks], G) -> set_type(Ks, G#digraph{cyclic = V}); @@ -116,7 +112,7 @@ set_type([], G) -> G. %% Data access functions -spec delete(G) -> 'true' when - G :: digraph(). + G :: graph(). delete(G) -> ets:delete(G#digraph.vtab), @@ -124,7 +120,7 @@ delete(G) -> ets:delete(G#digraph.ntab). -spec info(G) -> InfoList when - G :: digraph(), + G :: graph(), InfoList :: [{'cyclicity', Cyclicity :: d_cyclicity()} | {'memory', NoWords :: non_neg_integer()} | {'protection', Protection :: d_protection()}]. @@ -142,20 +138,20 @@ info(G) -> [{cyclicity, Cyclicity}, {memory, Memory}, {protection, Protection}]. -spec add_vertex(G) -> vertex() when - G :: digraph(). + G :: graph(). add_vertex(G) -> do_add_vertex({new_vertex_id(G), []}, G). -spec add_vertex(G, V) -> vertex() when - G :: digraph(), + G :: graph(), V :: vertex(). add_vertex(G, V) -> do_add_vertex({V, []}, G). -spec add_vertex(G, V, Label) -> vertex() when - G :: digraph(), + G :: graph(), V :: vertex(), Label :: label(). @@ -163,21 +159,21 @@ add_vertex(G, V, D) -> do_add_vertex({V, D}, G). -spec del_vertex(G, V) -> 'true' when - G :: digraph(), + G :: graph(), V :: vertex(). del_vertex(G, V) -> do_del_vertex(V, G). -spec del_vertices(G, Vertices) -> 'true' when - G :: digraph(), + G :: graph(), Vertices :: [vertex()]. del_vertices(G, Vs) -> do_del_vertices(Vs, G). -spec vertex(G, V) -> {V, Label} | 'false' when - G :: digraph(), + G :: graph(), V :: vertex(), Label :: label(). @@ -188,37 +184,37 @@ vertex(G, V) -> end. -spec no_vertices(G) -> non_neg_integer() when - G :: digraph(). + G :: graph(). no_vertices(G) -> ets:info(G#digraph.vtab, size). -spec vertices(G) -> Vertices when - G :: digraph(), + G :: graph(), Vertices :: [vertex()]. vertices(G) -> ets:select(G#digraph.vtab, [{{'$1', '_'}, [], ['$1']}]). --spec source_vertices(digraph()) -> [vertex()]. +-spec source_vertices(graph()) -> [vertex()]. source_vertices(G) -> collect_vertices(G, in). --spec sink_vertices(digraph()) -> [vertex()]. +-spec sink_vertices(graph()) -> [vertex()]. sink_vertices(G) -> collect_vertices(G, out). -spec in_degree(G, V) -> non_neg_integer() when - G :: digraph(), + G :: graph(), V :: vertex(). in_degree(G, V) -> length(ets:lookup(G#digraph.ntab, {in, V})). -spec in_neighbours(G, V) -> Vertex when - G :: digraph(), + G :: graph(), V :: vertex(), Vertex :: [vertex()]. @@ -228,7 +224,7 @@ in_neighbours(G, V) -> collect_elems(ets:lookup(NT, {in, V}), ET, 2). -spec in_edges(G, V) -> Edges when - G :: digraph(), + G :: graph(), V :: vertex(), Edges :: [edge()]. @@ -236,14 +232,14 @@ in_edges(G, V) -> ets:select(G#digraph.ntab, [{{{in, V}, '$1'}, [], ['$1']}]). -spec out_degree(G, V) -> non_neg_integer() when - G :: digraph(), + G :: graph(), V :: vertex(). out_degree(G, V) -> length(ets:lookup(G#digraph.ntab, {out, V})). -spec out_neighbours(G, V) -> Vertices when - G :: digraph(), + G :: graph(), V :: vertex(), Vertices :: [vertex()]. @@ -253,7 +249,7 @@ out_neighbours(G, V) -> collect_elems(ets:lookup(NT, {out, V}), ET, 3). -spec out_edges(G, V) -> Edges when - G :: digraph(), + G :: graph(), V :: vertex(), Edges :: [edge()]. @@ -261,7 +257,7 @@ out_edges(G, V) -> ets:select(G#digraph.ntab, [{{{out, V}, '$1'}, [], ['$1']}]). -spec add_edge(G, V1, V2) -> edge() | {'error', add_edge_err_rsn()} when - G :: digraph(), + G :: graph(), V1 :: vertex(), V2 :: vertex(). @@ -269,7 +265,7 @@ add_edge(G, V1, V2) -> do_add_edge({new_edge_id(G), V1, V2, []}, G). -spec add_edge(G, V1, V2, Label) -> edge() | {'error', add_edge_err_rsn()} when - G :: digraph(), + G :: graph(), V1 :: vertex(), V2 :: vertex(), Label :: label(). @@ -278,7 +274,7 @@ add_edge(G, V1, V2, D) -> do_add_edge({new_edge_id(G), V1, V2, D}, G). -spec add_edge(G, E, V1, V2, Label) -> edge() | {'error', add_edge_err_rsn()} when - G :: digraph(), + G :: graph(), E :: edge(), V1 :: vertex(), V2 :: vertex(), @@ -288,34 +284,34 @@ add_edge(G, E, V1, V2, D) -> do_add_edge({E, V1, V2, D}, G). -spec del_edge(G, E) -> 'true' when - G :: digraph(), + G :: graph(), E :: edge(). del_edge(G, E) -> do_del_edges([E], G). -spec del_edges(G, Edges) -> 'true' when - G :: digraph(), + G :: graph(), Edges :: [edge()]. del_edges(G, Es) -> do_del_edges(Es, G). -spec no_edges(G) -> non_neg_integer() when - G :: digraph(). + G :: graph(). no_edges(G) -> ets:info(G#digraph.etab, size). -spec edges(G) -> Edges when - G :: digraph(), + G :: graph(), Edges :: [edge()]. edges(G) -> ets:select(G#digraph.etab, [{{'$1', '_', '_', '_'}, [], ['$1']}]). -spec edges(G, V) -> Edges when - G :: digraph(), + G :: graph(), V :: vertex(), Edges :: [edge()]. @@ -324,7 +320,7 @@ edges(G, V) -> {{{in, V}, '$1'}, [], ['$1']}]). -spec edge(G, E) -> {E, V1, V2, Label} | 'false' when - G :: digraph(), + G :: graph(), E :: edge(), V1 :: vertex(), V2 :: vertex(), @@ -339,7 +335,7 @@ edge(G, E) -> %% %% Generate a "unique" edge identifier (relative to this graph) %% --spec new_edge_id(digraph()) -> edge(). +-spec new_edge_id(graph()) -> edge(). new_edge_id(G) -> NT = G#digraph.ntab, @@ -351,7 +347,7 @@ new_edge_id(G) -> %% %% Generate a "unique" vertex identifier (relative to this graph) %% --spec new_vertex_id(digraph()) -> vertex(). +-spec new_vertex_id(graph()) -> vertex(). new_vertex_id(G) -> NT = G#digraph.ntab, @@ -371,7 +367,7 @@ collect_elems([{_,Key}|Keys], Table, Index, Acc) -> [ets:lookup_element(Table, Key, Index)|Acc]); collect_elems([], _, _, Acc) -> Acc. --spec do_add_vertex({vertex(), label()}, digraph()) -> vertex(). +-spec do_add_vertex({vertex(), label()}, graph()) -> vertex(). do_add_vertex({V, _Label} = VL, G) -> ets:insert(G#digraph.vtab, VL), @@ -430,14 +426,14 @@ do_del_edge(E, V1, V2, G) -> {{{out,V1}, E}, [], [true]}]), ets:delete(G#digraph.etab, E). --spec rm_edges([vertex(),...], digraph()) -> 'true'. +-spec rm_edges([vertex(),...], graph()) -> 'true'. rm_edges([V1, V2|Vs], G) -> rm_edge(V1, V2, G), rm_edges([V2|Vs], G); rm_edges(_, _) -> true. --spec rm_edge(vertex(), vertex(), digraph()) -> 'ok'. +-spec rm_edge(vertex(), vertex(), graph()) -> 'ok'. rm_edge(V1, V2, G) -> Es = out_edges(G, V1), @@ -456,7 +452,7 @@ rm_edge_0([], _, _, #digraph{}) -> ok. %% %% Check that endpoints exist %% --spec do_add_edge({edge(), vertex(), vertex(), label()}, digraph()) -> +-spec do_add_edge({edge(), vertex(), vertex(), label()}, graph()) -> edge() | {'error', add_edge_err_rsn()}. do_add_edge({E, V1, V2, Label}, G) -> @@ -484,14 +480,14 @@ other_edge_exists(#digraph{etab = ET}, E, V1, V2) -> false end. --spec do_insert_edge(edge(), vertex(), vertex(), label(), digraph()) -> edge(). +-spec do_insert_edge(edge(), vertex(), vertex(), label(), graph()) -> edge(). do_insert_edge(E, V1, V2, Label, #digraph{ntab=NT, etab=ET}) -> ets:insert(NT, [{{out, V1}, E}, {{in, V2}, E}]), ets:insert(ET, {E, V1, V2, Label}), E. --spec acyclic_add_edge(edge(), vertex(), vertex(), label(), digraph()) -> +-spec acyclic_add_edge(edge(), vertex(), vertex(), label(), graph()) -> edge() | {'error', {'bad_edge', [vertex()]}}. acyclic_add_edge(_E, V1, V2, _L, _G) when V1 =:= V2 -> @@ -507,7 +503,7 @@ acyclic_add_edge(E, V1, V2, Label, G) -> %% -spec del_path(G, V1, V2) -> 'true' when - G :: digraph(), + G :: graph(), V1 :: vertex(), V2 :: vertex(). @@ -529,7 +525,7 @@ del_path(G, V1, V2) -> %% -spec get_cycle(G, V) -> Vertices | 'false' when - G :: digraph(), + G :: graph(), V :: vertex(), Vertices :: [vertex(),...]. @@ -550,7 +546,7 @@ get_cycle(G, V) -> %% -spec get_path(G, V1, V2) -> Vertices | 'false' when - G :: digraph(), + G :: graph(), V1 :: vertex(), V2 :: vertex(), Vertices :: [vertex(),...]. @@ -589,7 +585,7 @@ one_path([], _, [], _, _, _, _, _Counter) -> false. %% -spec get_short_cycle(G, V) -> Vertices | 'false' when - G :: digraph(), + G :: graph(), V :: vertex(), Vertices :: [vertex(),...]. @@ -602,7 +598,7 @@ get_short_cycle(G, V) -> %% -spec get_short_path(G, V1, V2) -> Vertices | 'false' when - G :: digraph(), + G :: graph(), V1 :: vertex(), V2 :: vertex(), Vertices :: [vertex(),...]. diff --git a/lib/stdlib/src/digraph_utils.erl b/lib/stdlib/src/digraph_utils.erl index 0e248df453..011bcd0260 100644 --- a/lib/stdlib/src/digraph_utils.erl +++ b/lib/stdlib/src/digraph_utils.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% Copyright Ericsson AB 1999-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 @@ -43,28 +43,28 @@ %% -spec components(Digraph) -> [Component] when - Digraph :: digraph(), + Digraph :: digraph:graph(), Component :: [digraph:vertex()]. components(G) -> forest(G, fun inout/3). -spec strong_components(Digraph) -> [StrongComponent] when - Digraph :: digraph(), + Digraph :: digraph:graph(), StrongComponent :: [digraph:vertex()]. strong_components(G) -> forest(G, fun in/3, revpostorder(G)). -spec cyclic_strong_components(Digraph) -> [StrongComponent] when - Digraph :: digraph(), + Digraph :: digraph:graph(), StrongComponent :: [digraph:vertex()]. cyclic_strong_components(G) -> remove_singletons(strong_components(G), G, []). -spec reachable(Vertices, Digraph) -> Reachable when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()], Reachable :: [digraph:vertex()]. @@ -72,7 +72,7 @@ reachable(Vs, G) when is_list(Vs) -> lists:append(forest(G, fun out/3, Vs, first)). -spec reachable_neighbours(Vertices, Digraph) -> Reachable when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()], Reachable :: [digraph:vertex()]. @@ -80,7 +80,7 @@ reachable_neighbours(Vs, G) when is_list(Vs) -> lists:append(forest(G, fun out/3, Vs, not_first)). -spec reaching(Vertices, Digraph) -> Reaching when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()], Reaching :: [digraph:vertex()]. @@ -88,7 +88,7 @@ reaching(Vs, G) when is_list(Vs) -> lists:append(forest(G, fun in/3, Vs, first)). -spec reaching_neighbours(Vertices, Digraph) -> Reaching when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()], Reaching :: [digraph:vertex()]. @@ -96,7 +96,7 @@ reaching_neighbours(Vs, G) when is_list(Vs) -> lists:append(forest(G, fun in/3, Vs, not_first)). -spec topsort(Digraph) -> Vertices | 'false' when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()]. topsort(G) -> @@ -107,13 +107,13 @@ topsort(G) -> end. -spec is_acyclic(Digraph) -> boolean() when - Digraph :: digraph(). + Digraph :: digraph:graph(). is_acyclic(G) -> loop_vertices(G) =:= [] andalso topsort(G) =/= false. -spec arborescence_root(Digraph) -> 'no' | {'yes', Root} when - Digraph :: digraph(), + Digraph :: digraph:graph(), Root :: digraph:vertex(). arborescence_root(G) -> @@ -136,29 +136,29 @@ arborescence_root(G) -> end. -spec is_arborescence(Digraph) -> boolean() when - Digraph :: digraph(). + Digraph :: digraph:graph(). is_arborescence(G) -> arborescence_root(G) =/= no. -spec is_tree(Digraph) -> boolean() when - Digraph :: digraph(). + Digraph :: digraph:graph(). is_tree(G) -> (digraph:no_edges(G) =:= digraph:no_vertices(G) - 1) andalso (length(components(G)) =:= 1). -spec loop_vertices(Digraph) -> Vertices when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()]. loop_vertices(G) -> [V || V <- digraph:vertices(G), is_reflexive_vertex(V, G)]. -spec subgraph(Digraph, Vertices) -> SubGraph when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()], - SubGraph :: digraph(). + SubGraph :: digraph:graph(). subgraph(G, Vs) -> try @@ -169,8 +169,8 @@ subgraph(G, Vs) -> end. -spec subgraph(Digraph, Vertices, Options) -> SubGraph when - Digraph :: digraph(), - SubGraph :: digraph(), + Digraph :: digraph:graph(), + SubGraph :: digraph:graph(), Vertices :: [digraph:vertex()], Options :: [{'type', SubgraphType} | {'keep_labels', boolean()}], SubgraphType :: 'inherit' | [digraph:d_type()]. @@ -184,8 +184,8 @@ subgraph(G, Vs, Opts) -> end. -spec condensation(Digraph) -> CondensedDigraph when - Digraph :: digraph(), - CondensedDigraph :: digraph(). + Digraph :: digraph:graph(), + CondensedDigraph :: digraph:graph(). condensation(G) -> SCs = strong_components(G), @@ -209,14 +209,14 @@ condensation(G) -> SCG. -spec preorder(Digraph) -> Vertices when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()]. preorder(G) -> lists:reverse(revpreorder(G)). -spec postorder(Digraph) -> Vertices when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()]. postorder(G) -> diff --git a/lib/stdlib/src/edlin_expand.erl b/lib/stdlib/src/edlin_expand.erl index 516c0aa30b..a2b4663219 100644 --- a/lib/stdlib/src/edlin_expand.erl +++ b/lib/stdlib/src/edlin_expand.erl @@ -73,7 +73,7 @@ to_atom(Str) -> error end. -match(Prefix, Alts, Extra) -> +match(Prefix, Alts, Extra0) -> Len = length(Prefix), Matches = lists:sort( [{S, A} || {H, A} <- Alts, @@ -89,7 +89,11 @@ match(Prefix, Alts, Extra) -> {yes, Remain, []} end; {complete, Str} -> - {yes, nthtail(Len, Str) ++ Extra, []}; + Extra = case {Extra0,Matches} of + {"(",[{Str,0}]} -> "()"; + {_,_} -> Extra0 + end, + {yes, nthtail(Len, Str) ++ Extra, []}; no -> {no, [], []} end. diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index 4fd302e612..68e079b7e5 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-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 @@ -46,8 +46,8 @@ istk=[], %Ifdef stack sstk=[], %State stack path=[], %Include-path - macs = dict:new() :: dict(), %Macros (don't care locations) - uses = dict:new() :: dict(), %Macro use structure + macs = dict:new() :: dict:dict(),%Macros (don't care locations) + uses = dict:new() :: dict:dict(),%Macro use structure pre_opened = false :: boolean() }). @@ -640,7 +640,7 @@ leave_file(From, St) -> Ms = dict:store({atom,'FILE'}, {none,[{string,CurrLoc,OldName2}]}, St#epp.macs), - NextSt = OldSt#epp{sstk=Sts,macs=Ms}, + NextSt = OldSt#epp{sstk=Sts,macs=Ms,uses=St#epp.uses}, enter_file_reply(From, OldName, CurrLoc, CurrLoc), case OldName2 =:= OldName of true -> 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_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl index 4741bef6b9..f53c6e1278 100644 --- a/lib/stdlib/src/erl_expand_records.erl +++ b/lib/stdlib/src/erl_expand_records.erl @@ -135,9 +135,10 @@ pattern({tuple,Line,Ps}, St0) -> pattern({map,Line,Ps}, St0) -> {TPs,St1} = pattern_list(Ps, St0), {{map,Line,TPs},St1}; -pattern({map_field_exact,Line,Key,V0}, St0) -> - {V,St1} = pattern(V0, St0), - {{map_field_exact,Line,Key,V},St1}; +pattern({map_field_exact,Line,Key0,V0}, St0) -> + {Key,St1} = pattern(Key0, St0), + {V,St2} = pattern(V0, St1), + {{map_field_exact,Line,Key,V},St2}; %%pattern({struct,Line,Tag,Ps}, St0) -> %% {TPs,TPsvs,St1} = pattern_list(Ps, St0), %% {{struct,Line,Tag,TPs},TPsvs,St1}; @@ -310,9 +311,10 @@ expr({tuple,Line,Es0}, St0) -> expr({map,Line,Es0}, St0) -> {Es1,St1} = expr_list(Es0, St0), {{map,Line,Es1},St1}; -expr({map,Line,Var,Es0}, St0) -> - {Es1,St1} = expr_list(Es0, St0), - {{map,Line,Var,Es1},St1}; +expr({map,Line,Arg0,Es0}, St0) -> + {Arg1,St1} = expr(Arg0, St0), + {Es1,St2} = expr_list(Es0, St1), + {{map,Line,Arg1,Es1},St2}; expr({map_field_assoc,Line,K0,V0}, St0) -> {K,St1} = expr(K0, St0), {V,St2} = expr(V0, St1), diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index f630db6032..9f5be2da37 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-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 @@ -85,8 +85,8 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> -record(usage, { calls = dict:new(), %Who calls who imported = [], %Actually imported functions - used_records=sets:new() :: set(), %Used record definitions - used_types = dict:new() :: dict() %Used type definitions + used_records=sets:new() :: sets:set(),%Used record definitions + used_types = dict:new() :: dict:dict()%Used type definitions }). %% Define the lint state record. @@ -95,13 +95,13 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> -record(lint, {state=start :: 'start' | 'attribute' | 'function', module=[], %Module behaviour=[], %Behaviour - exports=gb_sets:empty() :: gb_set(), %Exports + exports=gb_sets:empty() :: gb_sets:set(),%Exports imports=[], %Imports compile=[], %Compile flags - records=dict:new() :: dict(), %Record definitions - locals=gb_sets:empty() :: gb_set(), %All defined functions (prescanned) - no_auto=gb_sets:empty() :: gb_set(), %Functions explicitly not autoimported - defined=gb_sets:empty() :: gb_set(), %Defined fuctions + records=dict:new() :: dict:dict(), %Record definitions + locals=gb_sets:empty() :: gb_sets:set(),%All defined functions (prescanned) + no_auto=gb_sets:empty() :: gb_sets:set() | 'all',%Functions explicitly not autoimported + defined=gb_sets:empty() :: gb_sets:set(),%Defined fuctions on_load=[] :: [fa()], %On-load function on_load_line=0 :: line(), %Line for on_load clashes=[], %Exported functions named as BIFs @@ -118,10 +118,10 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> new = false :: boolean(), %Has user-defined 'new/N' called= [] :: [{fa(),line()}], %Called functions usage = #usage{} :: #usage{}, - specs = dict:new() :: dict(), %Type specifications - callbacks = dict:new() :: dict(), %Callback types - types = dict:new() :: dict(), %Type definitions - exp_types=gb_sets:empty():: gb_set() %Exported types + specs = dict:new() :: dict:dict(), %Type specifications + callbacks = dict:new() :: dict:dict(), %Callback types + types = dict:new() :: dict:dict(), %Type definitions + exp_types=gb_sets:empty():: gb_sets:set()%Exported types }). -type lint_state() :: #lint{}. @@ -344,9 +344,10 @@ format_error(spec_wrong_arity) -> "spec has the wrong arity"; format_error(callback_wrong_arity) -> "callback has the wrong arity"; -format_error({imported_predefined_type, Name}) -> - io_lib:format("referring to built-in type ~w as a remote type; " - "please take out the module name", [Name]); +format_error({deprecated_type, {Name, Arity}, {Mod, NewName}, Rel}) -> + io_lib:format("type ~w/~w is deprecated and will be " + "removed in ~s; use ~w:~w/~w", + [Name, Arity, Rel, Mod, NewName, Arity]); format_error({not_exported_opaque, {TypeName, Arity}}) -> io_lib:format("opaque type ~w~s is not exported", [TypeName, gen_type_paren(Arity)]); @@ -1155,7 +1156,7 @@ export_type(Line, ETs, #lint{usage = Usage, exp_types = ETs0} = St0) -> add_error(Line, {bad_export_type, ETs}, St0) end. --spec exports(lint_state()) -> gb_set(). +-spec exports(lint_state()) -> gb_sets:set(). exports(#lint{compile = Opts, defined = Defs, exports = Es}) -> case lists:member(export_all, Opts) of @@ -1888,7 +1889,7 @@ is_guard_test(Expression, Forms) -> end, start(), RecordAttributes), is_guard_test2(zip_file_and_line(Expression, "nofile"), St0#lint.records). -%% is_guard_test2(Expression, RecordDefs :: dict()) -> boolean(). +%% is_guard_test2(Expression, RecordDefs :: dict:dict()) -> boolean(). is_guard_test2({call,Line,{atom,Lr,record},[E,A]}, RDs) -> is_gexpr({call,Line,{atom,Lr,is_record},[E,A]}, RDs); is_guard_test2({call,_Line,{atom,_La,Test},As}=Call, RDs) -> @@ -2566,18 +2567,12 @@ check_type({paren_type, _L, [Type]}, SeenVars, St) -> check_type(Type, SeenVars, St); check_type({remote_type, L, [{atom, _, Mod}, {atom, _, Name}, Args]}, SeenVars, #lint{module=CurrentMod} = St) -> - St1 = - case is_default_type({Name, length(Args)}) - orelse is_var_arity_type(Name) of - true -> add_error(L, {imported_predefined_type, Name}, St); - false -> St - end, case Mod =:= CurrentMod of - true -> check_type({type, L, Name, Args}, SeenVars, St1); + true -> check_type({type, L, Name, Args}, SeenVars, St); false -> lists:foldl(fun(T, {AccSeenVars, AccSt}) -> check_type(T, AccSeenVars, AccSt) - end, {SeenVars, St1}, Args) + end, {SeenVars, St}, Args) end; check_type({integer, _L, _}, SeenVars, St) -> {SeenVars, St}; check_type({atom, _L, _}, SeenVars, St) -> {SeenVars, St}; @@ -2635,14 +2630,33 @@ check_type({type, _L, product, Args}, SeenVars, St) -> lists:foldl(fun(T, {AccSeenVars, AccSt}) -> check_type(T, AccSeenVars, AccSt) end, {SeenVars, St}, Args); -check_type({type, La, TypeName, Args}, SeenVars, #lint{usage=Usage} = St) -> +check_type({type, La, TypeName, Args}, SeenVars, St) -> + #lint{usage=Usage, module = Module, types=Types} = St, Arity = length(Args), + TypePair = {TypeName, Arity}, St1 = case is_var_arity_type(TypeName) of true -> St; false -> - OldUsed = Usage#usage.used_types, - UsedTypes = dict:store({TypeName, Arity}, La, OldUsed), - St#lint{usage=Usage#usage{used_types=UsedTypes}} + Obsolete = obsolete_type(TypePair), + IsObsolete = + case Obsolete of + {deprecated, {M, _}, _} when M =/= Module -> + case dict:find(TypePair, Types) of + {ok, _} -> false; + error -> true + end; + _ -> false + end, + case IsObsolete of + true -> + {deprecated, Replacement, Rel} = Obsolete, + W = {deprecated_type, TypePair, Replacement, Rel}, + add_warning(La, W, St); + false -> + OldUsed = Usage#usage.used_types, + UsedTypes = dict:store(TypePair, La, OldUsed), + St#lint{usage=Usage#usage{used_types=UsedTypes}} + end end, check_type({type, -1, product, Args}, SeenVars, St1); check_type(I, SeenVars, St) -> @@ -2765,6 +2779,17 @@ is_newly_introduced_builtin_type({set, 0}) -> true; % opaque is_newly_introduced_builtin_type({boolean, 0}) -> true; is_newly_introduced_builtin_type({Name, _}) when is_atom(Name) -> false. +%% Obsolete in OTP 17.0. +obsolete_type({array, 0}) -> {deprecated, {array, array}, "OTP 18.0"}; +obsolete_type({dict, 0}) -> {deprecated, {dict, dict}, "OTP 18.0"}; +obsolete_type({digraph, 0}) -> {deprecated, {digraph, graph}, "OTP 18.0"}; +obsolete_type({gb_set, 0}) -> {deprecated, {gb_sets, set}, "OTP 18.0"}; +obsolete_type({gb_tree, 0}) -> {deprecated, {gb_trees, tree}, "OTP 18.0"}; +obsolete_type({queue, 0}) -> {deprecated, {queue, queue}, "OTP 18.0"}; +obsolete_type({set, 0}) -> {deprecated, {sets, set}, "OTP 18.0"}; +obsolete_type({tid, 0}) -> {deprecated, {ets, tid}, "OTP 18.0"}; +obsolete_type({Name, _}) when is_atom(Name) -> no. + %% spec_decl(Line, Fun, Types, State) -> State. spec_decl(Line, MFA0, TypeSpecs, St0 = #lint{specs = Specs, module = Mod}) -> @@ -3648,15 +3673,22 @@ is_imported_from_erlang(ImportSet,{Func,Arity}) -> {ok,erlang} -> true; _ -> false end. -%% Build set of functions where auto-import is explicitly supressed +%% Build set of functions where auto-import is explicitly suppressed auto_import_suppressed(CompileFlags) -> - L0 = [ X || {no_auto_import,X} <- CompileFlags ], - L1 = [ {Y,Z} || {Y,Z} <- lists:flatten(L0), is_atom(Y), is_integer(Z) ], - gb_sets:from_list(L1). -%% Predicate to find out if autoimport is explicitly supressed for a function + case lists:member(no_auto_import, CompileFlags) of + true -> + all; + false -> + L0 = [ X || {no_auto_import,X} <- CompileFlags ], + L1 = [ {Y,Z} || {Y,Z} <- lists:flatten(L0), is_atom(Y), is_integer(Z) ], + gb_sets:from_list(L1) + end. +%% Predicate to find out if autoimport is explicitly suppressed for a function +is_autoimport_suppressed(all,{_Func,_Arity}) -> + true; is_autoimport_suppressed(NoAutoSet,{Func,Arity}) -> gb_sets:is_element({Func,Arity},NoAutoSet). -%% Predicate to find out if a function specific bif-clash supression (old deprecated) is present +%% Predicate to find out if a function specific bif-clash suppression (old deprecated) is present bif_clash_specifically_disabled(St,{F,A}) -> Nowarn = nowarn_function(nowarn_bif_clash, St#lint.compile), lists:member({F,A},Nowarn). 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/ets.erl b/lib/stdlib/src/ets.erl index cc5e69f574..42b11a97e2 100644 --- a/lib/stdlib/src/ets.erl +++ b/lib/stdlib/src/ets.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-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 @@ -53,10 +53,8 @@ | {tab(),integer(),integer(),binary(),list(),integer()} | {tab(),_,_,integer(),binary(),list(),integer(),integer()}. -%% a similar definition is also in erl_types -opaque tid() :: integer(). -%% these ones are also defined in erl_bif_types -type match_pattern() :: atom() | tuple(). -type match_spec() :: [{match_pattern(), [_], [_]}]. diff --git a/lib/stdlib/src/gb_sets.erl b/lib/stdlib/src/gb_sets.erl index 237317ac94..0a26d0182d 100644 --- a/lib/stdlib/src/gb_sets.erl +++ b/lib/stdlib/src/gb_sets.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2013. All Rights Reserved. +%% Copyright Ericsson AB 2001-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 @@ -196,31 +196,32 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Some types. --export_type([iter/0]). +-export_type([set/0, set/1, iter/0, iter/1]). --type gb_set_node() :: 'nil' | {term(), _, _}. +-type gb_set_node(Element) :: 'nil' | {Element, _, _}. +-type gb_set_node() :: gb_set_node(_). +-opaque set(Element) :: {non_neg_integer(), gb_set_node(Element)}. +-opaque set() :: set(_). +-opaque iter(Element) :: [gb_set_node(Element)]. -opaque iter() :: [gb_set_node()]. -%% A declaration equivalent to the following is currently hard-coded -%% in erl_types.erl -%% -%% -opaque gb_set() :: {non_neg_integer(), gb_set_node()}. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% gb_sets:set() in OTP 17 only. + -spec empty() -> Set when - Set :: gb_set(). + Set :: gb_sets:set(). empty() -> {0, nil}. -spec new() -> Set when - Set :: gb_set(). + Set :: gb_sets:set(). new() -> empty(). -spec is_empty(Set) -> boolean() when - Set :: gb_set(). + Set :: gb_sets:set(). is_empty({0, nil}) -> true; @@ -228,27 +229,24 @@ is_empty(_) -> false. -spec size(Set) -> non_neg_integer() when - Set :: gb_set(). + Set :: gb_sets:set(). size({Size, _}) -> Size. --spec singleton(Element) -> gb_set() when - Element :: term(). +-spec singleton(Element) -> set(Element). singleton(Key) -> {1, {Key, nil, nil}}. -spec is_element(Element, Set) -> boolean() when - Element :: term(), - Set :: gb_set(). + Set :: set(Element). is_element(Key, S) -> is_member(Key, S). -spec is_member(Element, Set) -> boolean() when - Element :: term(), - Set :: gb_set(). + Set :: set(Element). is_member(Key, {_, T}) -> is_member_1(Key, T). @@ -263,9 +261,8 @@ is_member_1(_, nil) -> false. -spec insert(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). insert(Key, {S, T}) -> S1 = S + 1, @@ -322,8 +319,8 @@ count(nil) -> {1, 0}. -spec balance(Set1) -> Set2 when - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). balance({S, T}) -> {S, balance(T, S)}. @@ -349,17 +346,15 @@ balance_list_1(L, 0) -> {nil, L}. -spec add_element(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). add_element(X, S) -> add(X, S). -spec add(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). add(X, S) -> case is_member(X, S) of @@ -370,32 +365,30 @@ add(X, S) -> end. -spec from_list(List) -> Set when - List :: [term()], - Set :: gb_set(). + List :: [Element], + Set :: set(Element). from_list(L) -> from_ordset(ordsets:from_list(L)). -spec from_ordset(List) -> Set when - List :: [term()], - Set :: gb_set(). + List :: [Element], + Set :: set(Element). from_ordset(L) -> S = length(L), {S, balance_list(L, S)}. -spec del_element(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). del_element(Key, S) -> delete_any(Key, S). -spec delete_any(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). delete_any(Key, S) -> case is_member(Key, S) of @@ -406,9 +399,8 @@ delete_any(Key, S) -> end. -spec delete(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). delete(Key, {S, T}) -> {S - 1, delete_1(Key, T)}. @@ -431,9 +423,8 @@ merge(Smaller, Larger) -> {Key, Smaller, Larger1}. -spec take_smallest(Set1) -> {Element, Set2} when - Set1 :: gb_set(), - Set2 :: gb_set(), - Element :: term(). + Set1 :: set(Element), + Set2 :: set(Element). take_smallest({S, T}) -> {Key, Larger} = take_smallest1(T), @@ -445,8 +436,8 @@ take_smallest1({Key, Smaller, Larger}) -> {Key1, Smaller1} = take_smallest1(Smaller), {Key1, {Key, Smaller1, Larger}}. --spec smallest(Set) -> term() when - Set :: gb_set(). +-spec smallest(Set) -> Element when + Set :: set(Element). smallest({_, T}) -> smallest_1(T). @@ -457,9 +448,8 @@ smallest_1({_Key, Smaller, _Larger}) -> smallest_1(Smaller). -spec take_largest(Set1) -> {Element, Set2} when - Set1 :: gb_set(), - Set2 :: gb_set(), - Element :: term(). + Set1 :: set(Element), + Set2 :: set(Element). take_largest({S, T}) -> {Key, Smaller} = take_largest1(T), @@ -471,8 +461,8 @@ take_largest1({Key, Smaller, Larger}) -> {Key1, Larger1} = take_largest1(Larger), {Key1, {Key, Smaller, Larger1}}. --spec largest(Set) -> term() when - Set :: gb_set(). +-spec largest(Set) -> Element when + Set :: set(Element). largest({_, T}) -> largest_1(T). @@ -483,8 +473,8 @@ largest_1({_Key, _Smaller, Larger}) -> largest_1(Larger). -spec to_list(Set) -> List when - Set :: gb_set(), - List :: [term()]. + Set :: set(Element), + List :: [Element]. to_list({_, T}) -> to_list(T, []). @@ -496,8 +486,8 @@ to_list({Key, Small, Big}, L) -> to_list(nil, L) -> L. -spec iterator(Set) -> Iter when - Set :: gb_set(), - Iter :: iter(). + Set :: set(Element), + Iter :: iter(Element). iterator({_, T}) -> iterator(T, []). @@ -513,9 +503,8 @@ iterator(nil, As) -> As. -spec next(Iter1) -> {Element, Iter2} | 'none' when - Iter1 :: iter(), - Iter2 :: iter(), - Element :: term(). + Iter1 :: iter(Element), + Iter2 :: iter(Element). next([{X, _, T} | As]) -> {X, iterator(T, As)}; @@ -546,9 +535,9 @@ next([]) -> %% overhead. -spec union(Set1, Set2) -> Set3 when - Set1 :: gb_set(), - Set2 :: gb_set(), - Set3 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element), + Set3 :: set(Element). union({N1, T1}, {N2, T2}) when N2 < N1 -> union(to_list_1(T2), N2, T1, N1); @@ -570,7 +559,7 @@ union(L, N1, T2, N2) -> union_1(L, mk_set(N2, T2)) end. --spec mk_set(non_neg_integer(), gb_set_node()) -> gb_set(). +-spec mk_set(non_neg_integer(), gb_set_node(T)) -> set(T). mk_set(N, T) -> {N, T}. @@ -651,8 +640,8 @@ balance_revlist_1(L, 0) -> {nil, L}. -spec union(SetList) -> Set when - SetList :: [gb_set(),...], - Set :: gb_set(). + SetList :: [set(Element),...], + Set :: set(Element). union([S | Ss]) -> union_list(S, Ss); @@ -666,9 +655,9 @@ union_list(S, []) -> S. %% The rest is modelled on the above. -spec intersection(Set1, Set2) -> Set3 when - Set1 :: gb_set(), - Set2 :: gb_set(), - Set3 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element), + Set3 :: set(Element). intersection({N1, T1}, {N2, T2}) when N2 < N1 -> intersection(to_list_1(T2), N2, T1, N1); @@ -717,8 +706,8 @@ intersection_2(_, [], As, S) -> {S, balance_revlist(As, S)}. -spec intersection(SetList) -> Set when - SetList :: [gb_set(),...], - Set :: gb_set(). + SetList :: [set(Element),...], + Set :: set(Element). intersection([S | Ss]) -> intersection_list(S, Ss). @@ -728,8 +717,8 @@ intersection_list(S, [S1 | Ss]) -> intersection_list(S, []) -> S. -spec is_disjoint(Set1, Set2) -> boolean() when - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). is_disjoint({N1, T1}, {N2, T2}) when N1 < N2 -> is_disjoint_1(T1, T2); @@ -758,17 +747,17 @@ is_disjoint_1(_, nil) -> %% traverse the whole element list of the left operand. -spec subtract(Set1, Set2) -> Set3 when - Set1 :: gb_set(), - Set2 :: gb_set(), - Set3 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element), + Set3 :: set(Element). subtract(S1, S2) -> difference(S1, S2). -spec difference(Set1, Set2) -> Set3 when - Set1 :: gb_set(), - Set2 :: gb_set(), - Set3 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element), + Set3 :: set(Element). difference({N1, T1}, {N2, T2}) -> difference(to_list_1(T1), N1, T2, N2). @@ -817,8 +806,8 @@ difference_2(Xs, [], As, S) -> %% without the construction of a new set. -spec is_subset(Set1, Set2) -> boolean() when - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). is_subset({N1, T1}, {N2, T2}) -> is_subset(to_list_1(T1), N1, T2, N2). @@ -867,20 +856,20 @@ is_set({N, {_, _, _}}) when is_integer(N), N >= 0 -> true; is_set(_) -> false. -spec filter(Pred, Set1) -> Set2 when - Pred :: fun((E :: term()) -> boolean()), - Set1 :: gb_set(), - Set2 :: gb_set(). + Pred :: fun((Element) -> boolean()), + Set1 :: set(Element), + Set2 :: set(Element). filter(F, S) -> from_ordset([X || X <- to_list(S), F(X)]). -spec fold(Function, Acc0, Set) -> Acc1 when - Function :: fun((E :: term(), AccIn) -> AccOut), - Acc0 :: term(), - Acc1 :: term(), - AccIn :: term(), - AccOut :: term(), - Set :: gb_set(). + Function :: fun((Element, AccIn) -> AccOut), + Acc0 :: Acc, + Acc1 :: Acc, + AccIn :: Acc, + AccOut :: Acc, + Set :: set(Element). fold(F, A, {_, T}) when is_function(F, 2) -> fold_1(F, A, T). diff --git a/lib/stdlib/src/gb_trees.erl b/lib/stdlib/src/gb_trees.erl index 7a4dfe1a0b..7069b61873 100644 --- a/lib/stdlib/src/gb_trees.erl +++ b/lib/stdlib/src/gb_trees.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2013. All Rights Reserved. +%% Copyright Ericsson AB 2001-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 @@ -152,25 +152,25 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Some types. --export_type([iter/0]). +-export_type([tree/0, tree/2, iter/0, iter/2]). --type gb_tree_node() :: 'nil' | {_, _, _, _}. +-type gb_tree_node(K, V) :: 'nil' + | {K, V, gb_tree_node(K, V), gb_tree_node(K, V)}. +-type gb_tree_node() :: gb_tree_node(_, _). +-opaque tree(Key, Value) :: {non_neg_integer(), gb_tree_node(Key, Value)}. +-opaque tree() :: tree(_, _). +-opaque iter(Key, Value) :: [gb_tree_node(Key, Value)]. -opaque iter() :: [gb_tree_node()]. -%% A declaration equivalent to the following is currently hard-coded -%% in erl_types.erl -%% -%% -opaque gb_tree() :: {non_neg_integer(), gb_tree_node()}. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec empty() -> gb_tree(). +-spec empty() -> tree(). empty() -> {0, nil}. -spec is_empty(Tree) -> boolean() when - Tree :: gb_tree(). + Tree :: tree(). is_empty({0, nil}) -> true; @@ -178,17 +178,15 @@ is_empty(_) -> false. -spec size(Tree) -> non_neg_integer() when - Tree :: gb_tree(). + Tree :: tree(). size({Size, _}) when is_integer(Size), Size >= 0 -> Size. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec lookup(Key, Tree) -> 'none' | {'value', Val} when - Key :: term(), - Val :: term(), - Tree :: gb_tree(). +-spec lookup(Key, Tree) -> 'none' | {'value', Value} when + Tree :: tree(Key, Value). lookup(Key, {_, T}) -> lookup_1(Key, T). @@ -214,8 +212,7 @@ lookup_1(_, nil) -> %% This is a specialized version of `lookup'. -spec is_defined(Key, Tree) -> boolean() when - Key :: term(), - Tree :: gb_tree(). + Tree :: tree(Key, Value :: term()). is_defined(Key, {_, T}) -> is_defined_1(Key, T). @@ -233,10 +230,8 @@ is_defined_1(_, nil) -> %% This is a specialized version of `lookup'. --spec get(Key, Tree) -> Val when - Key :: term(), - Tree :: gb_tree(), - Val :: term(). +-spec get(Key, Tree) -> Value when + Tree :: tree(Key, Value). get(Key, {_, T}) -> get_1(Key, T). @@ -250,11 +245,9 @@ get_1(_, {_, Value, _, _}) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec update(Key, Val, Tree1) -> Tree2 when - Key :: term(), - Val :: term(), - Tree1 :: gb_tree(), - Tree2 :: gb_tree(). +-spec update(Key, Value, Tree1) -> Tree2 when + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). update(Key, Val, {S, T}) -> T1 = update_1(Key, Val, T), @@ -271,11 +264,9 @@ update_1(Key, Value, {_, _, Smaller, Bigger}) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec insert(Key, Val, Tree1) -> Tree2 when - Key :: term(), - Val :: term(), - Tree1 :: gb_tree(), - Tree2 :: gb_tree(). +-spec insert(Key, Value, Tree1) -> Tree2 when + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). insert(Key, Val, {S, T}) when is_integer(S) -> S1 = S+1, @@ -324,11 +315,9 @@ insert_1(Key, _, _, _) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec enter(Key, Val, Tree1) -> Tree2 when - Key :: term(), - Val :: term(), - Tree1 :: gb_tree(), - Tree2 :: gb_tree(). +-spec enter(Key, Value, Tree1) -> Tree2 when + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). enter(Key, Val, T) -> case is_defined(Key, T) of @@ -352,8 +341,8 @@ count(nil) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec balance(Tree1) -> Tree2 when - Tree1 :: gb_tree(), - Tree2 :: gb_tree(). + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). balance({S, T}) -> {S, balance(T, S)}. @@ -379,8 +368,8 @@ balance_list_1(L, 0) -> {nil, L}. -spec from_orddict(List) -> Tree when - List :: [{Key :: term(), Val :: term()}], - Tree :: gb_tree(). + List :: [{Key, Value}], + Tree :: tree(Key, Value). from_orddict(L) -> S = length(L), @@ -389,9 +378,8 @@ from_orddict(L) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec delete_any(Key, Tree1) -> Tree2 when - Key :: term(), - Tree1 :: gb_tree(), - Tree2 :: gb_tree(). + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). delete_any(Key, T) -> case is_defined(Key, T) of @@ -404,9 +392,8 @@ delete_any(Key, T) -> %%% delete. Assumes that key is present. -spec delete(Key, Tree1) -> Tree2 when - Key :: term(), - Tree1 :: gb_tree(), - Tree2 :: gb_tree(). + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). delete(Key, {S, T}) when is_integer(S), S >= 0 -> {S - 1, delete_1(Key, T)}. @@ -432,11 +419,9 @@ merge(Smaller, Larger) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec take_smallest(Tree1) -> {Key, Val, Tree2} when - Tree1 :: gb_tree(), - Tree2 :: gb_tree(), - Key :: term(), - Val :: term(). +-spec take_smallest(Tree1) -> {Key, Value, Tree2} when + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). take_smallest({Size, Tree}) when is_integer(Size), Size >= 0 -> {Key, Value, Larger} = take_smallest1(Tree), @@ -448,10 +433,8 @@ take_smallest1({Key, Value, Smaller, Larger}) -> {Key1, Value1, Smaller1} = take_smallest1(Smaller), {Key1, Value1, {Key, Value, Smaller1, Larger}}. --spec smallest(Tree) -> {Key, Val} when - Tree :: gb_tree(), - Key :: term(), - Val :: term(). +-spec smallest(Tree) -> {Key, Value} when + Tree :: tree(Key, Value). smallest({_, Tree}) -> smallest_1(Tree). @@ -461,11 +444,9 @@ smallest_1({Key, Value, nil, _Larger}) -> smallest_1({_Key, _Value, Smaller, _Larger}) -> smallest_1(Smaller). --spec take_largest(Tree1) -> {Key, Val, Tree2} when - Tree1 :: gb_tree(), - Tree2 :: gb_tree(), - Key :: term(), - Val :: term(). +-spec take_largest(Tree1) -> {Key, Value, Tree2} when + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). take_largest({Size, Tree}) when is_integer(Size), Size >= 0 -> {Key, Value, Smaller} = take_largest1(Tree), @@ -477,10 +458,8 @@ take_largest1({Key, Value, Smaller, Larger}) -> {Key1, Value1, Larger1} = take_largest1(Larger), {Key1, Value1, {Key, Value, Smaller, Larger1}}. --spec largest(Tree) -> {Key, Val} when - Tree :: gb_tree(), - Key :: term(), - Val :: term(). +-spec largest(Tree) -> {Key, Value} when + Tree :: tree(Key, Value). largest({_, Tree}) -> largest_1(Tree). @@ -492,10 +471,8 @@ largest_1({_Key, _Value, _Smaller, Larger}) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec to_list(Tree) -> [{Key, Val}] when - Tree :: gb_tree(), - Key :: term(), - Val :: term(). +-spec to_list(Tree) -> [{Key, Value}] when + Tree :: tree(Key, Value). to_list({_, T}) -> to_list(T, []). @@ -509,8 +486,7 @@ to_list(nil, L) -> L. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec keys(Tree) -> [Key] when - Tree :: gb_tree(), - Key :: term(). + Tree :: tree(Key, Value :: term()). keys({_, T}) -> keys(T, []). @@ -521,9 +497,8 @@ keys(nil, L) -> L. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec values(Tree) -> [Val] when - Tree :: gb_tree(), - Val :: term(). +-spec values(Tree) -> [Value] when + Tree :: tree(Key :: term(), Value). values({_, T}) -> values(T, []). @@ -535,8 +510,8 @@ values(nil, L) -> L. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec iterator(Tree) -> Iter when - Tree :: gb_tree(), - Iter :: iter(). + Tree :: tree(Key, Value), + Iter :: iter(Key, Value). iterator({_, T}) -> iterator_1(T). @@ -554,11 +529,9 @@ iterator({_, _, L, _} = T, As) -> iterator(nil, As) -> As. --spec next(Iter1) -> 'none' | {Key, Val, Iter2} when - Iter1 :: iter(), - Iter2 :: iter(), - Key :: term(), - Val :: term(). +-spec next(Iter1) -> 'none' | {Key, Value, Iter2} when + Iter1 :: iter(Key, Value), + Iter2 :: iter(Key, Value). next([{X, V, _, T} | As]) -> {X, V, iterator(T, As)}; @@ -568,9 +541,9 @@ next([]) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec map(Function, Tree1) -> Tree2 when - Function :: fun((K :: term(), V1 :: term()) -> V2 :: term()), - Tree1 :: gb_tree(), - Tree2 :: gb_tree(). + Function :: fun((K :: Key, V1 :: Value1) -> V2 :: Value2), + Tree1 :: tree(Key, Value1), + Tree2 :: tree(Key, Value2). map(F, {Size, Tree}) when is_function(F, 2) -> {Size, map_1(F, Tree)}. diff --git a/lib/stdlib/src/lists.erl b/lib/stdlib/src/lists.erl index d6a9f4645d..6303465d3d 100644 --- a/lib/stdlib/src/lists.erl +++ b/lib/stdlib/src/lists.erl @@ -22,7 +22,7 @@ -compile({no_auto_import,[min/2]}). -export([append/2, append/1, subtract/2, reverse/1, - nth/2, nthtail/2, prefix/2, suffix/2, last/1, + nth/2, nthtail/2, prefix/2, suffix/2, droplast/1, last/1, seq/2, seq/3, sum/1, duplicate/2, min/1, max/1, sublist/2, sublist/3, delete/2, unzip/1, unzip3/1, zip/2, zip3/3, zipwith/3, zipwith3/4, @@ -203,6 +203,19 @@ suffix(Suffix, List) -> Delta = length(List) - length(Suffix), Delta >= 0 andalso nthtail(Delta, List) =:= Suffix. +%% droplast(List) returns the list dropping its last element + +-spec droplast(List) -> InitList when + List :: [T, ...], + InitList :: [T], + T :: term(). + +%% This is the simple recursive implementation +%% reverse(tl(reverse(L))) is faster on average, +%% but creates more garbage. +droplast([_T]) -> []; +droplast([H|T]) -> [H|droplast(T)]. + %% last(List) returns the last element in a list. -spec last(List) -> Last when diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index cebc9c91bd..380bc3eccc 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -577,6 +577,24 @@ obsolete_1(wxCursor, new, 3) -> obsolete_1(wxCursor, new, 4) -> {deprecated,"deprecated function not available in wxWidgets-2.9 and later"}; +%% Added in OTP 17. +obsolete_1(asn1ct, decode,3) -> + {deprecated,"deprecated; use Mod:decode/2 instead"}; +obsolete_1(asn1ct, encode, 3) -> + {deprecated,"deprecated; use Mod:encode/2 instead"}; +obsolete_1(asn1rt, decode,3) -> + {deprecated,"deprecated; use Mod:decode/2 instead"}; +obsolete_1(asn1rt, encode, 2) -> + {deprecated,"deprecated; use Mod:encode/2 instead"}; +obsolete_1(asn1rt, encode, 3) -> + {deprecated,"deprecated; use Mod:encode/2 instead"}; +obsolete_1(asn1rt, info, 1) -> + {deprecated,"deprecated; use Mod:info/0 instead"}; +obsolete_1(asn1rt, utf8_binary_to_list, 1) -> + {deprecated,{unicode,characters_to_list,1}}; +obsolete_1(asn1rt, utf8_list_to_binary, 1) -> + {deprecated,{unicode,characters_to_binary,1}}; + obsolete_1(_, _, _) -> no. diff --git a/lib/stdlib/src/queue.erl b/lib/stdlib/src/queue.erl index 4bbf5de8a5..472d503b99 100644 --- a/lib/stdlib/src/queue.erl +++ b/lib/stdlib/src/queue.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-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 @@ -32,6 +32,8 @@ -export([cons/2,head/1,tail/1, snoc/2,last/1,daeh/1,init/1,liat/1,lait/1]). +-export_type([queue/0, queue/1]). + %%-------------------------------------------------------------------------- %% Efficient implementation of double ended fifo queues %% @@ -44,10 +46,9 @@ %% that is; the RearList is reversed. %% -%% A declaration equivalent to the following is currently hard-coded -%% in erl_types.erl -%% -%% -opaque queue() :: {list(), list()}. +-opaque queue(Item) :: {list(Item), list(Item)}. + +-opaque queue() :: queue(_). %% Creation, inspection and conversion @@ -79,7 +80,7 @@ len(Q) -> erlang:error(badarg, [Q]). %% O(len(Q)) --spec to_list(Q :: queue()) -> list(). +-spec to_list(Q :: queue(Item)) -> list(Item). to_list({In,Out}) when is_list(In), is_list(Out) -> Out++lists:reverse(In, []); to_list(Q) -> @@ -88,7 +89,7 @@ to_list(Q) -> %% Create queue from list %% %% O(length(L)) --spec from_list(L :: list()) -> queue(). +-spec from_list(L :: list(Item)) -> queue(Item). from_list(L) when is_list(L) -> f2r(L); from_list(L) -> @@ -97,7 +98,7 @@ from_list(L) -> %% Return true or false depending on if element is in queue %% %% O(length(Q)) worst case --spec member(Item :: term(), Q :: queue()) -> boolean(). +-spec member(Item, Q :: queue(Item)) -> boolean(). member(X, {R,F}) when is_list(R), is_list(F) -> lists:member(X, R) orelse lists:member(X, F); member(X, Q) -> @@ -110,7 +111,7 @@ member(X, Q) -> %% Put at least one element in each list, if it is cheap %% %% O(1) --spec in(Item :: term(), Q1 :: queue()) -> Q2 :: queue(). +-spec in(Item, Q1 :: queue(Item)) -> Q2 :: queue(Item). in(X, {[_]=In,[]}) -> {[X], In}; in(X, {In,Out}) when is_list(In), is_list(Out) -> @@ -122,7 +123,7 @@ in(X, Q) -> %% Put at least one element in each list, if it is cheap %% %% O(1) --spec in_r(Item :: term(), Q1 :: queue()) -> Q2 :: queue(). +-spec in_r(Item, Q1 :: queue(Item)) -> Q2 :: queue(Item). in_r(X, {[],[_]=F}) -> {F,[X]}; in_r(X, {R,F}) when is_list(R), is_list(F) -> @@ -133,9 +134,9 @@ in_r(X, Q) -> %% Take from head/front %% %% O(1) amortized, O(len(Q)) worst case --spec out(Q1 :: queue()) -> - {{value, Item :: term()}, Q2 :: queue()} | - {empty, Q1 :: queue()}. +-spec out(Q1 :: queue(Item)) -> + {{value, Item}, Q2 :: queue(Item)} | + {empty, Q1 :: queue(Item)}. out({[],[]}=Q) -> {empty,Q}; out({[V],[]}) -> @@ -153,9 +154,9 @@ out(Q) -> %% Take from tail/rear %% %% O(1) amortized, O(len(Q)) worst case --spec out_r(Q1 :: queue()) -> - {{value, Item :: term()}, Q2 :: queue()} | - {empty, Q1 :: queue()}. +-spec out_r(Q1 :: queue(Item)) -> + {{value, Item}, Q2 :: queue(Item)} | + {empty, Q1 :: queue(Item)}. out_r({[],[]}=Q) -> {empty,Q}; out_r({[],[V]}) -> @@ -176,7 +177,7 @@ out_r(Q) -> %% Return the first element in the queue %% %% O(1) since the queue is supposed to be well formed --spec get(Q :: queue()) -> Item :: term(). +-spec get(Q :: queue(Item)) -> Item. get({[],[]}=Q) -> erlang:error(empty, [Q]); get({R,F}) when is_list(R), is_list(F) -> @@ -195,7 +196,7 @@ get([_|R], []) -> % malformed queue -> O(len(Q)) %% Return the last element in the queue %% %% O(1) since the queue is supposed to be well formed --spec get_r(Q :: queue()) -> Item :: term(). +-spec get_r(Q :: queue(Item)) -> Item. get_r({[],[]}=Q) -> erlang:error(empty, [Q]); get_r({[H|_],F}) when is_list(F) -> @@ -210,7 +211,7 @@ get_r(Q) -> %% Return the first element in the queue %% %% O(1) since the queue is supposed to be well formed --spec peek(Q :: queue()) -> empty | {value,Item :: term()}. +-spec peek(Q :: queue(Item)) -> empty | {value, Item}. peek({[],[]}) -> empty; peek({R,[H|_]}) when is_list(R) -> @@ -225,7 +226,7 @@ peek(Q) -> %% Return the last element in the queue %% %% O(1) since the queue is supposed to be well formed --spec peek_r(Q :: queue()) -> empty | {value,Item :: term()}. +-spec peek_r(Q :: queue(Item)) -> empty | {value, Item}. peek_r({[],[]}) -> empty; peek_r({[H|_],F}) when is_list(F) -> @@ -240,7 +241,7 @@ peek_r(Q) -> %% Remove the first element and return resulting queue %% %% O(1) amortized --spec drop(Q1 :: queue()) -> Q2 :: queue(). +-spec drop(Q1 :: queue(Item)) -> Q2 :: queue(Item). drop({[],[]}=Q) -> erlang:error(empty, [Q]); drop({[_],[]}) -> @@ -258,7 +259,7 @@ drop(Q) -> %% Remove the last element and return resulting queue %% %% O(1) amortized --spec drop_r(Q1 :: queue()) -> Q2 :: queue(). +-spec drop_r(Q1 :: queue(Item)) -> Q2 :: queue(Item). drop_r({[],[]}=Q) -> erlang:error(empty, [Q]); drop_r({[],[_]}) -> @@ -279,7 +280,7 @@ drop_r(Q) -> %% Return reversed queue %% %% O(1) --spec reverse(Q1 :: queue()) -> Q2 :: queue(). +-spec reverse(Q1 :: queue(Item)) -> Q2 :: queue(Item). reverse({R,F}) when is_list(R), is_list(F) -> {F,R}; reverse(Q) -> @@ -289,7 +290,7 @@ reverse(Q) -> %% %% Q2 empty: O(1) %% else: O(len(Q1)) --spec join(Q1 :: queue(), Q2 :: queue()) -> Q3 :: queue(). +-spec join(Q1 :: queue(Item), Q2 :: queue(Item)) -> Q3 :: queue(Item). join({R,F}=Q, {[],[]}) when is_list(R), is_list(F) -> Q; join({[],[]}, {R,F}=Q) when is_list(R), is_list(F) -> @@ -303,8 +304,8 @@ join(Q1, Q2) -> %% %% N = 0..len(Q) %% O(max(N, len(Q))) --spec split(N :: non_neg_integer(), Q1 :: queue()) -> - {Q2 :: queue(),Q3 :: queue()}. +-spec split(N :: non_neg_integer(), Q1 :: queue(Item)) -> + {Q2 :: queue(Item),Q3 :: queue(Item)}. split(0, {R,F}=Q) when is_list(R), is_list(F) -> {{[],[]},Q}; split(N, {R,F}=Q) when is_integer(N), N >= 1, is_list(R), is_list(F) -> @@ -345,8 +346,8 @@ split_r1_to_f2(N, [X|R1], F1, R2, F2) -> %% %% Fun(_) -> List: O(length(List) * len(Q)) %% else: O(len(Q) --spec filter(Fun, Q1 :: queue()) -> Q2 :: queue() when - Fun :: fun((Item :: term()) -> boolean() | list()). +-spec filter(Fun, Q1 :: queue(Item)) -> Q2 :: queue(Item) when + Fun :: fun((Item) -> boolean() | list(Item)). filter(Fun, {R0,F0}) when is_function(Fun, 1), is_list(R0), is_list(F0) -> F = filter_f(Fun, F0), R = filter_r(Fun, R0), @@ -422,7 +423,7 @@ filter_r(Fun, [X|R0]) -> %% Cons to head %% --spec cons(Item :: term(), Q1 :: queue()) -> Q2 :: queue(). +-spec cons(Item, Q1 :: queue(Item)) -> Q2 :: queue(Item). cons(X, Q) -> in_r(X, Q). @@ -431,7 +432,7 @@ cons(X, Q) -> %% Return the first element in the queue %% %% O(1) since the queue is supposed to be well formed --spec head(Q :: queue()) -> Item :: term(). +-spec head(Q :: queue(Item)) -> Item. head({[],[]}=Q) -> erlang:error(empty, [Q]); head({R,F}) when is_list(R), is_list(F) -> @@ -441,7 +442,7 @@ head(Q) -> %% Remove head element and return resulting queue %% --spec tail(Q1 :: queue()) -> Q2 :: queue(). +-spec tail(Q1 :: queue(Item)) -> Q2 :: queue(Item). tail(Q) -> drop(Q). @@ -449,22 +450,22 @@ tail(Q) -> %% Cons to tail %% --spec snoc(Q1 :: queue(), Item :: term()) -> Q2 :: queue(). +-spec snoc(Q1 :: queue(Item), Item) -> Q2 :: queue(Item). snoc(Q, X) -> in(X, Q). %% Return last element --spec daeh(Q :: queue()) -> Item :: term(). +-spec daeh(Q :: queue(Item)) -> Item. daeh(Q) -> get_r(Q). --spec last(Q :: queue()) -> Item :: term(). +-spec last(Q :: queue(Item)) -> Item. last(Q) -> get_r(Q). %% Remove last element and return resulting queue --spec liat(Q1 :: queue()) -> Q2 :: queue(). +-spec liat(Q1 :: queue(Item)) -> Q2 :: queue(Item). liat(Q) -> drop_r(Q). --spec lait(Q1 :: queue()) -> Q2 :: queue(). +-spec lait(Q1 :: queue(Item)) -> Q2 :: queue(Item). lait(Q) -> drop_r(Q). %% Oops, mis-spelled 'tail' reversed. Forget this one. --spec init(Q1 :: queue()) -> Q2 :: queue(). +-spec init(Q1 :: queue(Item)) -> Q2 :: queue(Item). init(Q) -> drop_r(Q). %%-------------------------------------------------------------------------- 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/src/sets.erl b/lib/stdlib/src/sets.erl index ebf011a7d9..be4b600f25 100644 --- a/lib/stdlib/src/sets.erl +++ b/lib/stdlib/src/sets.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2013. All Rights Reserved. +%% Copyright Ericsson AB 2000-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 @@ -43,6 +43,8 @@ -export([subtract/2,is_subset/2]). -export([fold/3,filter/2]). +-export_type([set/0, set/1]). + %% Note: mk_seg/1 must be changed too if seg_size is changed. -define(seg_size, 16). -define(max_seg, 32). @@ -54,7 +56,8 @@ %%------------------------------------------------------------------------------ -type seg() :: tuple(). --type segs() :: tuple(). +-type segs(E) :: tuple() + | E. % dummy %% Define a hash set. The default values are the standard ones. -record(set, @@ -65,14 +68,12 @@ exp_size=?exp_size :: non_neg_integer(), % Size to expand at con_size=?con_size :: non_neg_integer(), % Size to contract at empty :: seg(), % Empty segment - segs :: segs() % Segments + segs :: segs(_) % Segments }). -%% A declaration equivalent to the following one is hard-coded in erl_types. -%% That declaration contains hard-coded information about the #set{} -%% record and the types of its fields. So, please make sure that any -%% changes to its structure are also propagated to erl_types.erl. -%% -%% -opaque set() :: #set{}. + +-opaque set() :: set(_). + +-opaque set(Element) :: #set{segs :: segs(Element)}. %%------------------------------------------------------------------------------ @@ -98,24 +99,23 @@ size(S) -> S#set.size. %% to_list(Set) -> [Elem]. %% Return the elements in Set as a list. -spec to_list(Set) -> List when - Set :: set(), - List :: [term()]. + Set :: set(Element), + List :: [Element]. to_list(S) -> fold(fun (Elem, List) -> [Elem|List] end, [], S). %% from_list([Elem]) -> Set. %% Build a set from the elements in List. -spec from_list(List) -> Set when - List :: [term()], - Set :: set(). + List :: [Element], + Set :: set(Element). from_list(L) -> lists:foldl(fun (E, S) -> add_element(E, S) end, new(), L). %% is_element(Element, Set) -> boolean(). %% Return 'true' if Element is an element of Set, else 'false'. -spec is_element(Element, Set) -> boolean() when - Element :: term(), - Set :: set(). + Set :: set(Element). is_element(E, S) -> Slot = get_slot(S, E), Bkt = get_bucket(S, Slot), @@ -124,9 +124,8 @@ is_element(E, S) -> %% add_element(Element, Set) -> Set. %% Return Set with Element inserted in it. -spec add_element(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: set(), - Set2 :: set(). + Set1 :: set(Element), + Set2 :: set(Element). add_element(E, S0) -> Slot = get_slot(S0, E), {S1,Ic} = on_bucket(fun (B0) -> add_bkt_el(E, B0, B0) end, S0, Slot), @@ -141,9 +140,8 @@ add_bkt_el(E, [], Bkt) -> {[E|Bkt],1}. %% del_element(Element, Set) -> Set. %% Return Set but with Element removed. -spec del_element(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: set(), - Set2 :: set(). + Set1 :: set(Element), + Set2 :: set(Element). del_element(E, S0) -> Slot = get_slot(S0, E), {S1,Dc} = on_bucket(fun (B0) -> del_bkt_el(E, B0) end, S0, Slot), @@ -159,9 +157,9 @@ del_bkt_el(_, []) -> {[],0}. %% union(Set1, Set2) -> Set %% Return the union of Set1 and Set2. -spec union(Set1, Set2) -> Set3 when - Set1 :: set(), - Set2 :: set(), - Set3 :: set(). + Set1 :: set(Element), + Set2 :: set(Element), + Set3 :: set(Element). union(S1, S2) when S1#set.size < S2#set.size -> fold(fun (E, S) -> add_element(E, S) end, S2, S1); union(S1, S2) -> @@ -170,14 +168,14 @@ union(S1, S2) -> %% union([Set]) -> Set %% Return the union of the list of sets. -spec union(SetList) -> Set when - SetList :: [set()], - Set :: set(). + SetList :: [set(Element)], + Set :: set(Element). union([S1,S2|Ss]) -> union1(union(S1, S2), Ss); union([S]) -> S; union([]) -> new(). --spec union1(set(), [set()]) -> set(). +-spec union1(set(E), [set(E)]) -> set(E). union1(S1, [S2|Ss]) -> union1(union(S1, S2), Ss); union1(S1, []) -> S1. @@ -185,9 +183,9 @@ union1(S1, []) -> S1. %% intersection(Set1, Set2) -> Set. %% Return the intersection of Set1 and Set2. -spec intersection(Set1, Set2) -> Set3 when - Set1 :: set(), - Set2 :: set(), - Set3 :: set(). + Set1 :: set(Element), + Set2 :: set(Element), + Set3 :: set(Element). intersection(S1, S2) when S1#set.size < S2#set.size -> filter(fun (E) -> is_element(E, S2) end, S1); intersection(S1, S2) -> @@ -196,13 +194,13 @@ intersection(S1, S2) -> %% intersection([Set]) -> Set. %% Return the intersection of the list of sets. -spec intersection(SetList) -> Set when - SetList :: [set(),...], - Set :: set(). + SetList :: [set(Element),...], + Set :: set(Element). intersection([S1,S2|Ss]) -> intersection1(intersection(S1, S2), Ss); intersection([S]) -> S. --spec intersection1(set(), [set()]) -> set(). +-spec intersection1(set(E), [set(E)]) -> set(E). intersection1(S1, [S2|Ss]) -> intersection1(intersection(S1, S2), Ss); intersection1(S1, []) -> S1. @@ -210,8 +208,8 @@ intersection1(S1, []) -> S1. %% is_disjoint(Set1, Set2) -> boolean(). %% Check whether Set1 and Set2 are disjoint. -spec is_disjoint(Set1, Set2) -> boolean() when - Set1 :: set(), - Set2 :: set(). + Set1 :: set(Element), + Set2 :: set(Element). is_disjoint(S1, S2) when S1#set.size < S2#set.size -> fold(fun (_, false) -> false; (E, true) -> not is_element(E, S2) @@ -225,9 +223,9 @@ is_disjoint(S1, S2) -> %% Return all and only the elements of Set1 which are not also in %% Set2. -spec subtract(Set1, Set2) -> Set3 when - Set1 :: set(), - Set2 :: set(), - Set3 :: set(). + Set1 :: set(Element), + Set2 :: set(Element), + Set3 :: set(Element). subtract(S1, S2) -> filter(fun (E) -> not is_element(E, S2) end, S1). @@ -235,34 +233,34 @@ subtract(S1, S2) -> %% Return 'true' when every element of Set1 is also a member of %% Set2, else 'false'. -spec is_subset(Set1, Set2) -> boolean() when - Set1 :: set(), - Set2 :: set(). + Set1 :: set(Element), + Set2 :: set(Element). is_subset(S1, S2) -> fold(fun (E, Sub) -> Sub andalso is_element(E, S2) end, true, S1). %% fold(Fun, Accumulator, Set) -> Accumulator. %% Fold function Fun over all elements in Set and return Accumulator. -spec fold(Function, Acc0, Set) -> Acc1 when - Function :: fun((E :: term(),AccIn) -> AccOut), - Set :: set(), - Acc0 :: T, - Acc1 :: T, - AccIn :: T, - AccOut :: T. + Function :: fun((Element, AccIn) -> AccOut), + Set :: set(Element), + Acc0 :: Acc, + Acc1 :: Acc, + AccIn :: Acc, + AccOut :: Acc. fold(F, Acc, D) -> fold_set(F, Acc, D). %% filter(Fun, Set) -> Set. %% Filter Set with Fun. -spec filter(Pred, Set1) -> Set2 when - Pred :: fun((E :: term()) -> boolean()), - Set1 :: set(), - Set2 :: set(). + Pred :: fun((Element) -> boolean()), + Set1 :: set(Element), + Set2 :: set(Element). filter(F, D) -> filter_set(F, D). %% get_slot(Hashdb, Key) -> Slot. %% Get the slot. First hash on the new range, if we hit a bucket %% which has not been split use the unsplit buddy bucket. --spec get_slot(set(), term()) -> non_neg_integer(). +-spec get_slot(set(E), E) -> non_neg_integer(). get_slot(T, Key) -> H = erlang:phash(Key, T#set.maxn), if @@ -276,8 +274,8 @@ get_bucket(T, Slot) -> get_bucket_s(T#set.segs, Slot). %% on_bucket(Fun, Hashdb, Slot) -> {NewHashDb,Result}. %% Apply Fun to the bucket in Slot and replace the returned bucket. --spec on_bucket(fun((_) -> {[_], 0 | 1}), set(), non_neg_integer()) -> - {set(), 0 | 1}. +-spec on_bucket(fun((_) -> {[_], 0 | 1}), set(E), non_neg_integer()) -> + {set(E), 0 | 1}. on_bucket(F, T, Slot) -> SegI = ((Slot-1) div ?seg_size) + 1, BktI = ((Slot-1) rem ?seg_size) + 1, @@ -351,7 +349,7 @@ put_bucket_s(Segs, Slot, Bkt) -> Seg = setelement(BktI, element(SegI, Segs), Bkt), setelement(SegI, Segs, Seg). --spec maybe_expand(set(), 0 | 1) -> set(). +-spec maybe_expand(set(E), 0 | 1) -> set(E). maybe_expand(T0, Ic) when T0#set.size + Ic > T0#set.exp_size -> T = maybe_expand_segs(T0), %Do we need more segments. N = T#set.n + 1, %Next slot to expand into @@ -369,14 +367,14 @@ maybe_expand(T0, Ic) when T0#set.size + Ic > T0#set.exp_size -> segs = Segs2}; maybe_expand(T, Ic) -> T#set{size = T#set.size + Ic}. --spec maybe_expand_segs(set()) -> set(). +-spec maybe_expand_segs(set(E)) -> set(E). maybe_expand_segs(T) when T#set.n =:= T#set.maxn -> T#set{maxn = 2 * T#set.maxn, bso = 2 * T#set.bso, segs = expand_segs(T#set.segs, T#set.empty)}; maybe_expand_segs(T) -> T. --spec maybe_contract(set(), non_neg_integer()) -> set(). +-spec maybe_contract(set(E), non_neg_integer()) -> set(E). maybe_contract(T, Dc) when T#set.size - Dc < T#set.con_size, T#set.n > ?seg_size -> N = T#set.n, @@ -395,7 +393,7 @@ maybe_contract(T, Dc) when T#set.size - Dc < T#set.con_size, segs = Segs2}); maybe_contract(T, Dc) -> T#set{size = T#set.size - Dc}. --spec maybe_contract_segs(set()) -> set(). +-spec maybe_contract_segs(set(E)) -> set(E). maybe_contract_segs(T) when T#set.n =:= T#set.bso -> T#set{maxn = T#set.maxn div 2, bso = T#set.bso div 2, @@ -422,7 +420,7 @@ mk_seg(16) -> {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]}. %% of segments. We special case the powers of 2 upto 32, this should %% catch most case. N.B. the last element in the segments tuple is %% an extra element containing a default empty segment. --spec expand_segs(segs(), seg()) -> segs(). +-spec expand_segs(segs(E), seg()) -> segs(E). expand_segs({B1}, Empty) -> {B1,Empty}; expand_segs({B1,B2}, Empty) -> @@ -440,7 +438,7 @@ expand_segs(Segs, Empty) -> list_to_tuple(tuple_to_list(Segs) ++ lists:duplicate(tuple_size(Segs), Empty)). --spec contract_segs(segs()) -> segs(). +-spec contract_segs(segs(E)) -> segs(E). contract_segs({B1,_}) -> {B1}; contract_segs({B1,B2,_,_}) -> diff --git a/lib/stdlib/src/sofs.erl b/lib/stdlib/src/sofs.erl index 34eb224647..0bd67db100 100644 --- a/lib/stdlib/src/sofs.erl +++ b/lib/stdlib/src/sofs.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% Copyright Ericsson AB 2001-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 @@ -1509,7 +1509,7 @@ family_projection(SetFun, F) when ?IS_SET(F) -> %%% -spec(family_to_digraph(Family) -> Graph when - Graph :: digraph(), + Graph :: digraph:graph(), Family :: family()). family_to_digraph(F) when ?IS_SET(F) -> case ?TYPE(F) of @@ -1519,7 +1519,7 @@ family_to_digraph(F) when ?IS_SET(F) -> end. -spec(family_to_digraph(Family, GraphType) -> Graph when - Graph :: digraph(), + Graph :: digraph:graph(), Family :: family(), GraphType :: [digraph:d_type()]). family_to_digraph(F, Type) when ?IS_SET(F) -> @@ -1541,7 +1541,7 @@ family_to_digraph(F, Type) when ?IS_SET(F) -> end. -spec(digraph_to_family(Graph) -> Family when - Graph :: digraph(), + Graph :: digraph:graph(), Family :: family()). digraph_to_family(G) -> case catch digraph_family(G) of @@ -1550,7 +1550,7 @@ digraph_to_family(G) -> end. -spec(digraph_to_family(Graph, Type) -> Family when - Graph :: digraph(), + Graph :: digraph:graph(), Family :: family(), Type :: type()). digraph_to_family(G, T) -> diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src index 749a9a4201..22eefb2514 100644 --- a/lib/stdlib/src/stdlib.appup.src +++ b/lib/stdlib/src/stdlib.appup.src @@ -1,7 +1,7 @@ %% -*- erlang -*- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% Copyright Ericsson AB 1999-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 @@ -16,12 +16,10 @@ %% %% %CopyrightEnd% {"%VSN%", - %% Up from - max two major revisions back + %% Up from - max one major revision back [{<<"2\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17 - {<<"1\\.19(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R16 - {<<"1\\.18(\\.[0-9]+)*">>,[restart_new_emulator]}],%% R15 - %% Down to - max two major revisions back + {<<"1\\.19(\\.[0-9]+)*">>,[restart_new_emulator]}],%% R16 + %% Down to - max one major revision back [{<<"2\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R17 - {<<"1\\.19(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R16 - {<<"1\\.18(\\.[0-9]+)*">>,[restart_new_emulator]}] %% R15 + {<<"1\\.19(\\.[0-9]+)*">>,[restart_new_emulator]}] %% R16 }. diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index d18387568d..ede2742875 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-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 @@ -45,10 +45,13 @@ -type restart() :: 'permanent' | 'transient' | 'temporary'. -type shutdown() :: 'brutal_kill' | timeout(). -type worker() :: 'worker' | 'supervisor'. --type sup_name() :: {'local', Name :: atom()} | {'global', Name :: atom()}. +-type sup_name() :: {'local', Name :: atom()} + | {'global', Name :: atom()} + | {'via', Module :: module(), Name :: any()}. -type sup_ref() :: (Name :: atom()) | {Name :: atom(), Node :: node()} | {'global', Name :: atom()} + | {'via', Module :: module(), Name :: any()} | pid(). -type child_spec() :: {Id :: child_id(), StartFunc :: mfargs(), @@ -74,14 +77,15 @@ modules = [] :: modules()}). -type child_rec() :: #child{}. --define(DICT, dict). +-define(DICTS, dict). +-define(DICT, dict:dict). -define(SETS, sets). --define(SET, set). +-define(SET, sets:set). -record(state, {name, strategy :: strategy(), children = [] :: [child_rec()], - dynamics :: ?DICT() | ?SET(), + dynamics :: ?DICT(pid(), list()) | ?SET(pid()), intensity :: non_neg_integer(), period :: pos_integer(), restarts = [], @@ -441,7 +445,7 @@ handle_call(which_children, _From, #state{children = [#child{restart_type = RTyp State) when ?is_simple(State) -> Reply = lists:map(fun({?restarting(_),_}) -> {undefined,restarting,CT,Mods}; ({Pid, _}) -> {undefined, Pid, CT, Mods} end, - ?DICT:to_list(dynamics_db(RType, State#state.dynamics))), + ?DICTS:to_list(dynamics_db(RType, State#state.dynamics))), {reply, Reply, State}; handle_call(which_children, _From, State) -> @@ -480,7 +484,7 @@ handle_call(count_children, _From, #state{children = [#child{restart_type = RTy child_type = CT}]} = State) when ?is_simple(State) -> {Active, Count} = - ?DICT:fold(fun(Pid, _Val, {Alive, Tot}) -> + ?DICTS:fold(fun(Pid, _Val, {Alive, Tot}) -> case is_pid(Pid) andalso is_process_alive(Pid) of true -> {Alive+1, Tot +1}; @@ -774,17 +778,17 @@ restart(Child, State) -> restart(simple_one_for_one, Child, State) -> #child{pid = OldPid, mfargs = {M, F, A}} = Child, - Dynamics = ?DICT:erase(OldPid, dynamics_db(Child#child.restart_type, + Dynamics = ?DICTS:erase(OldPid, dynamics_db(Child#child.restart_type, State#state.dynamics)), case do_start_child_i(M, F, A) of {ok, Pid} -> - NState = State#state{dynamics = ?DICT:store(Pid, A, Dynamics)}, + NState = State#state{dynamics = ?DICTS:store(Pid, A, Dynamics)}, {ok, NState}; {ok, Pid, _Extra} -> - NState = State#state{dynamics = ?DICT:store(Pid, A, Dynamics)}, + NState = State#state{dynamics = ?DICTS:store(Pid, A, Dynamics)}, {ok, NState}; {error, Error} -> - NState = State#state{dynamics = ?DICT:store(restarting(OldPid), A, + NState = State#state{dynamics = ?DICTS:store(restarting(OldPid), A, Dynamics)}, report_error(start_error, Error, Child, State#state.name), {try_again, NState} @@ -977,7 +981,7 @@ terminate_dynamic_children(Child, Dynamics, SupName) -> wait_dynamic_children(Child, Pids, Sz, TRef, EStack0) end, %% Unroll stacked errors and report them - ?DICT:fold(fun(Reason, Ls, _) -> + ?DICTS:fold(fun(Reason, Ls, _) -> report_error(shutdown_error, Reason, Child#child{pid=Ls}, SupName) end, ok, EStack). @@ -991,22 +995,22 @@ monitor_dynamic_children(#child{restart_type=temporary}, Dynamics) -> {error, normal} -> {Pids, EStack}; {error, Reason} -> - {Pids, ?DICT:append(Reason, P, EStack)} + {Pids, ?DICTS:append(Reason, P, EStack)} end - end, {?SETS:new(), ?DICT:new()}, Dynamics); + end, {?SETS:new(), ?DICTS:new()}, Dynamics); monitor_dynamic_children(#child{restart_type=RType}, Dynamics) -> - ?DICT:fold(fun(P, _, {Pids, EStack}) when is_pid(P) -> + ?DICTS:fold(fun(P, _, {Pids, EStack}) when is_pid(P) -> case monitor_child(P) of ok -> {?SETS:add_element(P, Pids), EStack}; {error, normal} when RType =/= permanent -> {Pids, EStack}; {error, Reason} -> - {Pids, ?DICT:append(Reason, P, EStack)} + {Pids, ?DICTS:append(Reason, P, EStack)} end; (?restarting(_), _, {Pids, EStack}) -> {Pids, EStack} - end, {?SETS:new(), ?DICT:new()}, Dynamics). + end, {?SETS:new(), ?DICTS:new()}, Dynamics). wait_dynamic_children(_Child, _Pids, 0, undefined, EStack) -> @@ -1030,7 +1034,7 @@ wait_dynamic_children(#child{shutdown=brutal_kill} = Child, Pids, Sz, {'DOWN', _MRef, process, Pid, Reason} -> wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1, - TRef, ?DICT:append(Reason, Pid, EStack)) + TRef, ?DICTS:append(Reason, Pid, EStack)) end; wait_dynamic_children(#child{restart_type=RType} = Child, Pids, Sz, TRef, EStack) -> @@ -1045,7 +1049,7 @@ wait_dynamic_children(#child{restart_type=RType} = Child, Pids, Sz, {'DOWN', _MRef, process, Pid, Reason} -> wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1, - TRef, ?DICT:append(Reason, Pid, EStack)); + TRef, ?DICTS:append(Reason, Pid, EStack)); {timeout, TRef, kill} -> ?SETS:fold(fun(P, _) -> exit(P, kill) end, ok, Pids), @@ -1070,12 +1074,12 @@ save_child(Child, #state{children = Children} = State) -> save_dynamic_child(temporary, Pid, _, #state{dynamics = Dynamics} = State) -> State#state{dynamics = ?SETS:add_element(Pid, dynamics_db(temporary, Dynamics))}; save_dynamic_child(RestartType, Pid, Args, #state{dynamics = Dynamics} = State) -> - State#state{dynamics = ?DICT:store(Pid, Args, dynamics_db(RestartType, Dynamics))}. + State#state{dynamics = ?DICTS:store(Pid, Args, dynamics_db(RestartType, Dynamics))}. dynamics_db(temporary, undefined) -> ?SETS:new(); dynamics_db(_, undefined) -> - ?DICT:new(); + ?DICTS:new(); dynamics_db(_,Dynamics) -> Dynamics. @@ -1084,14 +1088,14 @@ dynamic_child_args(Pid, Dynamics) -> true -> {ok, undefined}; false -> - ?DICT:find(Pid, Dynamics) + ?DICTS:find(Pid, Dynamics) end. state_del_child(#child{pid = Pid, restart_type = temporary}, State) when ?is_simple(State) -> NDynamics = ?SETS:del_element(Pid, dynamics_db(temporary, State#state.dynamics)), State#state{dynamics = NDynamics}; state_del_child(#child{pid = Pid, restart_type = RType}, State) when ?is_simple(State) -> - NDynamics = ?DICT:erase(Pid, dynamics_db(RType, State#state.dynamics)), + NDynamics = ?DICTS:erase(Pid, dynamics_db(RType, State#state.dynamics)), State#state{dynamics = NDynamics}; state_del_child(Child, State) -> NChildren = del_child(Child#child.name, State#state.children), @@ -1154,7 +1158,7 @@ is_dynamic_pid(Pid, Dynamics) -> true -> ?SETS:is_element(Pid, Dynamics); false -> - ?DICT:is_key(Pid, Dynamics) + ?DICTS:is_key(Pid, Dynamics) end. replace_child(Child, State) -> diff --git a/lib/stdlib/src/supervisor_bridge.erl b/lib/stdlib/src/supervisor_bridge.erl index e8405ab9a4..ff4502f0b9 100644 --- a/lib/stdlib/src/supervisor_bridge.erl +++ b/lib/stdlib/src/supervisor_bridge.erl @@ -101,7 +101,16 @@ handle_cast(_, State) -> {noreply, State}. handle_info({'EXIT', Pid, Reason}, State) when State#state.pid =:= Pid -> - report_error(child_terminated, Reason, State), + case Reason of + normal -> + ok; + shutdown -> + ok; + {shutdown, _Term} -> + ok; + _ -> + report_error(child_terminated, Reason, State) + end, {stop, Reason, State#state{pid = undefined}}; handle_info(_, State) -> {noreply, State}. |