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

« back to all changes in this revision

Viewing changes to lib/tools/src/xref_compiler.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
1
%%
2
2
%% %CopyrightBegin%
3
 
%% 
4
 
%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
5
 
%% 
 
3
%%
 
4
%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
 
5
%%
6
6
%% The contents of this file are subject to the Erlang Public License,
7
7
%% Version 1.1, (the "License"); you may not use this file except in
8
8
%% compliance with the License. You should have received a copy of the
9
9
%% Erlang Public License along with this software. If not, it can be
10
10
%% retrieved online at http://www.erlang.org/.
11
 
%% 
 
11
%%
12
12
%% Software distributed under the License is distributed on an "AS IS"
13
13
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
14
%% the License for the specific language governing rights and limitations
15
15
%% under the License.
16
 
%% 
 
16
%%
17
17
%% %CopyrightEnd%
18
18
%%
19
19
 
31
31
-define(CALL(F), ok).
32
32
-endif.
33
33
 
 
34
%% Avoid warning for local function error/1 clashing with autoimported BIF.
 
35
-compile({no_auto_import,[error/1]}).
34
36
-export([compile/2]).
35
37
 
36
38
-export([update_graph_counter/3]).
37
39
 
38
40
-export([format_error/1]).
39
41
 
40
 
-import(lists, 
 
42
-import(lists,
41
43
        [concat/1, foldl/3, nthtail/2, reverse/1, sort/1, sublist/2]).
42
44
 
43
45
-import(sofs,
44
46
        [composite/2, difference/2, empty_set/0, from_term/1,
45
47
         intersection/2, is_empty_set/1, multiple_relative_product/2,
46
48
         projection/2, relation/1, relation_to_family/1,
47
 
         restriction/2, substitution/2, to_external/1, union/2,
48
 
         union_of_family/1]).
 
49
         restriction/2, specification/2, substitution/2,
 
50
         to_external/1, union/2, union_of_family/1]).
49
51
 
50
52
%%
51
53
%%  Exported functions
75
77
        {error, Info, Line} ->
76
78
            error({parse_error, Line, Info})
77
79
    end.
78
 
    
 
80
 
79
81
format_error({error, Module, Error}) ->
80
82
    Module:format_error(Error);
81
83
format_error({parse_error, Line, Error}) ->
115
117
            throw_error({variable_reassigned, xref_parser:t2s(Stmt)});
116
118
        error ->
117
119
            {Type, OType, NewE} = t_expr(E, Table),
118
 
            Val = #xref_var{name = Name, vtype = VarType, 
 
120
            Val = #xref_var{name = Name, vtype = VarType,
119
121
                            otype = OType, type = Type},
120
122
            NewTable = dict:store(Name, Val, Table),
121
123
            Stmts = if Stmts0 =:= [] -> [{variable, Name}]; true -> Stmts0 end,
128
130
    E1 = un_familiarize(Type, OType, NewE),
129
131
    NE = case {Type, OType} of
130
132
             %% Edges with empty sets of line numbers are removed.
131
 
             {{line, _}, edge} -> 
 
133
             {{line, _}, edge} ->
132
134
                 {relation_to_family, E1};
133
 
             {_Type, edge_closure} -> 
 
135
             {_Type, edge_closure} ->
134
136
                 %% Fake a closure usage, just to make sure it is destroyed.
135
137
                 E2 = {fun graph_access/2, E1, E1},
136
138
                 {fun(_E) -> 'closure()' end, E2};
163
165
%%% Constant = atom() | {atom(), atom()} | MFA | {MFA, MFA}
164
166
%%% Call = atom() % function in the sofs module
165
167
%%%      | fun()
166
 
%%% Type = {line, LineType} | function | module | application | release 
 
168
%%% Type = {line, LineType} | function | module | application | release
167
169
%%%      | number
168
170
%%% LineType = line | local_call | external_call | export_call | all_line_call
169
171
%%% VarType = predef | user | tmp
182
184
    case dict:find(Name, Table) of
183
185
        {ok, #xref_var{vtype = VarType, otype = OType, type = Type}} ->
184
186
            V0 = {variable, {VarType, Name}},
185
 
            V = case {VarType, Type, OType} of 
 
187
            V = case {VarType, Type, OType} of
186
188
                    {predef, release, _} -> V0;
187
189
                    {predef, application, _} -> V0;
188
190
                    {predef, module, _} -> V0;
212
214
                {edge_set, domain} -> vertex_set;
213
215
                {edge_set, weak} -> edge_set;
214
216
                {edge_set, strict} -> edge_set;
215
 
                _ -> 
 
217
                _ ->
216
218
                    throw_error({type_error, xref_parser:t2s(Expr)})
217
219
            end,
218
220
    Op = set_op(SOp),
223
225
    case Type of
224
226
        {line, _LineType} ->
225
227
            throw_error({type_error, xref_parser:t2s(Expr)});
226
 
        _Else -> 
 
228
        _Else ->
227
229
            ok
228
230
    end,
229
 
    OType = 
 
231
    OType =
230
232
        case {NOType, Op} of
231
233
            {edge, components} -> vertex_set;
232
234
            {edge, condensation} -> edge_set;
237
239
            %% Neither need nor want these ones:
238
240
            %% {edge_set, closure} -> edge_set_closure;
239
241
            %% {edge_set, components} -> vertex_set_set;
240
 
            _ -> 
 
242
            _ ->
241
243
                throw_error({type_error, xref_parser:t2s(Expr)})
242
244
        end,
243
245
    E2 = {convert, NOType, edge_closure, E1},
271
273
        number ->
272
274
            {expr, number, number, {call, ari_op(SOp), NE1, NE2}};
273
275
        _Else -> % set
274
 
            {Type, NewE1, NewE2} = 
 
276
            {Type, NewE1, NewE2} =
275
277
                case {type_ord(Type1), type_ord(Type2)} of
276
278
                    {T1, T2} when T1 =:= T2 ->
277
 
                        %% Example: if Type1 = {line, line} and 
 
279
                        %% Example: if Type1 = {line, line} and
278
280
                        %% Type2 = {line, export_line}, then this is not
279
281
                        %% correct, but works:
280
282
                        {Type1, NE1, NE2};
296
298
            throw_error({type_error, xref_parser:t2s(Expr)});
297
299
        {_Type1, {line, _LineType2}} ->
298
300
            throw_error({type_error, xref_parser:t2s(Expr)});
299
 
        _ -> 
 
301
        _ ->
300
302
            ok
301
303
    end,
302
304
    case {OType1, OType2} of
307
309
        {edge, vertex} ->
308
310
            restriction(ROp, E1, Type1, NE1, Type2, NE2);
309
311
        {edge_closure, vertex} when ROp =:= '|||' ->
310
 
            {expr, _, _, R1} = 
 
312
            {expr, _, _, R1} =
311
313
                closure_restriction('|', Type1, Type2, OType2, NE1, NE2),
312
 
            {expr, _, _, R2} = 
 
314
            {expr, _, _, R2} =
313
315
                closure_restriction('||', Type1, Type2, OType2, NE1, NE2),
314
316
            {expr, Type1, edge, {call, intersection, R1, R2}};
315
 
        {edge_closure, vertex} -> 
 
317
        {edge_closure, vertex} ->
316
318
            closure_restriction(ROp, Type1, Type2, OType2, NE1, NE2);
317
 
        _ -> 
 
319
        _ ->
318
320
            throw_error({type_error, xref_parser:t2s(Expr)})
319
321
    end;
320
322
check_expr(Expr={path, E1, E2}, Table) ->
330
332
    end,
331
333
    E2b = {convert, OType2, Type2, Type1, E2a},
332
334
    {OType1, NE1} = path_arg(OType1a, E1a),
333
 
    NE2 = case {OType1, OType2} of 
 
335
    NE2 = case {OType1, OType2} of
334
336
              {path, edge} -> {convert, OType2, edge_closure, E2b};
335
337
              {path, edge_closure} when Type1 =:= Type2 -> E2b;
336
338
              _ -> throw_error({type_error, xref_parser:t2s(Expr)})
347
349
            release -> 'R'
348
350
        end,
349
351
    Var = {variable, {predef, V}},
350
 
    Call = {call, fun(E, V2) -> xref_utils:regexpr(E, V2) end, 
 
352
    Call = {call, fun(E, V2) -> xref_utils:regexpr(E, V2) end,
351
353
            {constants, RExpr}, Var},
352
354
    {expr, Type, vertex, Call};
353
355
check_expr(C={constant, _Type, _OType, _C}, Table) ->
368
370
    end.
369
371
 
370
372
%% Allowed conversions.
371
 
conversions(_OType, {line, LineType}, {line, LineType}) -> ok; 
 
373
conversions(_OType, {line, LineType}, {line, LineType}) -> ok;
372
374
conversions(edge, {line, _}, {line, all_line_call}) -> ok;
373
 
conversions(edge, From, {line, Line}) 
 
375
conversions(edge, From, {line, Line})
374
376
                 when is_atom(From), Line =/= all_line_call -> ok;
375
377
conversions(vertex, From, {line, line}) when is_atom(From) -> ok;
376
378
conversions(vertex, From, To) when is_atom(From), is_atom(To) -> ok;
377
379
conversions(edge, From, To) when is_atom(From), is_atom(To) -> ok;
378
380
%% "Extra":
379
 
conversions(edge, {line, Line}, To) 
 
381
conversions(edge, {line, Line}, To)
380
382
                 when is_atom(To), Line =/= all_line_call -> ok;
381
383
conversions(vertex, {line, line}, To) when is_atom(To) -> ok;
382
384
conversions(_OType, _From, _To) -> not_ok.
399
401
 
400
402
restriction(ROp, E1, Type1, NE1, Type2, NE2) ->
401
403
    {Column, _} = restr_op(ROp),
402
 
    case NE1 of 
 
404
    case NE1 of
403
405
        {call, union_of_family, _E} when ROp =:= '|' ->
404
406
            restriction(Column, Type1, E1, Type2, NE2);
405
407
        {call, union_of_family, _E} when ROp =:= '||' ->
455
457
            E = function_vertices_to_family(Type, OType, {constants, S}),
456
458
            {expr, Type, OType, E};
457
459
        [{Type1, [C1|_]}, {Type2, [C2|_]} | _] ->
458
 
            throw_error({type_mismatch, 
459
 
                         make_vertex(Type1, C1), 
 
460
            throw_error({type_mismatch,
 
461
                         make_vertex(Type1, C1),
460
462
                         make_vertex(Type2, C2)})
461
463
    end.
462
464
 
467
469
    check_mix(Cs, Type, OType, C);
468
470
check_mix([C | _], _Type0, _OType0, C0) ->
469
471
    throw_error({type_mismatch, xref_parser:t2s(C0), xref_parser:t2s(C)});
470
 
check_mix([], _Type0, _OType0, _C0) -> 
 
472
check_mix([], _Type0, _OType0, _C0) ->
471
473
    ok.
472
474
 
473
475
split(Types, Cs, Table) ->
478
480
    S0 = known_vertices(Type, Vs, Table),
479
481
    S = difference(S0, AllSoFar),
480
482
    case is_empty_set(S) of
481
 
        true -> 
 
483
        true ->
482
484
            split(Types, Vs, AllSoFar, Type, Table, L);
483
 
        false -> 
 
485
        false ->
484
486
            All = union(AllSoFar, S0),
485
 
            split(Types, Vs, All, Type, Table, 
 
487
            split(Types, Vs, All, Type, Table,
486
488
                  [{Type, to_external(S)} | L])
487
489
    end;
488
490
split([], Vs, All, Type, _Table, L) ->
491
493
        [C|_] -> throw_error({unknown_constant, make_vertex(Type, C)})
492
494
    end.
493
495
 
494
 
make_vertex(Type, C) -> 
 
496
make_vertex(Type, C) ->
495
497
    xref_parser:t2s({constant, Type, vertex, C}).
496
498
 
497
499
constant_vertices([{constant, _Type, edge, {A,B}} | Cs], L) ->
504
506
known_vertices('Fun', Cs, T) ->
505
507
    M = projection(1, Cs),
506
508
    F = union_of_family(restriction(fetch_value(v, T), M)),
507
 
    intersection(Cs, F);
 
509
    union(bifs(Cs), intersection(Cs, F));
508
510
known_vertices('Mod', Cs, T) ->
509
511
    intersection(Cs, fetch_value('M', T));
510
512
known_vertices('App', Cs, T) ->
512
514
known_vertices('Rel', Cs, T) ->
513
515
    intersection(Cs, fetch_value('R', T)).
514
516
 
 
517
bifs(Cs) ->
 
518
    specification({external,
 
519
                   fun({M,F,A}) -> xref_utils:is_builtin(M, F, A) end},
 
520
                  Cs).
 
521
 
515
522
function_vertices_to_family(function, vertex, E) ->
516
523
    {call, partition_family, 1, E};
517
524
function_vertices_to_family(_Type, _OType, E) ->
567
574
 
568
575
general(_ObjectType, FromType, ToType, X) when FromType =:= ToType ->
569
576
    X;
570
 
general(edge, {line, _LineType}, ToType, LEs) -> 
 
577
general(edge, {line, _LineType}, ToType, LEs) ->
571
578
    VEs = {projection, ?Q({external, fun({V1V2,_Ls}) -> V1V2 end}), LEs},
572
579
    general(edge, function, ToType, VEs);
573
580
general(edge, function, ToType, VEs) ->
574
 
    MEs = {projection, 
 
581
    MEs = {projection,
575
582
           ?Q({external, fun({{M1,_,_},{M2,_,_}}) -> {M1,M2} end}),
576
583
           VEs},
577
584
    general(edge, module, ToType, MEs);
580
587
    general(edge, application, ToType, AEs);
581
588
general(edge, application, release, AEs) ->
582
589
    {image, {get, ae}, AEs};
583
 
general(vertex, {line, _LineType}, ToType, L) -> 
 
590
general(vertex, {line, _LineType}, ToType, L) ->
584
591
    V = {partition_family, ?Q(1), {domain, L}},
585
592
    general(vertex, function, ToType, V);
586
593
general(vertex, function, ToType, V) ->
595
602
special(_ObjectType, FromType, ToType, X) when FromType =:= ToType ->
596
603
    X;
597
604
special(edge, {line, _LineType}, {line, all_line_call}, Calls) ->
598
 
   {put, ?T(mods), 
599
 
       {projection, 
600
 
        ?Q({external, fun({{{M1,_,_},{M2,_,_}},_}) -> {M1,M2} end}), 
 
605
   {put, ?T(mods),
 
606
       {projection,
 
607
        ?Q({external, fun({{{M1,_,_},{M2,_,_}},_}) -> {M1,M2} end}),
601
608
        Calls},
602
 
       {put, ?T(def_at), 
 
609
       {put, ?T(def_at),
603
610
           {union, {image, {get, def_at},
604
 
                           {union, {domain, {get, ?T(mods)}}, 
 
611
                           {union, {domain, {get, ?T(mods)}},
605
612
                                   {range, {get, ?T(mods)}}}}},
606
613
           {fun funs_to_lines/2,
607
614
                   {get, ?T(def_at)}, Calls}}};
608
615
special(edge, function, {line, LineType}, VEs) ->
609
 
    Var = if 
 
616
    Var = if
610
617
              LineType =:= line -> call_at;
611
618
              LineType =:= export_call -> e_call_at;
612
619
              LineType =:= local_call -> l_call_at;
615
622
    line_edges(VEs, Var);
616
623
special(edge, module, ToType, MEs) ->
617
624
    VEs = {image,
618
 
           {projection, 
 
625
           {projection,
619
626
            ?Q({external, fun(FE={{M1,_,_},{M2,_,_}}) -> {{M1,M2},FE} end}),
620
 
            {union, 
 
627
            {union,
621
628
             {image, {get, e},
622
629
              {projection, ?Q({external, fun({M1,_M2}) -> M1 end}), MEs}}}},
623
630
           MEs},
629
636
    AEs = {inverse_image, {get, ae}, REs},
630
637
    special(edge, application, ToType, AEs);
631
638
special(vertex, function, {line, _LineType}, V) ->
632
 
    {restriction, 
 
639
    {restriction,
633
640
       {union_of_family, {restriction, {get, def_at}, {domain, V}}},
634
641
       {union_of_family, V}};
635
642
special(vertex, module, ToType, M) ->
643
650
    special(vertex, application, ToType, A).
644
651
 
645
652
line_edges(VEs, CallAt) ->
646
 
    {put, ?T(ves), VEs, 
647
 
        {put, ?T(m1), 
648
 
             {projection, ?Q({external, fun({{M1,_,_},_}) -> M1 end}), 
 
653
    {put, ?T(ves), VEs,
 
654
        {put, ?T(m1),
 
655
             {projection, ?Q({external, fun({{M1,_,_},_}) -> M1 end}),
649
656
              {get, ?T(ves)}},
650
657
             {image, {projection, ?Q({external, fun(C={VV,_L}) -> {VV,C} end}),
651
658
                      {union, {image, {get, CallAt}, {get, ?T(m1)}}}},
652
659
                     {get, ?T(ves)}}}}.
653
660
 
654
 
%% {(((v1,l1),(v2,l2)),l) : 
 
661
%% {(((v1,l1),(v2,l2)),l) :
655
662
%%       (v1,l1) in DefAt and (v2,l2) in DefAt and ((v1,v2),L) in CallAt}
656
663
funs_to_lines(DefAt, CallAt) ->
657
664
    T1 = multiple_relative_product({DefAt, DefAt}, projection(1, CallAt)),
765
772
 
766
773
%% Traverses the expression again, this time using more or less the
767
774
%% inverse of the table created by find_nodes. The first time a node
768
 
%% is visited, its children are traversed, the following times a 
 
775
%% is visited, its children are traversed, the following times a
769
776
%% get instructions are inserted (using the saved value).
770
777
make_instructions(N, UserVars, D) ->
771
778
    {D1, Is0} = make_instrs(N, D, []),
777
784
 
778
785
make_more_instrs([UV | UVs], D, Is) ->
779
786
    case dict:find(UV, D) of
780
 
        error -> 
 
787
        error ->
781
788
            make_more_instrs(UVs, D, Is);
782
 
        _Else -> 
 
789
        _Else ->
783
790
            {ND, NIs} = make_instrs(UV, D, Is),
784
791
            make_more_instrs(UVs, ND, [pop | NIs])
785
792
    end;
844
851
    evaluate(P, T, [Val | S]);
845
852
evaluate([{get, Var} | P], T, S) when is_atom(Var) -> % predefined
846
853
    Value = fetch_value(Var, T),
847
 
    Val = case Value of 
 
854
    Val = case Value of
848
855
              {R, _} -> R; % relation
849
856
              _ -> Value   % simple set
850
857
          end,
851
 
    evaluate(P, T, [Val | S]);    
 
858
    evaluate(P, T, [Val | S]);
852
859
evaluate([{get, {inverse, Var}} | P], T, S) -> % predefined, inverse
853
860
    {_, R} = fetch_value(Var, T),
854
 
    evaluate(P, T, [R | S]);    
 
861
    evaluate(P, T, [R | S]);
855
862
evaluate([{get, {user, Var}} | P], T, S) ->
856
863
    Val = fetch_value(Var, T),
857
 
    evaluate(P, T, [Val | S]);    
 
864
    evaluate(P, T, [Val | S]);
858
865
evaluate([{get, Var} | P], T, S) -> % tmp
859
866
    evaluate(P, T, [dict:fetch(Var, T) | S]);
860
867
evaluate([{save, Var={tmp, _}} | P], T, S=[Val | _]) ->
862
869
    evaluate(P, dict:store(Var, Val, T1), S);
863
870
evaluate([{save, {user, Name}} | P], T, S=[Val | _]) ->
864
871
    #xref_var{vtype = user, otype = OType, type = Type} = dict:fetch(Name, T),
865
 
    NewVar = #xref_var{name = Name, value = Val, 
 
872
    NewVar = #xref_var{name = Name, value = Val,
866
873
                       vtype = user, otype = OType, type = Type},
867
874
    T1 = update_graph_counter(Val, +1, T),
868
875
    NT = dict:store(Name, NewVar, T1),
889
896
                error when Inc =:= 1 ->
890
897
                    dict:store(Value, 1, T)
891
898
            end;
892
 
        _EXIT -> 
 
899
        _EXIT ->
893
900
            T
894
901
    end.
895
902