Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
0143-erl_lint-rename-Bvt-BinVar-variables-for-c...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0143-erl_lint-rename-Bvt-BinVar-variables-for-clarity-and.patch of Package erlang
From bf20eef225ea446198af8575f40ed9388626c6de Mon Sep 17 00:00:00 2001 From: Richard Carlsson <carlsson.richard@gmail.com> Date: Tue, 6 Oct 2020 14:47:14 +0200 Subject: [PATCH 3/3] erl_lint: rename Bvt/BinVar variables for clarity and improve comments --- lib/stdlib/src/erl_lint.erl | 186 +++++++++++++++++++----------------- 1 file changed, 97 insertions(+), 89 deletions(-) diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 94da474b40..5a35087050 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -1585,9 +1585,8 @@ clauses(Cs, St) -> clause({clause,_Line,H,G,B}, St0) -> Vt0 = [], - {Hvt,Binvt,St1} = head(H, Vt0, St0), - %% Cannot ignore BinVt since "binsize variables" may have been used. - Vt1 = vtupdate(Hvt, vtupdate(Binvt, Vt0)), + {Hvt,Hnew,St1} = head(H, Vt0, St0), + Vt1 = vtupdate(Hvt, vtupdate(Hnew, Vt0)), {Gvt,St2} = guard(G, Vt1, St1), Vt2 = vtupdate(Gvt, Vt1), {Bvt,St3} = exprs(B, Vt2, St2), @@ -1595,7 +1594,7 @@ clause({clause,_Line,H,G,B}, St0) -> check_unused_vars(Upd, Vt0, St3). %% head([HeadPattern], VarTable, State) -> -%% {VarTable,BinVarTable,State} +%% {VarTable,NewVars,State} %% Check a patterns in head returning "all" variables. Not updating the %% known variable list will result in multiple error messages/warnings. @@ -1603,21 +1602,23 @@ head(Ps, Vt, St0) -> head(Ps, Vt, Vt, St0). % Old = Vt head([P|Ps], Vt, Old, St0) -> - {Pvt,Bvt1,St1} = pattern(P, Vt, Old, St0), - {Psvt,Bvt2,St2} = head(Ps, Vt, Old, St1), - {vtmerge_pat(Pvt, Psvt),vtmerge_pat(Bvt1,Bvt2),St2}; + {Pvt,Pnew,St1} = pattern(P, Vt, Old, St0), + {Psvt,Psnew,St2} = head(Ps, Vt, Old, St1), + {vtmerge_pat(Pvt, Psvt),vtmerge_pat(Pnew, Psnew),St2}; head([], _Vt, _Env, St) -> {[],[],St}. %% pattern(Pattern, VarTable, Old, State) -> -%% {UpdVarTable,BinVarTable,State}. -%% Check pattern return variables. Old is the set of variables used for -%% deciding whether an occurrence is a binding occurrence or a use, and -%% VarTable is the set of variables used for arguments to binary -%% patterns. UpdVarTable is updated when same variable in VarTable is -%% used in the size part of a bit segment. All other information about -%% used variables are recorded in BinVarTable. The caller can then decide -%% what to do with it depending on whether variables in the pattern shadow -%% variabler or not. This separation is one way of dealing with these: +%% {UpdVarTable,NewVars,State}. +%% Check pattern return variables. VarTable is the set of variables +%% outside the pattern, used for map keys and binary sizes. Old is empty +%% if vars are shadowing, as in fun heads and comprehension generators, or +%% is otherwise equal to VarTable; this is used for deciding whether an +%% occurrence is a binding occurrence or a use. +%% UpdVarTable is updated when a previously existing variable is used in +%% the pattern. New variables and their uses are recorded in NewVars. The +%% caller can then decide what to do with it depending on whether or not +%% variables in the pattern shadow old variables. This separation is +%% one way of dealing with these: %% A = 4, fun(<<A:A>>) -> % A #2 unused %% A = 4, fun(<<A:8,16:A>>) -> % A #1 unused @@ -1636,9 +1637,9 @@ pattern({atom,Line,A}, _Vt, _Old, St) -> pattern({string,_Line,_S}, _Vt, _Old, St) -> {[],[],St}; pattern({nil,_Line}, _Vt, _Old, St) -> {[],[],St}; pattern({cons,_Line,H,T}, Vt, Old, St0) -> - {Hvt,Bvt1,St1} = pattern(H, Vt, Old, St0), - {Tvt,Bvt2,St2} = pattern(T, Vt, Old, St1), - {vtmerge_pat(Hvt, Tvt),vtmerge_pat(Bvt1,Bvt2),St2}; + {Hvt,Hnew,St1} = pattern(H, Vt, Old, St0), + {Tvt,Tnew,St2} = pattern(T, Vt, Old, St1), + {vtmerge_pat(Hvt, Tvt),vtmerge_pat(Hnew,Tnew),St2}; pattern({tuple,_Line,Ps}, Vt, Old, St) -> pattern_list(Ps, Vt, Old, St); pattern({map,_Line,Ps}, Vt, Old, St) -> @@ -1669,10 +1670,10 @@ pattern({op,_Line,'++',{cons,Li,{integer,_L2,_I},T},R}, Vt, Old, St) -> pattern({op,_Line,'++',{string,_Li,_S},R}, Vt, Old, St) -> pattern(R, Vt, Old, St); %String unimportant here pattern({match,_Line,Pat1,Pat2}, Vt, Old, St0) -> - {Lvt,Bvt1,St1} = pattern(Pat1, Vt, Old, St0), - {Rvt,Bvt2,St2} = pattern(Pat2, Vt, Old, St1), + {Lvt,Lnew,St1} = pattern(Pat1, Vt, Old, St0), + {Rvt,Rnew,St2} = pattern(Pat2, Vt, Old, St1), St3 = reject_invalid_alias(Pat1, Pat2, Vt, St2), - {vtmerge_pat(Lvt, Rvt),vtmerge_pat(Bvt1,Bvt2),St3}; + {vtmerge_pat(Lvt, Rvt),vtmerge_pat(Lnew,Rnew),St3}; %% Catch legal constant expressions, including unary +,-. pattern(Pat, _Vt, _Old, St) -> case is_pattern_expr(Pat) of @@ -1681,9 +1682,9 @@ pattern(Pat, _Vt, _Old, St) -> end. pattern_list(Ps, Vt, Old, St) -> - foldl(fun (P, {Psvt,Bvt,St0}) -> - {Pvt,Bvt1,St1} = pattern(P, Vt, Old, St0), - {vtmerge_pat(Pvt, Psvt),vtmerge_pat(Bvt,Bvt1),St1} + foldl(fun (P, {Psvt,Psnew,St0}) -> + {Pvt,Pnew,St1} = pattern(P, Vt, Old, St0), + {vtmerge_pat(Pvt, Psvt),vtmerge_pat(Psnew,Pnew),St1} end, {[],[],St}, Ps). %% Check for '_' initializing no fields. @@ -1824,43 +1825,43 @@ is_pattern_expr_1({op,_Line,Op,A1,A2}) -> is_pattern_expr_1(_Other) -> false. pattern_map(Ps, Vt, Old, St) -> - foldl(fun({map_field_assoc,L,_,_}, {Psvt,Bvt0,St0}) -> - {Psvt,Bvt0,add_error(L, illegal_pattern, St0)}; - ({map_field_exact,_L,K,V}, {Psvt,Bvt0,St0}) -> + foldl(fun({map_field_assoc,L,_,_}, {Psvt,Psnew,St0}) -> + {Psvt,Psnew,add_error(L, illegal_pattern, St0)}; + ({map_field_exact,_L,K,V}, {Psvt,Psnew,St0}) -> St1 = St0#lint{gexpr_context=map_key}, {Kvt,St2} = gexpr(K, Vt, St1), - {Vvt,Bvt2,St3} = pattern(V, Vt, Old, St2), + {Vvt,Vnew,St3} = pattern(V, Vt, Old, St2), {vtmerge_pat(vtmerge_pat(Kvt, Vvt), Psvt), - vtmerge_pat(Bvt0, Bvt2), + vtmerge_pat(Psnew, Vnew), St3} end, {[],[],St}, Ps). %% pattern_bin([Element], VarTable, Old, State) -> -%% {UpdVarTable,UpdBinVarTable,State}. -%% Check a pattern group. BinVarTable are used binsize variables. +%% {UpdVarTable,NewVars,State}. +%% Check a pattern group. pattern_bin(Es, Vt, Old, St0) -> - {_Sz,Esvt,Bvt,St1} = foldl(fun (E, Acc) -> + {_Sz,Esvt,Esnew,St1} = foldl(fun (E, Acc) -> pattern_element(E, Vt, Old, Acc) end, {0,[],[],St0}, Es), - {Esvt,Bvt,St1}. + {Esvt,Esnew,St1}. pattern_element({bin_element,Line,{string,_,_},Size,Ts}=Be, Vt, - Old, {Sz,Esvt,Bvt,St0}=Acc) -> + Old, {Sz,Esvt,Esnew,St0}=Acc) -> case good_string_size_type(Size, Ts) of true -> pattern_element_1(Be, Vt, Old, Acc); false -> St = add_error(Line, typed_literal_string, St0), - {Sz,Esvt,Bvt,St} + {Sz,Esvt,Esnew,St} end; pattern_element(Be, Vt, Old, Acc) -> pattern_element_1(Be, Vt, Old, Acc). -pattern_element_1({bin_element,Line,E,Sz0,Ts}, Vt, Old, {Size0,Esvt,Bvt,St0}) -> - {Pevt,Bvt1,St1} = pat_bit_expr(E, Old, Bvt, St0), - {Sz1,Szvt,Bvt2,St2} = pat_bit_size(Sz0, Vt, Bvt, St1), +pattern_element_1({bin_element,Line,E,Sz0,Ts}, Vt, Old, {Size0,Esvt,Esnew,St0}) -> + {Pevt,Penew,St1} = pat_bit_expr(E, Old, Esnew, St0), + {Sz1,Szvt,Sznew,St2} = pat_bit_size(Sz0, Vt, Esnew, St1), {Sz2,Bt,St3} = bit_type(Line, Sz1, Ts, St2), {Sz3,St4} = bit_size_check(Line, Sz2, Bt, St3), Sz4 = case {E,Sz3} of @@ -1869,7 +1870,7 @@ pattern_element_1({bin_element,Line,E,Sz0,Ts}, Vt, Old, {Size0,Esvt,Bvt,St0}) -> end, {Size1,St5} = add_bit_size(Line, Sz4, Size0, false, St4), {Size1,vtmerge(Szvt,vtmerge(Pevt, Esvt)), - vtmerge(Bvt2,vtmerge(Bvt, Bvt1)), St5}. + vtmerge(Sznew,vtmerge(Esnew, Penew)), St5}. good_string_size_type(default, default) -> true; @@ -1881,30 +1882,30 @@ good_string_size_type(default, Ts) -> end, Ts); good_string_size_type(_, _) -> false. -%% pat_bit_expr(Pattern, OldVarTable, BinVarTable,State) -> -%% {UpdVarTable,UpdBinVarTable,State}. +%% pat_bit_expr(Pattern, OldVarTable, NewVars, State) -> +%% {UpdVarTable,UpdNewVars,State}. %% Check pattern bit expression, only allow really valid patterns! -pat_bit_expr({var,_,'_'}, _Old, _Bvt, St) -> {[],[],St}; -pat_bit_expr({var,Ln,V}, Old, Bvt, St) -> pat_var(V, Ln, Old, Bvt, St); -pat_bit_expr({string,_,_}, _Old, _Bvt, St) -> {[],[],St}; -pat_bit_expr({bin,L,_}, _Old, _Bvt, St) -> +pat_bit_expr({var,_,'_'}, _Old, _New, St) -> {[],[],St}; +pat_bit_expr({var,Ln,V}, Old, New, St) -> pat_var(V, Ln, Old, New, St); +pat_bit_expr({string,_,_}, _Old, _new, St) -> {[],[],St}; +pat_bit_expr({bin,L,_}, _Old, _New, St) -> {[],[],add_error(L, illegal_pattern, St)}; -pat_bit_expr(P, _Old, _Bvt, St) -> +pat_bit_expr(P, _Old, _New, St) -> case is_pattern_expr(P) of true -> {[],[],St}; false -> {[],[],add_error(element(2, P), illegal_pattern, St)} end. -%% pat_bit_size(Size, VarTable, BinVarTable, State) -> -%% {Value,UpdVarTable,UpdBinVarTable,State}. +%% pat_bit_size(Size, VarTable, NewVars, State) -> +%% {Value,UpdVarTable,UpdNewVars,State}. %% Check pattern size expression, only allow really valid sizes! -pat_bit_size(default, _Vt, _Bvt, St) -> {default,[],[],St}; -pat_bit_size({var,Lv,V}, Vt0, Bvt0, St0) -> - {Vt,Bvt,St1} = pat_binsize_var(V, Lv, Vt0, Bvt0, St0), - {unknown,Vt,Bvt,St1}; -pat_bit_size(Size, Vt0, Bvt0, St0) -> +pat_bit_size(default, _Vt, _New, St) -> {default,[],[],St}; +pat_bit_size({var,Lv,V}, Vt0, New0, St0) -> + {Vt,New,St1} = pat_binsize_var(V, Lv, Vt0, New0, St0), + {unknown,Vt,New,St1}; +pat_bit_size(Size, Vt0, New0, St0) -> Line = element(2, Size), case erl_eval:partial_eval(Size) of {integer,Line,I} -> {I,[],[],St0}; @@ -1913,8 +1914,8 @@ pat_bit_size(Size, Vt0, Bvt0, St0) -> %% and/or guard BIFs calls. If the expression %% happens to evaluate to a non-integer value, the %% pattern will fail to match. - St1 = St0#lint{bvt=Bvt0,gexpr_context=bin_seg_size}, - {Vt,#lint{bvt=Bvt}=St2} = gexpr(Size, Vt0, St1), + St1 = St0#lint{bvt=New0,gexpr_context=bin_seg_size}, + {Vt,#lint{bvt=New}=St2} = gexpr(Size, Vt0, St1), St3 = St2#lint{bvt=none,gexpr_context=St0#lint.gexpr_context}, St = case is_bit_size_illegal(Expr) of true -> @@ -1924,7 +1925,7 @@ pat_bit_size(Size, Vt0, Bvt0, St0) -> add_warning(Line, non_integer_bitsize, St3); false -> St3 end, - {unknown,Vt,Bvt,St} + {unknown,Vt,New,St} end. is_bit_size_illegal({atom,_,_}) -> true; @@ -2540,9 +2541,9 @@ expr({'catch',Line,E}, Vt, St0) -> {vtupdate(vtunsafe({'catch',Line}, Evt, Vt), Evt),St}; expr({match,_Line,P,E}, Vt, St0) -> {Evt,St1} = expr(E, Vt, St0), - {Pvt,Bvt,St2} = pattern(P, vtupdate(Evt, Vt), St1), + {Pvt,Pnew,St2} = pattern(P, vtupdate(Evt, Vt), St1), St = reject_invalid_alias_expr(P, E, Vt, St2), - {vtupdate(Bvt, vtmerge(Evt, Pvt)),St}; + {vtupdate(Pnew, vtmerge(Evt, Pvt)),St}; %% No comparison or boolean operators yet. expr({op,_Line,_Op,A}, Vt, St) -> expr(A, Vt, St); @@ -2771,22 +2772,22 @@ pattern_field({atom,La,F}, Name, Fields, St) -> %% pattern_fields([PatField],RecordName,[RecDefField], %% VarTable,Old,State) -> -%% {UpdVarTable,UpdBinVarTable,State}. +%% {UpdVarTable,NewVars,State}. pattern_fields(Fs, Name, Fields, Vt0, Old, St0) -> CheckFun = fun (Val, Vt, St) -> pattern(Val, Vt, Old, St) end, - {_SeenFields,Uvt,Bvt1,St1} = - foldl(fun (Field, {Sfsa,Vta,Bvt1,Sta}) -> + {_SeenFields,Uvt,Unew,St1} = + foldl(fun (Field, {Sfsa,Vta,Newa,Sta}) -> case check_field(Field, Name, Fields, Vt0, Sta, Sfsa, CheckFun) of {Sfsb,{Vtb,Stb}} -> {Sfsb,vtmerge_pat(Vta, Vtb),[],Stb}; - {Sfsb,{Vtb,Bvt2,Stb}} -> + {Sfsb,{Vtb,Newb,Stb}} -> {Sfsb,vtmerge_pat(Vta, Vtb), - vtmerge_pat(Bvt1,Bvt2),Stb} + vtmerge_pat(Newa,Newb),Stb} end end, {[],[],[],St0}, Fs), - {Uvt,Bvt1,St1}. + {Uvt,Unew,St1}. %% record_field(Field, RecordName, [RecDefField], State) -> %% {UpdVarTable,State}. @@ -3356,8 +3357,8 @@ icrt_clauses(Cs, Vt, St) -> icrt_clause({clause,_Line,H,G,B}, Vt0, St0) -> Vt1 = taint_stack_var(Vt0, H, St0), - {Hvt,Binvt,St1} = head(H, Vt1, St0), - Vt2 = vtupdate(Hvt, Binvt), + {Hvt,Hnew,St1} = head(H, Vt1, St0), + Vt2 = vtupdate(Hvt, Hnew), Vt3 = taint_stack_var(Vt2, H, St0), {Gvt,St2} = guard(G, vtupdate(Vt3, Vt0), St1#lint{in_try_head=false}), Vt4 = vtupdate(Gvt, Vt2), @@ -3504,16 +3505,16 @@ handle_generator(P,E,Vt,Uvt,St0) -> %% Forget variables local to E immediately. Vt1 = vtupdate(vtold(Evt, Vt), Vt), {_, St2} = check_unused_vars(Evt, Vt, St1), - {Pvt,Binvt,St3} = pattern(P, Vt1, [], St2), + {Pvt,Pnew,St3} = pattern(P, Vt1, [], St2), %% Have to keep fresh variables separated from used variables somehow %% in order to handle for example X = foo(), [X || <<X:X>> <- bar()]. %% 1 2 2 1 Vt2 = vtupdate(Pvt, Vt1), - St4 = shadow_vars(Binvt, Vt1, generate, St3), - Svt = vtold(Vt2, Binvt), + St4 = shadow_vars(Pnew, Vt1, generate, St3), + Svt = vtold(Vt2, Pnew), {_, St5} = check_old_unused_vars(Svt, Uvt, St4), NUvt = vtupdate(vtnew(Svt, Uvt), Uvt), - Vt3 = vtupdate(vtsubtract(Vt2, Binvt), Binvt), + Vt3 = vtupdate(vtsubtract(Vt2, Pnew), Pnew), {Vt3,NUvt,St5}. handle_bitstring_gen_pat({bin,_,Segments=[_|_]},St) -> @@ -3550,10 +3551,10 @@ fun_clauses(Cs, Vt, St) -> {Uvt,St2#lint{recdef_top = OldRecDef}}. fun_clause({clause,_Line,H,G,B}, Vt0, St0) -> - {Hvt,Binvt,St1} = head(H, Vt0, [], St0), % No imported pattern variables + {Hvt,Hnew,St1} = head(H, Vt0, [], St0), % No imported pattern variables Vt1 = vtupdate(Hvt, Vt0), - St2 = shadow_vars(Binvt, Vt0, 'fun', St1), - Vt2 = vtupdate(vtsubtract(Vt1, Binvt), Binvt), + St2 = shadow_vars(Hnew, Vt0, 'fun', St1), + Vt2 = vtupdate(vtsubtract(Vt1, Hnew), Hnew), {Gvt,St3} = guard(G, Vt2, St2), Vt3 = vtupdate(Gvt, Vt2), {Bvt,St4} = exprs(B, Vt3, St3), @@ -3561,7 +3562,7 @@ fun_clause({clause,_Line,H,G,B}, Vt0, St0) -> %% Check new local variables. {_, St5} = check_unused_vars(Cvt, Vt0, St4), %% Check all shadowing variables. - Svt = vtold(Vt1, Binvt), + Svt = vtold(Vt1, Hnew), {_, St6} = check_old_unused_vars(Cvt, Svt, St5), Vt4 = vtmerge(Svt, vtsubtract(Cvt, Svt)), {vtold(Vt4, Vt0),St6}. @@ -3598,15 +3599,17 @@ fun_clause({clause,_Line,H,G,B}, Vt0, St0) -> %% For storing the variable table we use the orddict module. %% We know an empty set is []. -%% pat_var(Variable, LineNo, VarTable, State) -> {UpdVarTable,State} -%% A pattern variable has been found. Handle errors and warnings. Return -%% all variables as bound so errors and warnings are only reported once. -%% Bvt "shadows" Vt here, which is necessary in order to separate uses of -%% shadowed and shadowing variables. See also pat_binsize_var. +%% pat_var(Variable, LineNo, VarTable, NewVars, State) -> +%% {UpdVarTable,UpdNewVars,State} +%% A pattern variable has been found. Handle errors and warnings. Return +%% all used variables as bound so errors and warnings are only reported +%% once. New shadows Vt here, which is necessary in order to separate +%% uses of shadowed and shadowing variables. See also pat_binsize_var. -pat_var(V, Line, Vt, Bvt, St) -> - case orddict:find(V, Bvt) of +pat_var(V, Line, Vt, New, St) -> + case orddict:find(V, New) of {ok, {bound,_Usage,Ls}} -> + %% variable already in NewVars, mark as used {[],[{V,{bound,used,Ls}}],St}; error -> case orddict:find(V, Vt) of @@ -3625,17 +3628,19 @@ pat_var(V, Line, Vt, Bvt, St) -> error when St#lint.recdef_top -> {[],[{V,{bound,unused,[Line]}}], add_error(Line, {variable_in_record_def,V}, St)}; - error -> {[],[{V,{bound,unused,[Line]}}],St} + error -> + %% add variable to NewVars, not yet used + {[],[{V,{bound,unused,[Line]}}],St} end end. -%% pat_binsize_var(Variable, LineNo, VarTable, BinVarTable, State) -> -%% {UpdVarTable,UpdBinVarTable,State'} -%% A pattern variable has been found. Handle errors and warnings. Return -%% all variables as bound so errors and warnings are only reported once. +%% pat_binsize_var(Variable, LineNo, VarTable, NewVars, State) -> +%% {UpdVarTable,UpdNewVars,State'} +%% Special case of pat_var/expr_var for variables in binary size expressions +%% (never adds variables to NewVars, only marks uses). -pat_binsize_var(V, Line, Vt, Bvt, St) -> - case orddict:find(V, Bvt) of +pat_binsize_var(V, Line, Vt, New, St) -> + case orddict:find(V, New) of {ok,{bound,_Used,Ls}} -> {[],[{V,{bound,used,Ls}}],St}; error -> @@ -3667,6 +3672,7 @@ pat_binsize_var(V, Line, Vt, Bvt, St) -> expr_var(V, Line, Vt, #lint{bvt=none}=St) -> do_expr_var(V, Line, Vt, St); expr_var(V, Line, Vt0, #lint{bvt=Bvt0}=St0) when is_list(Bvt0) -> + %% handles variables in a binary segment size expression {Vt,Bvt,St} = pat_binsize_var(V, Line, Vt0, Bvt0, St0), {Vt,St#lint{bvt=vtmerge(Bvt0, Bvt)}}. @@ -3782,6 +3788,8 @@ vtmerge(Vt1, Vt2) -> vtmerge(Vts) -> foldl(fun (Vt, Mvts) -> vtmerge(Vt, Mvts) end, [], Vts). +%% this version marks variables that exist in both tables as used +%% (since that implies the compiler will add an equality check) vtmerge_pat(Vt1, Vt2) -> orddict:merge(fun (_V, {S1,_Usage1,L1}, {S2,_Usage2,L2}) -> {merge_state(S1, S2),used, merge_lines(L1, L2)} -- 2.26.2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor