summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBjörn Gustavsson <bjorn@erlang.org>2019-09-15 06:11:00 +0200
committerBjörn Gustavsson <bjorn@erlang.org>2019-09-20 10:06:39 +0200
commit1b325a756b0f90bcf2d29706effd65103523d635 (patch)
tree235ffbe3517f202527a54bec63aeb0380a6f3f23 /lib
parent39096dc64590ea39d13cc9bcb52bc5c7240a3c69 (diff)
downloaderlang-1b325a756b0f90bcf2d29706effd65103523d635.tar.gz
Eliminate the Kernel Erlang records for atomic literals
The `v3_kernel` pass still uses the records `#k_atom{}`, `#k_float{}`, `#k_int{}`, and `#k_nil{}` to represent atomic literals. That made sense in ancient times before the introduction of literals. Since both Core Erlang and SSA code use a single type of record for representing all literals (`#c_literal{}` and `#c_kernel{}`, respectively), using `#k_literal{}` to represent all literals in Kernel Erlang will simplify things.
Diffstat (limited to 'lib')
-rw-r--r--lib/compiler/src/beam_kernel_to_ssa.erl40
-rw-r--r--lib/compiler/src/v3_kernel.erl193
-rw-r--r--lib/compiler/src/v3_kernel.hrl6
-rw-r--r--lib/compiler/src/v3_kernel_pp.erl17
4 files changed, 98 insertions, 158 deletions
diff --git a/lib/compiler/src/beam_kernel_to_ssa.erl b/lib/compiler/src/beam_kernel_to_ssa.erl
index 3753a8925e..cb1b337468 100644
--- a/lib/compiler/src/beam_kernel_to_ssa.erl
+++ b/lib/compiler/src/beam_kernel_to_ssa.erl
@@ -266,7 +266,7 @@ select_cons(#k_val_clause{val=#k_cons{hd=Hd,tl=Tl},body=B},
{Is,St} = make_cond_branch(is_nonempty_list, [Src], Tf, St2),
{Is ++ Eis ++ Bis,St}.
-select_nil(#k_val_clause{val=#k_nil{},body=B}, V, Tf, Vf, St0) ->
+select_nil(#k_val_clause{val=#k_literal{val=[]},body=B}, V, Tf, Vf, St0) ->
{Bis,St1} = match_cg(B, Vf, St0),
Src = ssa_arg(V, St1),
{Is,St} = make_cond_branch({bif,'=:='}, [Src,#b_literal{val=[]}], Tf, St1),
@@ -404,12 +404,12 @@ select_extract_bin(#k_var{name=Hd}, Size0, Unit, Type, Flags, Vf,
Size = ssa_arg(Size0, St0),
build_bs_instr(Anno, Type, Vf, Ctx, Size, Unit, Flags, Dst, St1).
-select_extract_int(#k_var{name=Tl}, 0, #k_int{val=0}, _U, _Fs, _Vf,
+select_extract_int(#k_var{name=Tl}, 0, #k_literal{val=0}, _U, _Fs, _Vf,
Ctx, St0) ->
St = set_ssa_var(Tl, Ctx, St0),
{[],St};
-select_extract_int(#k_var{name=Tl}, Val, #k_int{val=Sz}, U, Fs, Vf,
- Ctx, St0) ->
+select_extract_int(#k_var{name=Tl}, Val, #k_literal{val=Sz}, U, Fs, Vf,
+ Ctx, St0) when is_integer(Sz) ->
{Dst,St1} = new_ssa_var(Tl, St0),
Bits = U*Sz,
Bin = case member(big, Fs) of
@@ -445,13 +445,7 @@ select_val(#k_val_clause{val=#k_tuple{es=Es},body=B}, V, Vf, St0) ->
{Eis,St1} = select_extract_tuple(V, Es, St0),
{Bis,St2} = match_cg(B, Vf, St1),
{length(Es),Eis ++ Bis,St2};
-select_val(#k_val_clause{val=Val0,body=B}, _V, Vf, St0) ->
- Val = case Val0 of
- #k_atom{val=Lit} -> Lit;
- #k_float{val=Lit} -> Lit;
- #k_int{val=Lit} -> Lit;
- #k_literal{val=Lit} -> Lit
- end,
+select_val(#k_val_clause{val=#k_literal{val=Val},body=B}, _V, Vf, St0) ->
{Bis,St1} = match_cg(B, Vf, St0),
{Val,Bis,St1}.
@@ -530,7 +524,7 @@ guard_clause_cg(#k_guard_clause{guard=G,body=B}, Fail, St0) ->
guard_cg(#k_protected{arg=Ts,ret=Rs,inner=Inner}, Fail, St) ->
protected_cg(Ts, Rs, Inner, Fail, St);
guard_cg(#k_test{op=Test0,args=As}, Fail, St0) ->
- #k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=Test}} = Test0,
+ #k_remote{mod=#k_literal{val=erlang},name=#k_literal{val=Test}} = Test0,
test_cg(Test, false, As, Fail, St0);
guard_cg(#k_seq{arg=Arg,body=Body}, Fail, St0) ->
{ArgIs,St1} = guard_cg(Arg, Fail, St0),
@@ -646,8 +640,8 @@ call_cg(Func0, As, [#k_var{name=R}|MoreRs]=Rs, Le, St0) ->
%% Inside a guard. The only allowed function call is to
%% erlang:error/1,2. We will generate a branch to the
%% failure branch.
- #k_remote{mod=#k_atom{val=erlang},
- name=#k_atom{val=error}} = Func0, %Assertion.
+ #k_remote{mod=#k_literal{val=erlang},
+ name=#k_literal{val=error}} = Func0, %Assertion.
[#k_var{name=DestVar}] = Rs,
St = set_ssa_var(DestVar, #b_literal{val=unused}, St0),
{[make_uncond_branch(Fail),#cg_unreachable{}],St};
@@ -694,20 +688,18 @@ call_target(Func, As, St) ->
bif_cg(#k_bif{op=#k_internal{name=Name},args=As,ret=Rs}, Le, St) ->
internal_cg(Name, As, Rs, Le, St);
-bif_cg(#k_bif{op=#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=Name}},
+bif_cg(#k_bif{op=#k_remote{mod=#k_literal{val=erlang},name=#k_literal{val=Name}},
args=As,ret=Rs}, Le, St) ->
bif_cg(Name, As, Rs, Le, St).
%% internal_cg(Bif, [Arg], [Ret], Le, State) ->
%% {[Ainstr],State}.
-internal_cg(make_fun, [Name0,Arity0|As], Rs, _Le, St0) ->
- #k_atom{val=Name} = Name0,
- #k_int{val=Arity} = Arity0,
+internal_cg(make_fun, As, Rs, _Le, St0) ->
[#k_var{name=Dst0}] = Rs,
{Dst,St} = new_ssa_var(Dst0, St0),
- Args = ssa_args(As, St),
- Local = #b_local{name=#b_literal{val=Name},arity=Arity},
+ [Name,#b_literal{val=Arity}|Args] = ssa_args(As, St),
+ Local = #b_local{name=Name,arity=Arity},
MakeFun = #b_set{op=make_fun,dst=Dst,args=[Local|Args]},
{[MakeFun],St};
internal_cg(bs_init_writable=I, As, [#k_var{name=Dst0}], _Le, St0) ->
@@ -808,7 +800,7 @@ cg_recv_mesg(#k_var{name=R}, Rm, Tl, Le, St0) ->
%% cg_recv_wait(Te, Tes, St) -> {[Ainstr],St}.
-cg_recv_wait(#k_int{val=0}, Es, St0) ->
+cg_recv_wait(#k_literal{val=0}, Es, St0) ->
{Tis,St} = cg(Es, St0),
{[#b_set{op=timeout}|Tis],St};
cg_recv_wait(Te, Es, St0) ->
@@ -1141,11 +1133,7 @@ ssa_args(As, St) ->
[ssa_arg(A, St) || A <- As].
ssa_arg(#k_var{name=V}, #cg{vars=Vars}) -> maps:get(V, Vars);
-ssa_arg(#k_literal{val=V}, _) -> #b_literal{val=V};
-ssa_arg(#k_atom{val=V}, _) -> #b_literal{val=V};
-ssa_arg(#k_float{val=V}, _) -> #b_literal{val=V};
-ssa_arg(#k_int{val=V}, _) -> #b_literal{val=V};
-ssa_arg(#k_nil{}, _) -> #b_literal{val=[]}.
+ssa_arg(#k_literal{val=V}, _) -> #b_literal{val=V}.
new_ssa_vars(Vs, St) ->
mapfoldl(fun(#k_var{name=V}, S) ->
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index 42e36c188c..bab19c219b 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -219,8 +219,9 @@ wrap_guard(Core, St0) ->
%% Must enter try blocks and isets and find the last Kexpr in them.
%% This must end in a recognised BEAM test!
-gexpr_test(#k_bif{anno=A,op=#k_remote{mod=#k_atom{val=erlang},
- name=#k_atom{val=F},arity=Ar}=Op,
+gexpr_test(#k_bif{anno=A,
+ op=#k_remote{mod=#k_literal{val=erlang},
+ name=#k_literal{val=F},arity=Ar}=Op,
args=Kargs}=Ke, St) ->
%% Either convert to test if ok, or add test.
%% At this stage, erlang:float/1 is not a type test. (It should
@@ -231,7 +232,7 @@ gexpr_test(#k_bif{anno=A,op=#k_remote{mod=#k_atom{val=erlang},
false -> gexpr_test_add(Ke, St) %Add equality test
end;
gexpr_test(#k_try{arg=B0,vars=[#k_var{name=X}],body=#k_var{name=X},
- handler=#k_atom{val=false}}=Try, St0) ->
+ handler=#k_literal{val=false}}=Try, St0) ->
{B,St} = gexpr_test(B0, St0),
%%ok = io:fwrite("~w: ~p~n", [?LINE,{B0,B}]),
{Try#k_try{arg=B},St};
@@ -241,12 +242,12 @@ gexpr_test(#iset{body=B0}=Iset, St0) ->
gexpr_test(Ke, St) -> gexpr_test_add(Ke, St). %Add equality test
gexpr_test_add(Ke, St0) ->
- Test = #k_remote{mod=#k_atom{val='erlang'},
- name=#k_atom{val='=:='},
+ Test = #k_remote{mod=#k_literal{val='erlang'},
+ name=#k_literal{val='=:='},
arity=2},
{Ae,Ap,St1} = force_atomic(Ke, St0),
{pre_seq(Ap, #k_test{anno=get_kanno(Ke),
- op=Test,args=[Ae,#k_atom{val='true'}]}),St1}.
+ op=Test,args=[Ae,#k_literal{val='true'}]}),St1}.
%% expr(Cexpr, Sub, State) -> {Kexpr,[PreKexpr],State}.
%% Convert a Core expression, flattening it at the same time.
@@ -275,19 +276,7 @@ expr(#c_var{anno=A0,name={Name,Arity}}=Fname, Sub, St) ->
expr(#c_var{anno=A,name=V}, Sub, St) ->
{#k_var{anno=A,name=get_vsub(V, Sub)},[],St};
expr(#c_literal{anno=A,val=V}, _Sub, St) ->
- Klit = case V of
- [] ->
- #k_nil{anno=A};
- V when is_integer(V) ->
- #k_int{anno=A,val=V};
- V when is_float(V) ->
- #k_float{anno=A,val=V};
- V when is_atom(V) ->
- #k_atom{anno=A,val=V};
- _ ->
- #k_literal{anno=A,val=V}
- end,
- {Klit,[],St};
+ {#k_literal{anno=A,val=V},[],St};
expr(#c_cons{anno=A,hd=Ch,tl=Ct}, Sub, St0) ->
%% Do cons in two steps, first the expressions left to right, then
%% any remaining literals right to left.
@@ -398,10 +387,12 @@ expr(#c_apply{anno=A,op=Cop,args=Cargs}, Sub, St) ->
expr(#c_call{anno=A,module=#c_literal{val=erlang},name=#c_literal{val=is_record},
args=[_,Tag,Sz]=Args0}, Sub, St0) ->
{Args,Ap,St} = atomic_list(Args0, Sub, St0),
- Remote = #k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=is_record},arity=3},
+ Remote = #k_remote{mod=#k_literal{val=erlang},
+ name=#k_literal{val=is_record},
+ arity=3},
case {Tag,Sz} of
{#c_literal{val=Atom},#c_literal{val=Int}}
- when is_atom(Atom), is_integer(Int) ->
+ when is_atom(Atom), is_integer(Int) ->
%% Tag and size are literals. Make it a BIF, which will actually
%% be expanded out in a later pass.
{#k_bif{anno=A,op=Remote,args=Args},Ap,St};
@@ -446,8 +437,8 @@ expr(#c_primop{anno=A,name=#c_literal{val=match_fail},args=Cargs0}, Sub, St0) ->
Cargs = translate_match_fail(Cargs0, Sub, A, St0),
{Kargs,Ap,St} = atomic_list(Cargs, Sub, St0),
Ar = length(Cargs),
- Call = #k_call{anno=A,op=#k_remote{mod=#k_atom{val=erlang},
- name=#k_atom{val=error},
+ Call = #k_call{anno=A,op=#k_remote{mod=#k_literal{val=erlang},
+ name=#k_literal{val=error},
arity=Ar},args=Kargs},
{Call,Ap,St};
expr(#c_primop{anno=A,name=#c_literal{val=N},args=Cargs}, Sub, St0) ->
@@ -597,14 +588,9 @@ map_remove_dup_keys([{exact,K0,V}|Es0],Used0) ->
map_remove_dup_keys(Es0, Used1);
map_remove_dup_keys([], Used) -> Used.
-%% Be explicit instead of using set_kanno(K, []).
+%% Clean a map key from annotations.
map_key_clean(#k_var{name=V}) -> {var,V};
-map_key_clean(#k_literal{val=V}) -> {lit,V};
-map_key_clean(#k_int{val=V}) -> {lit,V};
-map_key_clean(#k_float{val=V}) -> {lit,V};
-map_key_clean(#k_atom{val=V}) -> {lit,V};
-map_key_clean(#k_nil{}) -> {lit,[]}.
-
+map_key_clean(#k_literal{val=V}) -> {lit,V}.
%% call_type(Module, Function, Arity) -> call | bif | apply | error.
%% Classify the call.
@@ -694,10 +680,13 @@ atomic_bin([#c_bitstr{anno=A,val=E0,size=S0,unit=U0,type=T,flags=Fs0}|Es0],
atomic_bin([], _Sub, St) -> {#k_bin_end{},[],St}.
validate_bin_element_size(#k_var{}) -> ok;
-validate_bin_element_size(#k_int{val=V}) when V >= 0 -> ok;
-validate_bin_element_size(#k_atom{val=all}) -> ok;
-validate_bin_element_size(#k_atom{val=undefined}) -> ok;
-validate_bin_element_size(_) -> throw(bad_element_size).
+validate_bin_element_size(#k_literal{val=Val}) ->
+ case Val of
+ all -> ok;
+ undefined -> ok;
+ _ when is_integer(Val), Val >= 0 -> ok;
+ _ -> throw(bad_element_size)
+ end.
%% atomic_list([Cexpr], Sub, State) -> {[Kexpr],[PreKexpr],State}.
@@ -708,15 +697,11 @@ atomic_list(Ces, Sub, St) ->
end, {[],[],St}, Ces).
%% is_atomic(Kexpr) -> boolean().
-%% Is a Kexpr atomic? Strings are NOT considered atomic!
+%% Is a Kexpr atomic?
is_atomic(#k_literal{}) -> true;
-is_atomic(#k_int{}) -> true;
-is_atomic(#k_float{}) -> true;
-is_atomic(#k_atom{}) -> true;
-%%is_atomic(#k_char{}) -> true; %No characters
-is_atomic(#k_nil{}) -> true;
is_atomic(#k_var{}) -> true;
+%%is_atomic(#k_char{}) -> true; %No characters
is_atomic(_) -> false.
%% variable(Cexpr, Sub, State) -> {Kvar,[PreKexpr],State}.
@@ -804,15 +789,14 @@ pattern_bin_1([#c_bitstr{anno=A,val=E0,size=S0,unit=U,type=T,flags=Fs}|Es0],
Isub0, Osub0, St0) ->
{S1,[],St1} = expr(S0, Isub0, St0),
S = case S1 of
- #k_int{} -> S1;
#k_var{} -> S1;
- #k_atom{} -> S1;
+ #k_literal{val=Val} when is_integer(Val); is_atom(Val) -> S1;
_ ->
%% Bad size (coming from an optimization or Core Erlang
%% source code) - replace it with a known atom because
%% a literal or bit syntax construction can cause further
%% problems.
- #k_atom{val=bad_size}
+ #k_literal{val=bad_size}
end,
U0 = cerl:concrete(U),
Fs0 = cerl:concrete(Fs),
@@ -835,7 +819,8 @@ pattern_bin_1([], Isub, Osub, St) -> {#k_bin_end{},{Isub,Osub},St}.
%% more literals and group more clauses. Those integers may be "squeezed"
%% later into the largest integer possible.
%%
-build_bin_seg(A, #k_int{val=Bits} = Sz, U, integer=Type, [unsigned,big]=Flags, #k_literal{val=Int}=Seg, Next) ->
+build_bin_seg(A, #k_literal{val=Bits} = Sz, U, integer=Type,
+ [unsigned,big]=Flags, #k_literal{val=Int}=Seg, Next) ->
Size = Bits * U,
case integer_fits_and_is_expandable(Int, Size) of
true -> build_bin_seg_integer_recur(A, Size, Int, Next);
@@ -859,7 +844,7 @@ build_bin_seg_integer_recur(A, Bits, Val, Next) ->
build_bin_seg_integer(A, Bits, Val, Next).
build_bin_seg_integer(A, Bits, Val, Next) ->
- Sz = #k_int{anno=A,val=Bits},
+ Sz = #k_literal{anno=A,val=Bits},
Seg = #k_literal{anno=A,val=Val},
#k_bin_seg{anno=A,size=Sz,unit=1,type=integer,flags=[unsigned,big],seg=Seg,next=Next}.
@@ -1052,11 +1037,6 @@ foldr2(_, Acc, [], []) -> Acc.
kmatch(Us, Ccs, Sub, St0) ->
{Cs,St1} = match_pre(Ccs, Sub, St0), %Convert clauses
Def = fail,
-%% Def = #k_call{anno=[compiler_generated],
-%% op=#k_remote{mod=#k_atom{val=erlang},
-%% name=#k_atom{val=exit},
-%% arity=1},
-%% args=[#k_atom{val=kernel_match_error}]},
match(Us, Cs, Def, St1). %Do the match.
%% match_pre([Cclause], Sub, State) -> {[Clause],State}.
@@ -1246,31 +1226,27 @@ expand_pat_lit_clause(#iclause{pats=[#k_literal{anno=A,val=Val}|Ps]}=C) ->
expand_pat_lit_clause(C) -> C.
expand_pat_lit([H|T], A) ->
- #k_cons{anno=A,hd=literal(H, A),tl=literal(T, A)};
+ #k_cons{anno=A,hd=#k_literal{anno=A,val=H},tl=#k_literal{anno=A,val=T}};
expand_pat_lit(Tuple, A) when is_tuple(Tuple) ->
- #k_tuple{anno=A,es=[literal(E, A) || E <- tuple_to_list(Tuple)]};
+ #k_tuple{anno=A,es=[#k_literal{anno=A,val=E} || E <- tuple_to_list(Tuple)]};
expand_pat_lit(Lit, A) ->
- literal(Lit, A).
-
-literal([], A) ->
- #k_nil{anno=A};
-literal(Val, A) when is_integer(Val) ->
- #k_int{anno=A,val=Val};
-literal(Val, A) when is_float(Val) ->
- #k_float{anno=A,val=Val};
-literal(Val, A) when is_atom(Val) ->
- #k_atom{anno=A,val=Val};
-literal(Val, A) when is_list(Val); is_tuple(Val) ->
- #k_literal{anno=A,val=Val}.
+ #k_literal{anno=A,val=Lit}.
%% opt_singled_valued([{Type,Clauses}]) -> [{Type,Clauses}].
-%% If a type only has one clause and if the pattern is literal,
-%% the matching can be done more efficiently by directly comparing
-%% with the literal (that is especially true for binaries).
+%% If a type only has one clause and if the pattern is a complex
+%% literal, the matching can be done more efficiently by directly
+%% comparing with the literal (that is especially true for binaries).
+%%
+%% It is important not to do this transformation for atomic literals
+%% (such as `[]`), since that would cause the test for an emtpy list
+%% to be executed before the test for a nonempty list.
opt_single_valued(Ttcs) ->
opt_single_valued(Ttcs, [], []).
+opt_single_valued([{_,[#iclause{pats=[#k_literal{}|_]}]}=Ttc|Ttcs], TtcAcc, LitAcc) ->
+ %% This is an atomic literal.
+ opt_single_valued(Ttcs, [Ttc|TtcAcc], LitAcc);
opt_single_valued([{_,[#iclause{pats=[P0|Ps]}=Tc]}=Ttc|Ttcs], TtcAcc, LitAcc) ->
try combine_lit_pat(P0) of
P ->
@@ -1300,26 +1276,13 @@ opt_single_valued([], TtcAcc, LitAcc) ->
combine_lit_pat(#ialias{pat=Pat0}=Alias) ->
Pat = combine_lit_pat(Pat0),
Alias#ialias{pat=Pat};
+combine_lit_pat(#k_literal{}) ->
+ %% This is an atomic literal. Rewriting would be a pessimization,
+ %% especially for `[]`.
+ throw(not_possible);
combine_lit_pat(Pat) ->
- case do_combine_lit_pat(Pat) of
- #k_literal{val=Val} when is_atom(Val) ->
- throw(not_possible);
- #k_literal{val=Val} when is_number(Val) ->
- throw(not_possible);
- #k_literal{val=[]} ->
- throw(not_possible);
- #k_literal{}=Lit ->
- Lit
- end.
+ do_combine_lit_pat(Pat).
-do_combine_lit_pat(#k_atom{anno=A,val=Val}) ->
- #k_literal{anno=A,val=Val};
-do_combine_lit_pat(#k_float{anno=A,val=Val}) ->
- #k_literal{anno=A,val=Val};
-do_combine_lit_pat(#k_int{anno=A,val=Val}) ->
- #k_literal{anno=A,val=Val};
-do_combine_lit_pat(#k_nil{anno=A}) ->
- #k_literal{anno=A,val=[]};
do_combine_lit_pat(#k_binary{anno=A,segs=Segs}) ->
Bin = combine_bin_segs(Segs),
#k_literal{anno=A,val=Bin};
@@ -1338,7 +1301,7 @@ do_combine_lit_pat(#k_tuple{anno=A,es=Es0}) ->
do_combine_lit_pat(_) ->
throw(not_possible).
-combine_bin_segs(#k_bin_seg{size=#k_int{val=8},unit=1,type=integer,
+combine_bin_segs(#k_bin_seg{size=#k_literal{val=8},unit=1,type=integer,
flags=[unsigned,big],seg=#k_literal{val=Int},next=Next})
when is_integer(Int), 0 =< Int, Int =< 255 ->
<<Int,(combine_bin_segs(Next))/bits>>;
@@ -1409,9 +1372,9 @@ handle_bin_con_not_possible([]) -> [].
%% exception is thrown.
select_bin_int([#iclause{pats=[#k_bin_seg{anno=A,type=integer,
- size=#k_int{val=Bits0}=Sz,unit=U,
- flags=Fl,seg=#k_literal{val=Val},
- next=N}|Ps]}=C|Cs0]) ->
+ size=#k_literal{val=Bits0}=Sz,unit=U,
+ flags=Fl,seg=#k_literal{val=Val},
+ next=N}|Ps]}=C|Cs0]) when is_integer(Bits0) ->
Bits = U * Bits0,
if
Bits > ?EXPAND_MAX_SIZE_SEGMENT -> throw(not_possible); %Expands the code too much.
@@ -1428,7 +1391,7 @@ select_bin_int([#iclause{pats=[#k_bin_seg{anno=A,type=integer,
select_bin_int(_) -> throw(not_possible).
select_bin_int_1([#iclause{pats=[#k_bin_seg{anno=A,type=integer,
- size=#k_int{val=Bits0}=Sz,
+ size=#k_literal{val=Bits0}=Sz,
unit=U,
flags=Fl,seg=#k_literal{val=Val},
next=N}|Ps]}=C|Cs],
@@ -1599,7 +1562,7 @@ get_match(#k_cons{}, St0) ->
get_match(#k_binary{}, St0) ->
{[V]=Mes,St1} = new_vars(1, St0),
{#k_binary{segs=V},Mes,St1};
-get_match(#k_bin_seg{size=#k_atom{val=all},next={k_bin_end,[]}}=Seg, St0) ->
+get_match(#k_bin_seg{size=#k_literal{val=all},next={k_bin_end,[]}}=Seg, St0) ->
{[S,N0],St1} = new_vars(2, St0),
N = set_kanno(N0, [no_usage]),
{Seg#k_bin_seg{seg=S,next=N},[S],St1};
@@ -1630,7 +1593,7 @@ new_clauses(Cs0, U, St) ->
#k_cons{hd=H,tl=T} -> [H,T|As];
#k_tuple{es=Es} -> Es ++ As;
#k_binary{segs=E} -> [E|As];
- #k_bin_seg{size=#k_atom{val=all},
+ #k_bin_seg{size=#k_literal{val=all},
seg=S,next={k_bin_end,[]}} ->
[S|As];
#k_bin_seg{seg=S,next=N} ->
@@ -1705,15 +1668,17 @@ squeeze_clauses_by_bin_integer_count([Clause | Clauses], N, Count, GroupAcc, Acc
clause_count_bin_integer_segments(#iclause{pats=[#k_bin_seg{seg=#k_literal{}} = BinSeg | _]}) ->
count_bin_integer_segments(BinSeg, 0);
-clause_count_bin_integer_segments(#iclause{pats=[#k_bin_seg{size=#k_int{val=Size},unit=Unit,
- type=integer,flags=[unsigned,big], seg=#k_var{}} | _]})
- when ((Size * Unit) rem 8) =:= 0 ->
+clause_count_bin_integer_segments(#iclause{pats=[#k_bin_seg{size=#k_literal{val=Size},unit=Unit,
+ type=integer,flags=[unsigned,big],
+ seg=#k_var{}} | _]})
+ when ((Size * Unit) rem 8) =:= 0 ->
{variadic, (Size * Unit) div 8};
clause_count_bin_integer_segments(_) ->
error.
-count_bin_integer_segments(#k_bin_seg{size=#k_int{val=8},unit=1,type=integer,flags=[unsigned,big],
- seg=#k_literal{val=Int},next=Next}, Count) when is_integer(Int), 0 =< Int, Int =< 255 ->
+count_bin_integer_segments(#k_bin_seg{size=#k_literal{val=8},unit=1,type=integer,flags=[unsigned,big],
+ seg=#k_literal{val=Int},next=Next}, Count)
+ when is_integer(Int), 0 =< Int, Int =< 255 ->
count_bin_integer_segments(Next, Count + 1);
count_bin_integer_segments(_, Count) when Count > 0 ->
{literal, Count};
@@ -1740,7 +1705,7 @@ squeeze_clauses([], _Size) ->
[].
squeeze_segments(#k_bin_seg{size=Sz, seg=#k_literal{val=Val}=Lit} = BinSeg, Acc, Size, 1) ->
- BinSeg#k_bin_seg{size=Sz#k_int{val=Size + 8}, seg=Lit#k_literal{val=(Acc bsl 8) bor Val}};
+ BinSeg#k_bin_seg{size=Sz#k_literal{val=Size + 8}, seg=Lit#k_literal{val=(Acc bsl 8) bor Val}};
squeeze_segments(#k_bin_seg{seg=#k_literal{val=Val},next=Next}, Acc, Size, Count) ->
squeeze_segments(Next, (Acc bsl 8) bor Val, Size + 8, Count - 1).
@@ -1805,26 +1770,26 @@ arg_alias(_Con) -> [].
arg_con(Arg) ->
case arg_arg(Arg) of
- #k_literal{} -> k_literal;
- #k_int{} -> k_int;
- #k_float{} -> k_float;
- #k_atom{} -> k_atom;
- #k_nil{} -> k_nil;
- #k_cons{} -> k_cons;
+ #k_cons{} -> k_cons;
#k_tuple{} -> k_tuple;
#k_map{} -> k_map;
#k_binary{} -> k_binary;
#k_bin_end{} -> k_bin_end;
#k_bin_seg{} -> k_bin_seg;
- #k_var{} -> k_var
+ #k_var{} -> k_var;
+ #k_literal{val=[]} -> k_nil;
+ #k_literal{val=Val} ->
+ if
+ is_atom(Val) -> k_atom;
+ is_integer(Val) -> k_int;
+ is_float(Val) -> k_float;
+ true -> k_literal
+ end
end.
arg_val(Arg, C) ->
case arg_arg(Arg) of
#k_literal{val=Lit} -> Lit;
- #k_int{val=I} -> I;
- #k_float{val=F} -> F;
- #k_atom{val=A} -> A;
#k_tuple{es=Es} -> length(Es);
#k_bin_seg{size=S,unit=U,type=T,flags=Fs} ->
case S of
@@ -2005,7 +1970,7 @@ uexpr(#k_try{anno=A,arg=A0,vars=Vs,body=B0,evars=Evs,handler=H0},
case is_in_guard(St0) of
true ->
{[#k_var{name=X}],#k_var{name=X}} = {Vs,B0}, %Assertion.
- #k_atom{val=false} = H0, %Assertion.
+ #k_literal{val=false} = H0, %Assertion.
{Avs,St1} = new_vars(length(Rs0), St0),
{A1,Bu,St} = uexpr(A0, {break,Avs}, St1),
{#k_protected{anno=A,arg=A1,ret=Rs0,inner=Avs},Bu,St};
@@ -2053,7 +2018,7 @@ uexpr(#ifun{anno=A,vars=Vs,body=B0}, {break,Rs}, St0) ->
Fun = make_fdef(A, Fname, Arity, Vs++Fvs, B1),
{#k_bif{anno=A,
op=#k_internal{name=make_fun,arity=length(Free)+2},
- args=[#k_atom{val=Fname},#k_int{val=Arity}|Fvs],
+ args=[#k_literal{val=Fname},#k_literal{val=Arity}|Fvs],
ret=Rs},
Free,add_local_function(Fun, St)};
uexpr(Lit, {break,Rs0}, St0) ->
@@ -2188,11 +2153,7 @@ op_vars(Atomic) -> lit_vars(Atomic).
%% Return the variables in a literal.
lit_vars(#k_var{name=N}) -> [N];
-lit_vars(#k_int{}) -> [];
-lit_vars(#k_float{}) -> [];
-lit_vars(#k_atom{}) -> [];
%%lit_vars(#k_char{}) -> [];
-lit_vars(#k_nil{}) -> [];
lit_vars(#k_cons{hd=H,tl=T}) ->
union(lit_vars(H), lit_vars(T));
lit_vars(#k_map{var=Var,es=Es}) ->
@@ -2218,10 +2179,6 @@ lit_list_vars(Ps) ->
pat_vars(#k_var{name=N}) -> {[],[N]};
%%pat_vars(#k_char{}) -> {[],[]};
pat_vars(#k_literal{}) -> {[],[]};
-pat_vars(#k_int{}) -> {[],[]};
-pat_vars(#k_float{}) -> {[],[]};
-pat_vars(#k_atom{}) -> {[],[]};
-pat_vars(#k_nil{}) -> {[],[]};
pat_vars(#k_cons{hd=H,tl=T}) ->
pat_list_vars([H,T]);
pat_vars(#k_binary{segs=V}) ->
diff --git a/lib/compiler/src/v3_kernel.hrl b/lib/compiler/src/v3_kernel.hrl
index b68cd61b19..f2d90d0c99 100644
--- a/lib/compiler/src/v3_kernel.hrl
+++ b/lib/compiler/src/v3_kernel.hrl
@@ -27,11 +27,7 @@
%% Literals
%% NO CHARACTERS YET.
%%-record(k_char, {anno=[],val}).
--record(k_literal, {anno=[],val}). %Only used for complex literals.
--record(k_int, {anno=[],val}).
--record(k_float, {anno=[],val}).
--record(k_atom, {anno=[],val}).
--record(k_nil, {anno=[]}).
+-record(k_literal, {anno=[],val}).
-record(k_tuple, {anno=[],es}).
-record(k_map, {anno=[],var=#k_literal{val=#{}},op,es}).
diff --git a/lib/compiler/src/v3_kernel_pp.erl b/lib/compiler/src/v3_kernel_pp.erl
index d99502f571..571d51a59d 100644
--- a/lib/compiler/src/v3_kernel_pp.erl
+++ b/lib/compiler/src/v3_kernel_pp.erl
@@ -81,11 +81,7 @@ format_anno(Anno, Ctxt0, ObjFun) ->
%% format_1(Kexpr, Context) -> string().
-format_1(#k_atom{val=A}, _Ctxt) -> core_atom(A);
%%format_1(#k_char{val=C}, _Ctxt) -> io_lib:write_char(C);
-format_1(#k_float{val=F}, _Ctxt) -> float_to_list(F);
-format_1(#k_int{val=I}, _Ctxt) -> integer_to_list(I);
-format_1(#k_nil{}, _Ctxt) -> "[]";
format_1(#k_var{name=V}, _Ctxt) ->
if is_atom(V) ->
case atom_to_list(V) of
@@ -133,10 +129,13 @@ format_1(#k_bin_seg{next=Next}=S, Ctxt) ->
[format_bin_seg_1(S, Ctxt),
format_bin_seg(Next, ctxt_bump_indent(Ctxt, 2))];
format_1(#k_bin_int{size=Sz,unit=U,flags=Fs,val=Val,next=Next}, Ctxt) ->
- S = #k_bin_seg{size=Sz,unit=U,type=integer,flags=Fs,seg=#k_int{val=Val},next=Next},
+ S = #k_bin_seg{size=Sz,unit=U,type=integer,flags=Fs,
+ seg=#k_literal{val=Val},next=Next},
[format_bin_seg_1(S, Ctxt),
format_bin_seg(Next, ctxt_bump_indent(Ctxt, 2))];
format_1(#k_bin_end{}, _Ctxt) -> "#<>#";
+format_1(#k_literal{val=A}, _Ctxt) when is_atom(A) ->
+ core_atom(A);
format_1(#k_literal{val=Term}, _Ctxt) ->
io_lib:format("~p", [Term]);
format_1(#k_local{name=N,arity=A}, Ctxt) ->
@@ -325,7 +324,7 @@ format_1(#k_fdef{func=F,arity=A,vars=Vs,body=B}, Ctxt) ->
];
format_1(#k_mdef{name=N,exports=Es,attributes=As,body=B}, Ctxt) ->
["module ",
- format(#k_atom{val=N}, ctxt_bump_indent(Ctxt, 7)),
+ format(#k_literal{val=N}, ctxt_bump_indent(Ctxt, 7)),
nl_indent(Ctxt),
"export [",
format_vseq(Es,
@@ -415,17 +414,17 @@ format_fa_pair({F,A}, _Ctxt) -> [core_atom(F),$/,integer_to_list(A)].
%% format_attribute({Name,Val}, Context) -> Txt.
format_attribute({Name,Val}, Ctxt) when is_list(Val) ->
- Txt = format(#k_atom{val=Name}, Ctxt),
+ Txt = format(#k_literal{val=Name}, Ctxt),
Ctxt1 = ctxt_bump_indent(Ctxt, width(Txt,Ctxt)+4),
[Txt," = ",
$[,format_vseq(Val, "", ",", Ctxt1,
fun (A, _C) -> io_lib:write(A) end),$]
];
format_attribute({Name,Val}, Ctxt) ->
- Txt = format(#k_atom{val=Name}, Ctxt),
+ Txt = format(#k_literal{val=Name}, Ctxt),
[Txt," = ",io_lib:write(Val)].
-format_list_tail(#k_nil{anno=[]}, _Ctxt) -> "]";
+format_list_tail(#k_literal{anno=[],val=[]}, _Ctxt) -> "]";
format_list_tail(#k_cons{anno=[],hd=H,tl=T}, Ctxt) ->
Txt = [$,|format(H, Ctxt)],
Ctxt1 = ctxt_bump_indent(Ctxt, width(Txt, Ctxt)),