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/.
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
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.''
16
%% $Id: core_lib.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $
18
%% Purpose: Core Erlang abstract syntax functions.
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]).
30
%% -compile([export_all]).
32
-include("core_parse.hrl").
34
%% get_anno(Core) -> Anno.
35
%% set_anno(Core, Anno) -> Core.
36
%% Generic get/set annotation.
38
get_anno(C) -> element(2, C).
39
set_anno(C, A) -> setelement(2, C, A).
41
%% is_atomic(Expr) -> true | false.
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.
52
%% is_literal(Expr) -> true | false.
54
is_literal(#c_cons{hd=H,tl=T}) ->
56
true -> is_literal(T);
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).
63
is_literal_list(Es) -> lists:all(fun is_literal/1, Es).
66
lists:all(fun (#c_bitstr{val=E,size=S}) ->
67
is_literal(E) and is_literal(S)
70
%% is_simple(Expr) -> true | false.
72
is_simple(#c_var{}) -> true;
73
is_simple(#c_cons{hd=H,tl=T}) ->
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).
82
is_simple_list(Es) -> lists:all(fun is_simple/1, Es).
85
lists:all(fun (#c_bitstr{val=E,size=S}) ->
86
is_simple(E) and is_simple(S)
89
%% is_simple_top(Expr) -> true | false.
90
%% Only check if the top-level is a simple.
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).
98
%% literal_value(LitExpr) -> Value.
99
%% Return the value of LitExpr.
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)).
112
literal_value_list(Vals) -> lists:map(fun literal_value/1, Vals).
114
%% make_literal(Value) -> LitExpr.
115
%% Make a literal expression from an Erlang value.
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))}.
126
make_literal_list(Vals) -> lists:map(fun make_literal/1, Vals).
128
%% make_values([CoreExpr] | CoreExpr) -> #c_values{} | CoreExpr.
129
%% Make a suitable values structure, expr or values, depending on
132
make_values([E]) -> E;
133
make_values([H|_]=Es) -> #c_values{anno=get_anno(H),es=Es};
134
make_values([]) -> #c_values{es=[]};
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
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.
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),
153
map(F, #c_values{es=Es}=R) ->
154
F(R#c_values{es=map_list(F, Es)});
156
map(F, #c_alias{var=Var, pat=Pat}=R) ->
157
F(R#c_alias{var=map(F, Var),
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)});
165
map(F, #c_fun{vars=Vars, body=Body}=R) ->
166
F(R#c_fun{vars=map_list(F, Vars),
168
map(F, #c_let{vars=Vs, arg=Arg, body=Body}=R) ->
169
F(R#c_let{vars=map_list(F, Vs),
172
map(F, #c_letrec{defs=Fs,body=Body}=R) ->
173
F(R#c_letrec{defs=map_list(F, Fs),
175
map(F, #c_seq{arg=Arg, body=Body}=R) ->
176
F(R#c_seq{arg=map(F, Arg),
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),
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),
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),
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.
209
map_list(F, L) -> lists:map(fun (E) -> map(F, E) end, L).
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)
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));
224
fold(F, Acc, #c_alias{pat=P,var=V}=R) ->
225
F(R, fold(F, fold(F, Acc, P), V));
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));
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
260
fold_list(F, Acc, L) ->
261
lists:foldl(fun (E, A) -> fold(F, A, E) end, Acc, L).
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)
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);
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);
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);
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
349
mapfold_list(F, Acc, L) ->
350
lists:mapfoldl(fun (E, A) -> mapfold(F, A, E) end, Acc, L).
352
%% is_var_used(VarName, Expr) -> true | false.
353
%% Test if the variable VarName is used in Expr.
355
is_var_used(V, B) -> vu_body(V, B).
357
vu_body(V, #c_values{es=Es}) ->
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
366
false -> vu_expr(V, T)
368
vu_expr(V, #c_tuple{es=Es}) ->
370
vu_expr(V, #c_binary{segments=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
376
false -> vu_body(V, B)
378
vu_expr(V, #c_let{vars=Vs,arg=Arg,body=B}) ->
379
case vu_body(V, Arg) of
382
%% Variables in let shadow previous variables.
383
case vu_var_list(V, Vs) of
385
false -> vu_body(V, B)
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
391
false -> vu_body(V, B)
393
vu_expr(V, #c_seq{arg=Arg,body=B}) ->
394
case vu_expr(V, Arg) of
396
false -> vu_body(V, B)
398
vu_expr(V, #c_case{arg=Arg,clauses=Cs}) ->
399
case vu_expr(V, Arg) of
401
false -> vu_clauses(V, Cs)
403
vu_expr(V, #c_receive{clauses=Cs,timeout=T,action=A}) ->
404
case vu_clauses(V, Cs) of
407
case vu_expr(V, T) of
409
false -> vu_body(V, A)
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
418
vu_expr(V, #c_catch{body=B}) ->
420
vu_expr(V, #c_try{arg=E,vars=Vs,body=B,evars=Evs,handler=H}) ->
421
case vu_body(V, E) of
424
%% Variables shadow previous ones.
425
case case vu_var_list(V, Vs) of
427
false -> vu_body(V, B)
431
case vu_var_list(V, Evs) of
433
false -> vu_body(V, H)
437
vu_expr(_, _) -> false. %Everything else
439
vu_expr_list(V, Es) ->
440
lists:any(fun(E) -> vu_expr(V, E) end, Es).
442
vu_seg_list(V, Ss) ->
443
lists:any(fun (#c_bitstr{val=Val,size=Size}) ->
444
case vu_expr(V, Val) of
446
false -> vu_expr(V, Size)
450
%% vu_clause(VarName, Clause) -> true | false.
451
%% vu_clauses(VarName, [Clause]) -> true | false.
452
%% Have to get the pattern results right.
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
461
false ->vu_body(V, B)
466
lists:any(fun(C) -> vu_clause(V, C) end, Cs).
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.
473
%%vu_pattern(V, Pat) -> vu_pattern(V, Pat, {false,false}).
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)
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)
491
vu_pattern(_, _, St) -> St.
493
vu_pattern_list(V, Ps) -> vu_pattern_list(V, Ps, {false,false}).
495
vu_pattern_list(V, Ps, St0) ->
496
lists:foldl(fun(P, St) -> vu_pattern(V, P, St) end, St0, Ps).
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}
506
%% vu_var_list(VarName, [Var]) -> true | false.
508
vu_var_list(V, Vs) ->
509
lists:any(fun (#c_var{name=V2}) -> V =:= V2 end, Vs).