~ubuntu-branches/ubuntu/trusty/erlang/trusty

« back to all changes in this revision

Viewing changes to lib/dialyzer/test/options1_tests_SUITE_data/src/compiler/core_lib.erl

  • Committer: Bazaar Package Importer
  • Author(s): Clint Byrum
  • Date: 2011-05-05 15:48:43 UTC
  • mfrom: (3.5.13 sid)
  • Revision ID: james.westby@ubuntu.com-20110505154843-0om6ekzg6m7ugj27
Tags: 1:14.b.2-dfsg-3ubuntu1
* Merge from debian unstable.  Remaining changes:
  - Drop libwxgtk2.8-dev build dependency. Wx isn't in main, and not
    supposed to.
  - Drop erlang-wx binary.
  - Drop erlang-wx dependency from -megaco, -common-test, and -reltool, they
    do not really need wx. Also drop it from -debugger; the GUI needs wx,
    but it apparently has CLI bits as well, and is also needed by -megaco,
    so let's keep the package for now.
  - debian/patches/series: Do what I meant, and enable build-options.patch
    instead.
* Additional changes:
  - Drop erlang-wx from -et
* Dropped Changes:
  - patches/pcre-crash.patch: CVE-2008-2371: outer level option with
    alternatives caused crash. (Applied Upstream)
  - fix for ssl certificate verification in newSSL: 
    ssl_cacertfile_fix.patch (Applied Upstream)
  - debian/patches/series: Enable native.patch again, to get stripped beam
    files and reduce the package size again. (build-options is what
    actually accomplished this)
  - Remove build-options.patch on advice from upstream and because it caused
    odd build failures.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
%% ``The contents of this file are subject to the Erlang Public License,
 
2
%% Version 1.1, (the "License"); you may not use this file except in
 
3
%% compliance with the License. You should have received a copy of the
 
4
%% Erlang Public License along with this software. If not, it can be
 
5
%% retrieved via the world wide web at http://www.erlang.org/.
 
6
%% 
 
7
%% Software distributed under the License is distributed on an "AS IS"
 
8
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 
9
%% the License for the specific language governing rights and limitations
 
10
%% under the License.
 
11
%% 
 
12
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
 
13
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
 
14
%% AB. All Rights Reserved.''
 
15
%% 
 
16
%%     $Id: core_lib.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
 
17
%%
 
18
%% Purpose: Core Erlang abstract syntax functions.
 
19
 
 
20
-module(core_lib).
 
21
 
 
22
-export([get_anno/1,set_anno/2]).
 
23
-export([is_atomic/1,is_literal/1,is_literal_list/1,
 
24
         is_simple/1,is_simple_list/1,is_simple_top/1]).
 
25
-export([literal_value/1,make_literal/1]).
 
26
-export([make_values/1]).
 
27
-export([map/2, fold/3, mapfold/3]).
 
28
-export([is_var_used/2]).
 
29
 
 
30
%% -compile([export_all]).
 
31
 
 
32
-include("core_parse.hrl").
 
33
 
 
34
%% get_anno(Core) -> Anno.
 
35
%% set_anno(Core, Anno) -> Core.
 
36
%%  Generic get/set annotation.
 
37
 
 
38
get_anno(C) -> element(2, C).
 
39
set_anno(C, A) -> setelement(2, C, A).
 
40
 
 
41
%% is_atomic(Expr) -> true | false.
 
42
 
 
43
is_atomic(#c_char{}) -> true;
 
44
is_atomic(#c_int{}) -> true;
 
45
is_atomic(#c_float{}) -> true;
 
46
is_atomic(#c_atom{}) -> true;
 
47
is_atomic(#c_string{}) -> true;
 
48
is_atomic(#c_nil{}) -> true;
 
49
is_atomic(#c_fname{}) -> true;
 
50
is_atomic(_) -> false.
 
51
 
 
52
%% is_literal(Expr) -> true | false.
 
53
 
 
54
is_literal(#c_cons{hd=H,tl=T}) ->
 
55
    case is_literal(H) of
 
56
        true -> is_literal(T); 
 
57
        false -> false
 
58
    end;
 
59
is_literal(#c_tuple{es=Es}) -> is_literal_list(Es);
 
60
is_literal(#c_binary{segments=Es}) -> is_lit_bin(Es);
 
61
is_literal(E) -> is_atomic(E).
 
62
 
 
63
is_literal_list(Es) -> lists:all(fun is_literal/1, Es).
 
64
 
 
65
is_lit_bin(Es) ->
 
66
    lists:all(fun (#c_bitstr{val=E,size=S}) ->
 
67
                      is_literal(E) and is_literal(S)
 
68
              end, Es).
 
69
 
 
70
%% is_simple(Expr) -> true | false.
 
71
 
 
72
is_simple(#c_var{}) -> true;
 
73
is_simple(#c_cons{hd=H,tl=T}) ->
 
74
    case is_simple(H) of
 
75
        true -> is_simple(T); 
 
76
        false -> false
 
77
    end;
 
78
is_simple(#c_tuple{es=Es}) -> is_simple_list(Es);
 
79
is_simple(#c_binary{segments=Es}) -> is_simp_bin(Es);
 
80
is_simple(E) -> is_atomic(E).
 
81
 
 
82
is_simple_list(Es) -> lists:all(fun is_simple/1, Es).
 
83
 
 
84
is_simp_bin(Es) ->
 
85
    lists:all(fun (#c_bitstr{val=E,size=S}) ->
 
86
                      is_simple(E) and is_simple(S)
 
87
              end, Es).
 
88
 
 
89
%% is_simple_top(Expr) -> true | false.
 
90
%%  Only check if the top-level is a simple.
 
91
 
 
92
is_simple_top(#c_var{}) -> true;
 
93
is_simple_top(#c_cons{}) -> true;
 
94
is_simple_top(#c_tuple{}) -> true;
 
95
is_simple_top(#c_binary{}) -> true;
 
96
is_simple_top(E) -> is_atomic(E).
 
97
 
 
98
%% literal_value(LitExpr) -> Value.
 
99
%%  Return the value of LitExpr.
 
100
 
 
101
literal_value(#c_char{val=C}) -> C;
 
102
literal_value(#c_int{val=I}) -> I;
 
103
literal_value(#c_float{val=F}) -> F;
 
104
literal_value(#c_atom{val=A}) -> A;
 
105
literal_value(#c_string{val=S}) -> S;
 
106
literal_value(#c_nil{}) -> [];
 
107
literal_value(#c_cons{hd=H,tl=T}) ->
 
108
    [literal_value(H)|literal_value(T)];
 
109
literal_value(#c_tuple{es=Es}) ->
 
110
    list_to_tuple(literal_value_list(Es)).
 
111
 
 
112
literal_value_list(Vals) -> lists:map(fun literal_value/1, Vals).
 
113
 
 
114
%% make_literal(Value) -> LitExpr.
 
115
%%  Make a literal expression from an Erlang value.
 
116
 
 
117
make_literal(I) when integer(I) -> #c_int{val=I};
 
118
make_literal(F) when float(F) -> #c_float{val=F};
 
119
make_literal(A) when atom(A) -> #c_atom{val=A};
 
120
make_literal([]) -> #c_nil{};
 
121
make_literal([H|T]) ->
 
122
    #c_cons{hd=make_literal(H),tl=make_literal(T)};
 
123
make_literal(T) when tuple(T) ->
 
124
    #c_tuple{es=make_literal_list(tuple_to_list(T))}.
 
125
 
 
126
make_literal_list(Vals) -> lists:map(fun make_literal/1, Vals). 
 
127
 
 
128
%% make_values([CoreExpr] | CoreExpr) -> #c_values{} | CoreExpr.
 
129
%%  Make a suitable values structure, expr or values, depending on
 
130
%%  Expr.
 
131
 
 
132
make_values([E]) -> E;
 
133
make_values([H|_]=Es) -> #c_values{anno=get_anno(H),es=Es};
 
134
make_values([]) -> #c_values{es=[]};
 
135
make_values(E) -> E.
 
136
 
 
137
%% map(MapFun, CoreExpr) -> CoreExpr.
 
138
%%  This function traverses the core parse format, at each level
 
139
%%  applying the submited argument function, assumed to do the real
 
140
%%  work.
 
141
%%
 
142
%%  The "eager" style, where each component of a construct are
 
143
%%  descended to before the construct itself, admits that some
 
144
%%  companion functions (the F:s) may be made simpler, since it may be
 
145
%%  safely assumed that no lower illegal instanced will be
 
146
%%  created/uncovered by actions on the current level.
 
147
 
 
148
map(F, #c_tuple{es=Es}=R) ->
 
149
    F(R#c_tuple{es=map_list(F, Es)});
 
150
map(F, #c_cons{hd=Hd, tl=Tl}=R) ->
 
151
    F(R#c_cons{hd=map(F, Hd), 
 
152
               tl=map(F, Tl)});
 
153
map(F, #c_values{es=Es}=R) ->
 
154
    F(R#c_values{es=map_list(F, Es)});
 
155
 
 
156
map(F, #c_alias{var=Var, pat=Pat}=R) ->
 
157
    F(R#c_alias{var=map(F, Var),
 
158
                pat=map(F, Pat)});
 
159
 
 
160
map(F, #c_module{defs=Defs}=R) ->
 
161
    F(R#c_module{defs=map_list(F, Defs)});
 
162
map(F, #c_def{val=Val}=R) ->
 
163
    F(R#c_def{val=map(F, Val)});
 
164
 
 
165
map(F, #c_fun{vars=Vars, body=Body}=R) ->
 
166
    F(R#c_fun{vars=map_list(F, Vars),
 
167
              body=map(F, Body)});
 
168
map(F, #c_let{vars=Vs, arg=Arg, body=Body}=R) ->
 
169
    F(R#c_let{vars=map_list(F, Vs), 
 
170
              arg=map(F, Arg), 
 
171
              body=map(F, Body)});
 
172
map(F, #c_letrec{defs=Fs,body=Body}=R) ->
 
173
    F(R#c_letrec{defs=map_list(F, Fs),
 
174
                 body=map(F, Body)});
 
175
map(F, #c_seq{arg=Arg, body=Body}=R) ->
 
176
    F(R#c_seq{arg=map(F, Arg),
 
177
              body=map(F, Body)});
 
178
map(F, #c_case{arg=Arg, clauses=Clauses}=R) ->
 
179
    F(R#c_case{arg=map(F, Arg),
 
180
               clauses=map_list(F, Clauses)});
 
181
map(F, #c_clause{pats=Ps, guard=Guard, body=Body}=R) ->
 
182
    F(R#c_clause{pats=map_list(F, Ps), 
 
183
                 guard=map(F, Guard), 
 
184
                 body=map(F, Body)});
 
185
map(F, #c_receive{clauses=Cls, timeout=Tout, action=Act}=R) ->
 
186
    F(R#c_receive{clauses=map_list(F, Cls),
 
187
                  timeout=map(F, Tout),
 
188
                  action=map(F, Act)});
 
189
map(F, #c_apply{op=Op,args=Args}=R) ->
 
190
    F(R#c_apply{op=map(F, Op),
 
191
                args=map_list(F, Args)});
 
192
map(F, #c_call{module=M,name=N,args=Args}=R) ->
 
193
    F(R#c_call{module=map(F, M),
 
194
               name=map(F, N),
 
195
               args=map_list(F, Args)});
 
196
map(F, #c_primop{name=N,args=Args}=R) ->
 
197
    F(R#c_primop{name=map(F, N),
 
198
                 args=map_list(F, Args)});
 
199
map(F, #c_try{arg=Expr,vars=Vars,body=Body,evars=Evars,handler=Handler}=R) ->
 
200
    F(R#c_try{arg=map(F, Expr), 
 
201
              vars=map(F, Vars), 
 
202
              body=map(F, Body),
 
203
              evars=map(F, Evars),
 
204
              handler=map(F, Handler)});
 
205
map(F, #c_catch{body=Body}=R) ->
 
206
    F(R#c_catch{body=map(F, Body)});
 
207
map(F, T) -> F(T).                              %Atomic nodes.
 
208
 
 
209
map_list(F, L) -> lists:map(fun (E) -> map(F, E) end, L).
 
210
 
 
211
%% fold(FoldFun, Accumulator, CoreExpr) -> Accumulator.
 
212
%%  This function traverses the core parse format, at each level
 
213
%%  applying the submited argument function, assumed to do the real
 
214
%%  work, and keeping the accumulated result in the A (accumulator)
 
215
%%  argument.
 
216
 
 
217
fold(F, Acc, #c_tuple{es=Es}=R) ->
 
218
    F(R, fold_list(F, Acc, Es));
 
219
fold(F, Acc, #c_cons{hd=Hd, tl=Tl}=R) ->
 
220
    F(R, fold(F, fold(F, Acc, Hd), Tl));
 
221
fold(F, Acc, #c_values{es=Es}=R) ->
 
222
    F(R, fold_list(F, Acc, Es));
 
223
 
 
224
fold(F, Acc, #c_alias{pat=P,var=V}=R) ->
 
225
    F(R, fold(F, fold(F, Acc, P), V));
 
226
 
 
227
fold(F, Acc, #c_module{defs=Defs}=R) ->
 
228
    F(R, fold_list(F, Acc, Defs));
 
229
fold(F, Acc, #c_def{val=Val}=R) ->
 
230
    F(R, fold(F, Acc, Val));
 
231
 
 
232
fold(F, Acc, #c_fun{vars=Vars, body=Body}=R) ->
 
233
    F(R, fold(F, fold_list(F, Acc, Vars), Body));
 
234
fold(F, Acc, #c_let{vars=Vs, arg=Arg, body=Body}=R) ->
 
235
    F(R, fold(F, fold(F, fold_list(F, Acc, Vs), Arg), Body));
 
236
fold(F, Acc, #c_letrec{defs=Fs,body=Body}=R) ->
 
237
    F(R, fold(F, fold_list(F, Acc, Fs), Body));
 
238
fold(F, Acc, #c_seq{arg=Arg, body=Body}=R) ->
 
239
    F(R, fold(F, fold(F, Acc, Arg), Body));
 
240
fold(F, Acc, #c_case{arg=Arg, clauses=Clauses}=R) ->
 
241
    F(R, fold_list(F, fold(F, Acc, Arg), Clauses));
 
242
fold(F, Acc, #c_clause{pats=Ps,guard=G,body=B}=R) ->
 
243
    F(R, fold(F, fold(F, fold_list(F, Acc, Ps), G), B));
 
244
fold(F, Acc, #c_receive{clauses=Cl, timeout=Ti, action=Ac}=R) ->
 
245
    F(R, fold_list(F, fold(F, fold(F, Acc, Ac), Ti), Cl));
 
246
fold(F, Acc, #c_apply{op=Op, args=Args}=R) ->
 
247
    F(R, fold_list(F, fold(F, Acc, Op), Args));
 
248
fold(F, Acc, #c_call{module=Mod,name=Name,args=Args}=R) ->
 
249
    F(R, fold_list(F, fold(F, fold(F, Acc, Mod), Name), Args));
 
250
fold(F, Acc, #c_primop{name=Name,args=Args}=R) ->
 
251
    F(R, fold_list(F, fold(F, Acc, Name), Args));
 
252
fold(F, Acc, #c_try{arg=E,vars=Vs,body=Body,evars=Evs,handler=H}=R) ->
 
253
    NewB = fold(F, fold_list(F, fold(F, Acc, E), Vs), Body),
 
254
    F(R, fold(F, fold_list(F, NewB, Evs), H));
 
255
fold(F, Acc, #c_catch{body=Body}=R) ->
 
256
    F(R, fold(F, Acc, Body));
 
257
fold(F, Acc, T) ->                              %Atomic nodes
 
258
    F(T, Acc).
 
259
 
 
260
fold_list(F, Acc, L) ->
 
261
    lists:foldl(fun (E, A) -> fold(F, A, E) end, Acc, L).
 
262
 
 
263
%% mapfold(MapfoldFun, Accumulator, CoreExpr) -> {CoreExpr,Accumulator}.
 
264
%%  This function traverses the core parse format, at each level
 
265
%%  applying the submited argument function, assumed to do the real
 
266
%%  work, and keeping the accumulated result in the A (accumulator)
 
267
%%  argument.
 
268
 
 
269
mapfold(F, Acc0, #c_tuple{es=Es0}=R) ->
 
270
    {Es1,Acc1} = mapfold_list(F, Acc0, Es0),
 
271
    F(R#c_tuple{es=Es1}, Acc1);
 
272
mapfold(F, Acc0, #c_cons{hd=H0,tl=T0}=R) ->
 
273
    {H1,Acc1} = mapfold(F, Acc0, H0),
 
274
    {T1,Acc2} = mapfold(F, Acc1, T0),
 
275
    F(R#c_cons{hd=H1,tl=T1}, Acc2);
 
276
mapfold(F, Acc0, #c_values{es=Es0}=R) ->
 
277
    {Es1,Acc1} = mapfold_list(F, Acc0, Es0),
 
278
    F(R#c_values{es=Es1}, Acc1);
 
279
 
 
280
mapfold(F, Acc0, #c_alias{pat=P0,var=V0}=R) ->
 
281
    {P1,Acc1} = mapfold(F, Acc0, P0),
 
282
    {V1,Acc2} = mapfold(F, Acc1, V0),
 
283
    F(R#c_alias{pat=P1,var=V1}, Acc2);
 
284
 
 
285
mapfold(F, Acc0, #c_module{defs=D0}=R) ->
 
286
    {D1,Acc1} = mapfold_list(F, Acc0, D0),
 
287
    F(R#c_module{defs=D1}, Acc1);
 
288
mapfold(F, Acc0, #c_def{val=V0}=R) ->
 
289
    {V1,Acc1} = mapfold(F, Acc0, V0),
 
290
    F(R#c_def{val=V1}, Acc1);
 
291
 
 
292
mapfold(F, Acc0, #c_fun{vars=Vs0, body=B0}=R) ->
 
293
    {Vs1,Acc1} = mapfold_list(F, Acc0, Vs0),
 
294
    {B1,Acc2} = mapfold(F, Acc1, B0),
 
295
    F(R#c_fun{vars=Vs1,body=B1}, Acc2);
 
296
mapfold(F, Acc0, #c_let{vars=Vs0, arg=A0, body=B0}=R) ->
 
297
    {Vs1,Acc1} = mapfold_list(F, Acc0, Vs0),
 
298
    {A1,Acc2} = mapfold(F, Acc1, A0),
 
299
    {B1,Acc3} = mapfold(F, Acc2, B0),
 
300
    F(R#c_let{vars=Vs1,arg=A1,body=B1}, Acc3);
 
301
mapfold(F, Acc0, #c_letrec{defs=Fs0,body=B0}=R) ->
 
302
    {Fs1,Acc1} = mapfold_list(F, Acc0, Fs0),
 
303
    {B1,Acc2} = mapfold(F, Acc1, B0),
 
304
    F(R#c_letrec{defs=Fs1,body=B1}, Acc2);
 
305
mapfold(F, Acc0, #c_seq{arg=A0, body=B0}=R) ->
 
306
    {A1,Acc1} = mapfold(F, Acc0, A0),
 
307
    {B1,Acc2} = mapfold(F, Acc1, B0),
 
308
    F(R#c_seq{arg=A1,body=B1}, Acc2);
 
309
mapfold(F, Acc0, #c_case{arg=A0,clauses=Cs0}=R) ->
 
310
    {A1,Acc1} = mapfold(F, Acc0, A0),
 
311
    {Cs1,Acc2} = mapfold_list(F, Acc1, Cs0),
 
312
    F(R#c_case{arg=A1,clauses=Cs1}, Acc2);
 
313
mapfold(F, Acc0, #c_clause{pats=Ps0,guard=G0,body=B0}=R) ->
 
314
    {Ps1,Acc1} = mapfold_list(F, Acc0, Ps0),
 
315
    {G1,Acc2} = mapfold(F, Acc1, G0),
 
316
    {B1,Acc3} = mapfold(F, Acc2, B0),
 
317
    F(R#c_clause{pats=Ps1,guard=G1,body=B1}, Acc3);
 
318
mapfold(F, Acc0, #c_receive{clauses=Cs0,timeout=T0,action=A0}=R) ->
 
319
    {T1,Acc1} = mapfold(F, Acc0, T0),
 
320
    {Cs1,Acc2} = mapfold_list(F, Acc1, Cs0),
 
321
    {A1,Acc3} = mapfold(F, Acc2, A0),
 
322
    F(R#c_receive{clauses=Cs1,timeout=T1,action=A1}, Acc3);
 
323
mapfold(F, Acc0, #c_apply{op=Op0, args=As0}=R) ->
 
324
    {Op1,Acc1} = mapfold(F, Acc0, Op0),
 
325
    {As1,Acc2} = mapfold_list(F, Acc1, As0),
 
326
    F(R#c_apply{op=Op1,args=As1}, Acc2);
 
327
mapfold(F, Acc0, #c_call{module=M0,name=N0,args=As0}=R) ->
 
328
    {M1,Acc1} = mapfold(F, Acc0, M0),
 
329
    {N1,Acc2} = mapfold(F, Acc1, N0),
 
330
    {As1,Acc3} = mapfold_list(F, Acc2, As0),
 
331
    F(R#c_call{module=M1,name=N1,args=As1}, Acc3);
 
332
mapfold(F, Acc0, #c_primop{name=N0, args=As0}=R) ->
 
333
    {N1,Acc1} = mapfold(F, Acc0, N0),
 
334
    {As1,Acc2} = mapfold_list(F, Acc1, As0),
 
335
    F(R#c_primop{name=N1,args=As1}, Acc2);
 
336
mapfold(F, Acc0, #c_try{arg=E0,vars=Vs0,body=B0,evars=Evs0,handler=H0}=R) ->
 
337
    {E1,Acc1} = mapfold(F, Acc0, E0),
 
338
    {Vs1,Acc2} = mapfold_list(F, Acc1, Vs0),
 
339
    {B1,Acc3} = mapfold(F, Acc2, B0),
 
340
    {Evs1,Acc4} = mapfold_list(F, Acc3, Evs0),
 
341
    {H1,Acc5} = mapfold(F, Acc4, H0),
 
342
    F(R#c_try{arg=E1,vars=Vs1,body=B1,evars=Evs1,handler=H1}, Acc5);
 
343
mapfold(F, Acc0, #c_catch{body=B0}=R) ->
 
344
    {B1,Acc1} = mapfold(F, Acc0, B0),
 
345
    F(R#c_catch{body=B1}, Acc1);
 
346
mapfold(F, Acc, T) ->                           %Atomic nodes
 
347
        F(T, Acc).
 
348
 
 
349
mapfold_list(F, Acc, L) ->
 
350
    lists:mapfoldl(fun (E, A) -> mapfold(F, A, E) end, Acc, L).
 
351
 
 
352
%% is_var_used(VarName, Expr) -> true | false.
 
353
%%  Test if the variable VarName is used in Expr.
 
354
 
 
355
is_var_used(V, B) -> vu_body(V, B).
 
356
 
 
357
vu_body(V, #c_values{es=Es}) ->
 
358
    vu_expr_list(V, Es);
 
359
vu_body(V, Body) ->
 
360
    vu_expr(V, Body).
 
361
 
 
362
vu_expr(V, #c_var{name=V2}) -> V =:= V2;
 
363
vu_expr(V, #c_cons{hd=H,tl=T}) ->
 
364
    case vu_expr(V, H) of
 
365
        true -> true;
 
366
        false -> vu_expr(V, T)
 
367
    end;
 
368
vu_expr(V, #c_tuple{es=Es}) ->
 
369
    vu_expr_list(V, Es);
 
370
vu_expr(V, #c_binary{segments=Ss}) ->
 
371
    vu_seg_list(V, Ss);
 
372
vu_expr(V, #c_fun{vars=Vs,body=B}) ->
 
373
    %% Variables in fun shadow previous variables
 
374
    case vu_var_list(V, Vs) of
 
375
        true -> false;
 
376
        false -> vu_body(V, B)
 
377
    end;
 
378
vu_expr(V, #c_let{vars=Vs,arg=Arg,body=B}) ->
 
379
    case vu_body(V, Arg) of
 
380
        true -> true;
 
381
        false ->
 
382
            %% Variables in let shadow previous variables.
 
383
            case vu_var_list(V, Vs) of
 
384
                true -> false;
 
385
                false -> vu_body(V, B)
 
386
            end
 
387
    end;
 
388
vu_expr(V, #c_letrec{defs=Fs,body=B}) ->
 
389
    case lists:any(fun (#c_def{val=Fb}) -> vu_body(V, Fb) end, Fs) of
 
390
        true -> true;
 
391
        false -> vu_body(V, B)
 
392
    end;
 
393
vu_expr(V, #c_seq{arg=Arg,body=B}) ->
 
394
    case vu_expr(V, Arg) of
 
395
        true -> true;
 
396
        false -> vu_body(V, B)
 
397
    end;
 
398
vu_expr(V, #c_case{arg=Arg,clauses=Cs}) ->
 
399
    case vu_expr(V, Arg) of
 
400
        true -> true;
 
401
        false -> vu_clauses(V, Cs)
 
402
    end;
 
403
vu_expr(V, #c_receive{clauses=Cs,timeout=T,action=A}) ->
 
404
    case vu_clauses(V, Cs) of
 
405
        true -> true;
 
406
        false ->
 
407
            case vu_expr(V, T) of
 
408
                true -> true;
 
409
                false -> vu_body(V, A)
 
410
            end
 
411
    end;
 
412
vu_expr(V, #c_apply{op=Op,args=As}) ->
 
413
    vu_expr_list(V, [Op|As]);
 
414
vu_expr(V, #c_call{module=M,name=N,args=As}) ->
 
415
    vu_expr_list(V, [M,N|As]);
 
416
vu_expr(V, #c_primop{args=As}) ->               %Name is an atom
 
417
    vu_expr_list(V, As);
 
418
vu_expr(V, #c_catch{body=B}) ->
 
419
    vu_body(V, B);
 
420
vu_expr(V, #c_try{arg=E,vars=Vs,body=B,evars=Evs,handler=H}) ->
 
421
    case vu_body(V, E) of
 
422
        true -> true;
 
423
        false ->
 
424
            %% Variables shadow previous ones.
 
425
            case case vu_var_list(V, Vs) of
 
426
                     true -> false;
 
427
                     false -> vu_body(V, B)
 
428
                 end of
 
429
                true -> true;
 
430
                false ->
 
431
                    case vu_var_list(V, Evs) of
 
432
                        true -> false;
 
433
                        false -> vu_body(V, H)
 
434
                    end
 
435
            end
 
436
    end;
 
437
vu_expr(_, _) -> false.                         %Everything else
 
438
 
 
439
vu_expr_list(V, Es) ->
 
440
    lists:any(fun(E) -> vu_expr(V, E) end, Es).
 
441
 
 
442
vu_seg_list(V, Ss) ->
 
443
    lists:any(fun (#c_bitstr{val=Val,size=Size}) ->
 
444
                      case vu_expr(V, Val) of
 
445
                          true -> true;
 
446
                          false -> vu_expr(V, Size)
 
447
                      end
 
448
              end, Ss).
 
449
 
 
450
%% vu_clause(VarName, Clause) -> true | false.
 
451
%% vu_clauses(VarName, [Clause]) -> true | false.
 
452
%%  Have to get the pattern results right.
 
453
 
 
454
vu_clause(V, #c_clause{pats=Ps,guard=G,body=B}) ->
 
455
    case vu_pattern_list(V, Ps) of
 
456
        {true,_Shad} -> true;                   %It is used
 
457
        {false,true} -> false;                  %Shadowed
 
458
        {false,false} ->                        %Not affected
 
459
            case vu_expr(V, G) of
 
460
                true -> true;
 
461
                false ->vu_body(V, B)
 
462
            end
 
463
    end.
 
464
 
 
465
vu_clauses(V, Cs) ->
 
466
    lists:any(fun(C) -> vu_clause(V, C) end, Cs).
 
467
 
 
468
%% vu_pattern(VarName, Pattern) -> {Used,Shadow}.
 
469
%% vu_pattern_list(VarName, [Pattern]) -> {Used,Shadow}.
 
470
%%  Binaries complicate patterns as a variable can both be properly
 
471
%%  used, in a bit segment size, and shadow.  They can also do both.
 
472
 
 
473
%%vu_pattern(V, Pat) -> vu_pattern(V, Pat, {false,false}).
 
474
 
 
475
vu_pattern(V, #c_var{name=V2}, St) ->
 
476
    setelement(2, St, V =:= V2);
 
477
vu_pattern(V, #c_cons{hd=H,tl=T}, St0) ->
 
478
    case vu_pattern(V, H, St0) of
 
479
        {true,true}=St1 -> St1;                 %Nothing more to know
 
480
        St1 -> vu_pattern(V, T, St1)
 
481
    end;
 
482
vu_pattern(V, #c_tuple{es=Es}, St) ->
 
483
    vu_pattern_list(V, Es, St);
 
484
vu_pattern(V, #c_binary{segments=Ss}, St) ->
 
485
    vu_pat_seg_list(V, Ss, St);
 
486
vu_pattern(V, #c_alias{var=Var,pat=P}, St0) ->
 
487
    case vu_pattern(V, Var, St0) of
 
488
        {true,true}=St1 -> St1;
 
489
        St1 -> vu_pattern(V, P, St1)
 
490
    end;
 
491
vu_pattern(_, _, St) -> St.
 
492
 
 
493
vu_pattern_list(V, Ps) -> vu_pattern_list(V, Ps, {false,false}).
 
494
 
 
495
vu_pattern_list(V, Ps, St0) ->
 
496
    lists:foldl(fun(P, St) -> vu_pattern(V, P, St) end, St0, Ps).
 
497
 
 
498
vu_pat_seg_list(V, Ss, St) ->
 
499
    lists:foldl(fun (#c_bitstr{val=Val,size=Size}, St0) ->
 
500
                        case vu_pattern(V, Val, St0) of
 
501
                            {true,true}=St1 -> St1;
 
502
                            {_Used,Shad} -> {vu_expr(V, Size),Shad}
 
503
                        end
 
504
                end, St, Ss).
 
505
 
 
506
%% vu_var_list(VarName, [Var]) -> true | false.
 
507
 
 
508
vu_var_list(V, Vs) ->
 
509
    lists:any(fun (#c_var{name=V2}) -> V =:= V2 end, Vs).