From d7b6e2ef74c28bc60058b110bdefe5c54d1da058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Fri, 14 Jun 2019 13:30:08 +0200 Subject: compiler: Add common method for literal -> type conversion --- lib/compiler/src/beam_ssa_type.erl | 31 +----------------------------- lib/compiler/src/beam_types.erl | 29 ++++++++++++++++++++++++++++ lib/compiler/src/beam_validator.erl | 38 ++++++++++++------------------------- 3 files changed, 42 insertions(+), 56 deletions(-) (limited to 'lib/compiler') diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl index 79ed0d7885..c348dc68d3 100644 --- a/lib/compiler/src/beam_ssa_type.erl +++ b/lib/compiler/src/beam_ssa_type.erl @@ -1210,36 +1210,7 @@ get_type(#b_var{}=V, Ts) -> #{V:=T} = Ts, T; get_type(#b_literal{val=Val}, _Ts) -> - if - is_atom(Val) -> - beam_types:make_atom(Val); - is_float(Val) -> - float; - is_function(Val) -> - {arity,Arity} = erlang:fun_info(Val, arity), - #t_fun{arity=Arity}; - is_integer(Val) -> - beam_types:make_integer(Val); - is_list(Val), Val =/= [] -> - cons; - is_map(Val) -> - #t_map{}; - Val =:= {} -> - beam_types:make_tuple(0, true); - is_tuple(Val) -> - {Es, _} = foldl(fun(E, {Es0, Index}) -> - Type = get_type(#b_literal{val=E}, #{}), - Es = beam_types:set_element_type(Index, - Type, - Es0), - {Es, Index + 1} - end, {#{}, 1}, tuple_to_list(Val)), - beam_types:make_tuple(tuple_size(Val), true, Es); - Val =:= [] -> - nil; - true -> - any - end. + beam_types:make_type_from_value(Val). %% infer_types(Var, Types, #d{}) -> {SuccTypes,FailTypes} %% Looking at the expression that defines the variable Var, infer diff --git a/lib/compiler/src/beam_types.erl b/lib/compiler/src/beam_types.erl index c3ad594304..07d3c3d3f2 100644 --- a/lib/compiler/src/beam_types.erl +++ b/lib/compiler/src/beam_types.erl @@ -22,6 +22,8 @@ -include("beam_types.hrl"). +-import(lists, [foldl/3]). + -export([meet/1, meet/2, join/1, join/2, subtract/2]). -export([get_singleton_value/1, @@ -31,6 +33,8 @@ -export([get_element_type/2, set_element_type/3]). +-export([make_type_from_value/1]). + -export([make_atom/1, make_boolean/0, make_integer/1, @@ -348,6 +352,31 @@ get_element_type(Index, Es) -> %%% Type constructors %%% +-spec make_type_from_value(term()) -> type(). +make_type_from_value(Value) -> + mtfv_1(Value). + +mtfv_1([]) -> nil; +mtfv_1([_|_]) -> cons; +mtfv_1(A) when is_atom(A) -> #t_atom{elements=[A]}; +mtfv_1(B) when is_binary(B) -> #t_bitstring{unit=8}; +mtfv_1(B) when is_bitstring(B) -> #t_bitstring{}; +mtfv_1(F) when is_float(F) -> float; +mtfv_1(F) when is_function(F) -> + {arity, Arity} = erlang:fun_info(F, arity), + #t_fun{arity=Arity}; +mtfv_1(I) when is_integer(I) -> make_integer(I); +mtfv_1(M) when is_map(M) -> #t_map{}; +mtfv_1(T) when is_tuple(T) -> + {Es,_} = foldl(fun(Val, {Es0, Index}) -> + Type = mtfv_1(Val), + Es = set_element_type(Index, Type, Es0), + {Es, Index + 1} + end, {#{}, 1}, tuple_to_list(T)), + #t_tuple{exact=true,size=tuple_size(T),elements=Es}; +mtfv_1(_Term) -> + any. + -spec make_atom(atom()) -> type(). make_atom(Atom) when is_atom(Atom) -> #t_atom{elements=[Atom]}. diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 8fe7ed8b69..90049b3a25 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -2014,32 +2014,18 @@ is_value_alive(#value_ref{}=Ref, #vst{current=#st{vs=Vs}}) -> is_value_alive(_, _) -> false. -get_literal_type(nil) -> glt_1([]); -get_literal_type({atom,A}) when is_atom(A) -> glt_1(A); -get_literal_type({float,F}) when is_float(F) -> glt_1(F); -get_literal_type({integer,I}) when is_integer(I) -> glt_1(I); -get_literal_type({literal,L}) -> glt_1(L); -get_literal_type(T) -> error({not_literal,T}). - -glt_1([]) -> nil; -glt_1([_|_]) -> cons; -glt_1(A) when is_atom(A) -> #t_atom{elements=[A]}; -glt_1(B) when is_bitstring(B) -> #t_bitstring{}; -glt_1(F) when is_float(F) -> float; -glt_1(F) when is_function(F) -> - {arity, Arity} = erlang:fun_info(F, arity), - #t_fun{arity=Arity}; -glt_1(I) when is_integer(I) -> beam_types:make_integer(I); -glt_1(M) when is_map(M) -> #t_map{}; -glt_1(T) when is_tuple(T) -> - {Es,_} = foldl(fun(Val, {Es0, Index}) -> - Type = glt_1(Val), - Es = beam_types:set_element_type(Index, Type, Es0), - {Es, Index + 1} - end, {#{}, 1}, tuple_to_list(T)), - #t_tuple{exact=true,size=tuple_size(T),elements=Es}; -glt_1(_Term) -> - any. +get_literal_type(nil) -> + beam_types:make_type_from_value([]); +get_literal_type({atom,A}) when is_atom(A) -> + beam_types:make_type_from_value(A); +get_literal_type({float,F}) when is_float(F) -> + beam_types:make_type_from_value(F); +get_literal_type({integer,I}) when is_integer(I) -> + beam_types:make_type_from_value(I); +get_literal_type({literal,L}) -> + beam_types:make_type_from_value(L); +get_literal_type(T) -> + error({not_literal,T}). %%% %%% Branch tracking -- cgit v1.2.3