4
%% Copyright Ericsson AB 2013. All Rights Reserved.
6
%% The contents of this file are subject to the Erlang Public License,
7
%% Version 1.1, (the "License"); you may not use this file except in
8
%% compliance with the License. You should have received a copy of the
9
%% Erlang Public License along with this software. If not, it can be
10
%% retrieved online at http://www.erlang.org/.
12
%% Software distributed under the License is distributed on an "AS IS"
13
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
%% the License for the specific language governing rights and limitations
21
-export([parse_transform/2,
24
%% Expand function definition forms of parameterized module.
25
%% The code is based on the code in sys_expand_pmod which used to be
26
%% included in the compiler, but details are different because
27
%% sys_pre_expand has not been run. In particular:
29
%% * Record definitions are still present and must be handled.
31
%% * (Syntatic) local calls may actually be calls to an imported
32
%% funtion or a BIF. It is a local call if and only if there
33
%% is a definition for the function in the module.
35
%% * When we introduce the module parameters and 'THIS' in each
36
%% function, we must artificially use it to avoid a warning for
39
%% * On the other hand, we don't have to worry about module_info/0,1
40
%% because they have not been added yet.
42
-record(pmod, {parameters,
46
parse_transform(Forms0, _Options) ->
48
Forms = transform(Forms0),
49
case erase(?MODULE) of
53
File = get_file(Forms),
54
{error,[{File,Errors}],[]}
57
format_error(extends_self) ->
58
"cannot extend from self";
59
format_error(define_instance) ->
60
"defining instance function not allowed in parameterized module".
62
add_error(Line, Error) ->
63
put(?MODULE, get(?MODULE) ++ [{Line,?MODULE,Error}]).
65
get_file([{attribute,_,file,{File,_}}|_]) -> File;
66
get_file([_|T]) -> get_file(T).
69
Def = collect_defined(Forms0),
70
{Base,ModAs,Forms1} = attribs(Forms0, [], undefined, []),
71
{Mod,Ps0} = case ModAs of
79
pmod_expand(Forms1, Mod, Base, Ps0, Def)
83
NewFs0 = maybe_extend(Base, Mod, Ps0),
84
NewExps = collect_defined(NewFs0),
85
Forms3 = add_attributes(Forms2, [{attribute,0,export,NewExps}]),
86
add_new_funcs(Forms3, NewFs0).
88
pmod_expand(Forms0, Mod, Base, Ps0, Def) ->
89
Ps = if is_atom(Base) ->
94
St0 = #pmod{parameters=Ps,defined=gb_sets:from_list(Def)},
95
{Forms1,_} = forms(Forms0, St0),
96
Forms2 = update_exps(Forms1),
97
Forms3 = update_forms(Forms2),
98
NewFs0 = add_instance(Mod, Ps, []),
99
NewFs = ensure_new(Base, Ps0, NewFs0),
100
Forms = add_new_funcs(Forms3, NewFs),
101
NewExps = collect_defined(NewFs),
102
add_attributes(Forms, [{attribute,0,export,NewExps}]).
104
add_attributes([{attribute,_,module,_}=F|Fs], Attrs) ->
106
add_attributes([F|Fs], Attrs) ->
107
[F|add_attributes(Fs, Attrs)].
109
add_new_funcs([{eof,_}|_]=Fs, NewFs) ->
111
add_new_funcs([F|Fs], Es) ->
112
[F|add_new_funcs(Fs, Es)].
114
maybe_extend([], _, _) ->
115
%% No 'extends' attribute.
117
maybe_extend(Base, _Mod, undefined) ->
118
%% There is a an 'extends' attribute; the module is not parameterized.
119
Name = '$handle_undefined_function',
120
Args = [{var,0,'Func'},{var,0,'Args'}],
121
Body = [make_apply({atom,0,Base}, {var,0,'Func'}, {var,0,'Args'})],
122
F = {function,0,Name,2,[{clause,0,Args,[],Body}]},
124
maybe_extend(Base, Mod, Ps) ->
125
%% There is a an 'extends' attribute; the module is parameterized.
126
Name = '$handle_undefined_function',
127
Args = [{var,0,'Func'},{var,0,'Args'}],
128
DontCares = [{var,0,'_'} || _ <- Ps],
129
TuplePs = {tuple,0,[{atom,0,Mod},{var,0,'BaseVars'}|DontCares]},
130
G = [{call,0,{atom,0,is_atom},
131
[{call,0,{atom,0,element},
132
[{integer,0,1},{var,0,'BaseVars'}]}]}],
133
FixedArgs = make_lists_rev([{var,0,'Rs'},
134
{cons,0,{var,0,'BaseVars'},{nil,0}}]),
135
Body = [{'case',0,make_lists_rev([{var,0,'Args'}]),
136
[{clause,0,[{cons,0,TuplePs,{var,0,'Rs'}}],[G],
137
[make_apply({atom,0,Base}, {var,0,'Func'}, FixedArgs)]},
138
{clause,0,[{var,0,'_'}],[],
139
[make_apply({atom,0,Base}, {var,0,'Func'}, {var,0,'Args'})]}
141
F = {function,0,Name,2,[{clause,0,Args,[],Body}]},
144
make_apply(M, F, A) ->
145
{call,0,{remote,0,{atom,0,erlang},{atom,0,apply}},[M,F,A]}.
147
make_lists_rev(As) ->
148
{call,0,{remote,0,{atom,0,lists},{atom,0,reverse}},As}.
150
ensure_new(Base, Ps, Fs) ->
155
add_new(Base, Ps, Fs)
158
has_new([{function,_L,new,_A,_Cs} | _Fs]) ->
165
add_new(Base, Ps, Fs) ->
166
Vs = [{var,0,V} || V <- Ps],
167
As = if is_atom(Base) ->
168
[{call,0,{remote,0,{atom,0,Base},{atom,0,new}},Vs} | Vs];
172
Body = [{call,0,{atom,0,instance},As}],
173
add_func(new, Vs, Body, Fs).
175
add_instance(Mod, Ps, Fs) ->
176
Vs = [{var,0,V} || V <- Ps],
177
AbsMod = [{tuple,0,[{atom,0,Mod}|Vs]}],
178
add_func(instance, Vs, AbsMod, Fs).
180
add_func(Name, Args, Body, Fs) ->
182
F = {function,0,Name,A,[{clause,0,Args,[],Body}]},
185
collect_defined(Fs) ->
186
[{N,A} || {function,_,N,A,_} <- Fs].
188
attribs([{attribute,Line,module,{Mod,_}=ModAs}|T], Base, _, Acc) ->
189
attribs(T, Base, ModAs, [{attribute,Line,module,Mod}|Acc]);
190
attribs([{attribute,_,module,Mod}=H|T], Base, _, Acc) ->
191
attribs(T, Base, Mod, [H|Acc]);
192
attribs([{attribute,Line,extends,Base}|T], Base0, Ps, Acc) when is_atom(Base) ->
199
add_error(Line, extends_self),
200
attribs(T, Base0, Ps, Acc);
202
attribs(T, Base, Ps, Acc)
204
attribs([H|T], Base, Ps, Acc) ->
205
attribs(T, Base, Ps, [H|Acc]);
206
attribs([], Base, Ps, Acc) ->
207
{Base,Ps,lists:reverse(Acc)}.
209
%% This is extremely simplistic for now; all functions get an extra
210
%% parameter, whether they need it or not, except for static functions.
212
update_function_name({F,A}) when F =/= new ->
214
update_function_name(E) ->
217
update_forms([{function,L,N,A,Cs}|Fs]) when N =/= new ->
218
[{function,L,N,A+1,Cs}|update_forms(Fs)];
219
update_forms([F|Fs]) ->
220
[F|update_forms(Fs)];
224
update_exps([{attribute,Line,export,Es0}|T]) ->
225
Es = [update_function_name(E) || E <- Es0],
226
[{attribute,Line,export,Es}|update_exps(T)];
227
update_exps([H|T]) ->
232
%% Process the program forms.
234
forms([F0|Fs0],St0) ->
235
{F1,St1} = form(F0,St0),
236
{Fs1,St2} = forms(Fs0,St1),
241
%% Only function definitions are of interest here. State is not updated.
242
form({function,Line,instance,_Arity,_Clauses}=F,St) ->
243
add_error(Line, define_instance),
245
form({function,Line,Name0,Arity0,Clauses0},St) when Name0 =/= new ->
246
{Name,Arity,Clauses} = function(Name0, Arity0, Clauses0, St),
247
{{function,Line,Name,Arity,Clauses},St};
248
%% Pass anything else through
249
form(F,St) -> {F,St}.
251
function(Name, Arity, Clauses0, St) ->
252
Clauses1 = clauses(Clauses0,St),
253
{Name,Arity,Clauses1}.
255
clauses([C|Cs],#pmod{parameters=Ps}=St) ->
256
{clause,L,H,G,B0} = clause(C,St),
257
T = {tuple,L,[{var,L,V} || V <- ['_'|Ps]]},
258
B = [{match,L,{var,L,'_'},{var,L,V}} || V <- ['THIS'|Ps]] ++ B0,
259
[{clause,L,H++[{match,L,T,{var,L,'THIS'}}],G,B}|clauses(Cs,St)];
260
clauses([],_St) -> [].
262
clause({clause,Line,H,G,B0},St) ->
263
%% We never update H and G, so we will just copy them.
265
{clause,Line,H,G,B1}.
267
pattern_grp([{bin_element,L1,E1,S1,T1} | Fs],St) ->
280
[{bin_element,L1,expr(E1,St),S2,T2} | pattern_grp(Fs,St)];
281
pattern_grp([],_St) ->
286
bit_types([Atom | Rest]) when is_atom(Atom) ->
287
[Atom | bit_types(Rest)];
288
bit_types([{Atom, Integer} | Rest]) when is_atom(Atom), is_integer(Integer) ->
289
[{Atom, Integer} | bit_types(Rest)].
296
expr({var,_L,_V}=Var,_St) ->
298
expr({integer,_Line,_I}=Integer,_St) -> Integer;
299
expr({float,_Line,_F}=Float,_St) -> Float;
300
expr({atom,_Line,_A}=Atom,_St) -> Atom;
301
expr({string,_Line,_S}=String,_St) -> String;
302
expr({char,_Line,_C}=Char,_St) -> Char;
303
expr({nil,_Line}=Nil,_St) -> Nil;
304
expr({cons,Line,H0,T0},St) ->
308
expr({lc,Line,E0,Qs0},St) ->
309
Qs1 = lc_bc_quals(Qs0,St),
312
expr({bc,Line,E0,Qs0},St) ->
313
Qs1 = lc_bc_quals(Qs0,St),
316
expr({tuple,Line,Es0},St) ->
317
Es1 = expr_list(Es0,St),
319
expr({record,Line,Name,Is0},St) ->
320
Is = record_fields(Is0,St),
321
{record,Line,Name,Is};
322
expr({record,Line,E0,Name,Is0},St) ->
324
Is = record_fields(Is0,St),
325
{record,Line,E,Name,Is};
326
expr({record_field,Line,E0,Name,Key},St) ->
328
{record_field,Line,E,Name,Key};
329
expr({block,Line,Es0},St) ->
332
expr({'if',Line,Cs0},St) ->
333
Cs1 = icr_clauses(Cs0,St),
335
expr({'case',Line,E0,Cs0},St) ->
337
Cs1 = icr_clauses(Cs0,St),
338
{'case',Line,E1,Cs1};
339
expr({'receive',Line,Cs0},St) ->
340
Cs1 = icr_clauses(Cs0,St),
341
{'receive',Line,Cs1};
342
expr({'receive',Line,Cs0,To0,ToEs0},St) ->
344
ToEs1 = exprs(ToEs0,St),
345
Cs1 = icr_clauses(Cs0,St),
346
{'receive',Line,Cs1,To1,ToEs1};
347
expr({'try',Line,Es0,Scs0,Ccs0,As0},St) ->
349
Scs1 = icr_clauses(Scs0,St),
350
Ccs1 = icr_clauses(Ccs0,St),
352
{'try',Line,Es1,Scs1,Ccs1,As1};
353
expr({'fun',_,{function,_,_,_}}=ExtFun,_St) ->
355
expr({'fun',Line,Body},St) ->
358
Cs1 = fun_clauses(Cs0,St),
359
{'fun',Line,{clauses,Cs1}};
360
{function,F,A} = Function ->
361
{F1,A1} = update_function_name({F,A}),
363
{'fun',Line,Function};
365
%% Must rewrite local fun-name to a fun that does a
366
%% call with the extra THIS parameter.
367
As = make_vars(A, Line),
368
As1 = As ++ [{var,Line,'THIS'}],
369
Call = {call,Line,{atom,Line,F1},As1},
370
Cs = [{clause,Line,As,[],[Call]}],
371
{'fun',Line,{clauses,Cs}}
373
{function,_M,_F,_A} = Fun4 -> %This is an error in lint!
376
expr({call,Lc,{atom,_,instance}=Name,As0},St) ->
377
%% All local functions 'instance(...)' are static by definition,
378
%% so they do not take a 'THIS' argument when called
379
As1 = expr_list(As0,St),
381
expr({call,Lc,{atom,_,new}=Name,As0},St) ->
382
%% All local functions 'new(...)' are static by definition,
383
%% so they do not take a 'THIS' argument when called
384
As1 = expr_list(As0,St),
386
expr({call,Lc,{atom,_Lf,F}=Atom,As0}, #pmod{defined=Def}=St) ->
387
As1 = expr_list(As0,St),
388
case gb_sets:is_member({F,length(As0)}, Def) of
390
%% BIF or imported function.
393
%% Local function call - needs THIS parameter.
394
{call,Lc,Atom,As1 ++ [{var,0,'THIS'}]}
396
expr({call,Line,F0,As0},St) ->
397
%% Other function call
399
As1 = expr_list(As0,St),
401
expr({'catch',Line,E0},St) ->
404
expr({match,Line,P,E0},St) ->
407
expr({bin,Line,Fs},St) ->
408
Fs2 = pattern_grp(Fs,St),
410
expr({op,Line,Op,A0},St) ->
413
expr({op,Line,Op,L0,R0},St) ->
417
%% The following are not allowed to occur anywhere!
418
expr({remote,Line,M0,F0},St) ->
423
expr_list([E0|Es],St) ->
425
[E1|expr_list(Es,St)];
426
expr_list([],_St) -> [].
428
record_fields([{record_field,L,K,E0}|T],St) ->
430
[{record_field,L,K,E}|record_fields(T,St)];
431
record_fields([],_) -> [].
433
icr_clauses([C0|Cs],St) ->
435
[C1|icr_clauses(Cs,St)];
436
icr_clauses([],_St) -> [].
438
lc_bc_quals([{generate,Line,P,E0}|Qs],St) ->
440
[{generate,Line,P,E1}|lc_bc_quals(Qs,St)];
441
lc_bc_quals([{b_generate,Line,P,E0}|Qs],St) ->
443
[{b_generate,Line,P,E1}|lc_bc_quals(Qs,St)];
444
lc_bc_quals([E0|Qs],St) ->
446
[E1|lc_bc_quals(Qs,St)];
447
lc_bc_quals([],_St) -> [].
449
fun_clauses([C0|Cs],St) ->
451
[C1|fun_clauses(Cs,St)];
452
fun_clauses([],_St) -> [].
457
make_vars(N, M, L) when N =< M ->
458
V = list_to_atom("X"++integer_to_list(N)),
459
[{var,L,V} | make_vars(N + 1, M, L)];
460
make_vars(_, _, _) ->