1
1
%% =====================================================================
2
%% @doc Core Erlang pattern matching compiler.
4
%% <p>For reference, see Simon L. Peyton Jones "The Implementation of
5
%% Functional Programming Languages", chapter 5 (by Phil Wadler).</p>
8
%% Copyright (C) 1999-2002 Richard Carlsson
2
%% Copyright (C) 1999-2004 Richard Carlsson
10
4
%% This library is free software; you can redistribute it and/or modify
11
5
%% it under the terms of the GNU Lesser General Public License as
22
16
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25
%% Author contact: richardc@csd.uu.se
21
%% @author Richard Carlsson <richardc@it.uu.se>
22
%% @copyright 2000-2006 Richard Carlsson
24
%% @doc Core Erlang pattern matching compiler.
26
%% <p>For reference, see Simon L. Peyton Jones "The Implementation of
27
%% Functional Programming Languages", chapter 5 (by Phil Wadler).</p>
29
29
%% @type cerl() = cerl:cerl().
30
30
%% Abstract Core Erlang syntax trees.
31
31
%% @type cerl_records() = cerl:cerl_records().
32
32
%% An explicit record representation of Core Erlang syntax trees.
34
%% TODO: Binary-patterns
36
34
-module(cerl_pmatch).
38
-export([clauses/2, module/2, expr/2, core_transform/2]).
36
-define(NO_UNUSED, true).
40
-export([transform/2, core_transform/2, expr/2]).
40
43
-import(lists, [all/2, splitwith/2, foldr/3, keysort/2, foldl/3,
46
-define(binary_id, {binary}).
47
-define(cons_id, {cons}).
48
-define(tuple_id, {tuple}).
49
-define(literal_id(V), V).
43
52
%% @spec core_transform(Module::cerl_records(), Options::[term()]) ->
46
55
%% @doc Transforms a module represented by records. See
47
%% <code>module/2</code> for details.
56
%% <code>transform/2</code> for details.
49
58
%% <p>Use the compiler option <code>{core_transform, cerl_pmatch}</code>
50
59
%% to insert this function as a compilation pass.</p>
54
64
core_transform(M, Opts) ->
55
cerl:to_records(module(cerl:from_records(M), Opts)).
58
%% @spec module(Module::cerl(), Options::[term()]) -> cerl()
65
cerl:to_records(transform(cerl:from_records(M), Opts)).
70
%% @spec transform(Module::cerl(), Options::[term()]) -> cerl()
60
72
%% @doc Rewrites all <code>case</code>-clauses in <code>Module</code>.
61
73
%% <code>receive</code>-clauses are not affected. Currently, no options
189
202
%% body of a final catch-all clause.
191
204
match_con([V | Vs], Cs, Else, Env) ->
193
case group_con(Cs) of
205
case group_con(Cs) of
195
207
%% Don't create a group type switch if there is only one
198
209
make_switch(V, [match_congroup(D, Vs, Cs, Else, Env)
199
|| {_, D, Cs} <- Gs],
210
|| {D, _, Cs} <- Gs],
202
213
Cs1 = [match_typegroup(T, V, Vs, Gs, Else, Env)
203
|| {_, T, Gs} <- Ts],
214
|| {T, _, Gs} <- Ts],
204
215
make_switch(V, Cs1, Else, Env)
207
match_typegroup(_T, _V, Vs, [{_, D, Cs}], Else, Env) ->
219
match_typegroup(_T, _V, Vs, [{D, _, Cs}], Else, Env) when element(1, D) /= ?binary_id ->
208
220
%% Don't create a group type switch if there is only one constructor
209
%% in the group. (Note that this always happens for the empty list.)
221
%% in the group. (Note that this always happens for '[]'.)
222
%% Special case for binaries which always get a group switch
210
223
match_congroup(D, Vs, Cs, Else, Env);
211
224
match_typegroup(T, V, Vs, Gs, Else, Env) ->
212
225
Body = make_switch(V, [match_congroup(D, Vs, Cs, Else, Env)
213
|| {_, D, Cs} <- Gs],
226
|| {D, _, Cs} <- Gs],
215
228
typetest_clause(T, V, Body, Env).
217
match_congroup({<<0>>, Segs}, Vs, Cs, Else, Env) ->
218
Body = match(Vs, Cs, Else, Env),
219
cerl:c_clause([make_pat(<<0>>, Segs)], Body);
230
match_congroup({?binary_id, Segs}, Vs, Cs, _Else, Env) ->
232
Guard = cerl:c_primop(cerl:c_atom(set_label), [cerl:c_int(Ref)]),
233
NewElse = cerl:c_primop(cerl:c_atom(goto_label), [cerl:c_int(Ref)]),
234
Body = match(Vs, Cs, NewElse, Env),
235
cerl:c_clause([make_pat(?binary_id, Segs)], Guard, Body);
221
237
match_congroup({D, A}, Vs, Cs, Else, Env) ->
222
238
Vs1 = new_vars(A, Env),
224
240
cerl:c_clause([make_pat(D, Vs1)], Body).
226
242
make_switch(V, Cs, Else, Env) ->
227
cerl:c_case(V, if Else == none -> Cs;
243
cerl:c_case(V, if Else =:= none -> Cs;
228
244
true -> Cs ++ [cerl:c_clause([new_var(Env)],
232
%% We preserve the relative order of different constructors as they were
233
%% originally listed. This is done by including the clause number in the
234
%% key used for sorting the clauses by type (this stage does not
235
%% distingush between different value instances of atoms, integers and
236
%% floats). The clauses are then grouped by type. After grouping by
237
%% constructor (this separates value instances), the groups are then
238
%% sorted again by the clause number of the first clause of each group.
248
%% We preserve the relative order of different-type constructors as they
249
%% were originally listed. This is done by tracking the clause numbers.
241
252
{Cs1, _} = mapfoldl(fun (C, N) ->
243
254
Ps1 = sub_pats(P) ++ Ps,
244
255
G = cerl:clause_guard(C),
245
256
B = cerl:clause_body(C),
246
{{{con_type(P), N}, con_desc(P),
247
cerl:update_c_clause(C, Ps1, G, B)},
257
C1 = cerl:update_c_clause(C, Ps1, G, B),
251
%% Group by descriptor (separates different integers, atoms, etc.)
252
%% Constructors that have the same descriptor have the same type.
253
Css = group(keysort(1, Cs1), fun ({_,D,_}) -> D end),
254
Gs = [{T, D, [C || {_,_,C} <- Cs]} || Cs=[{T,D,_}|_] <- Css],
255
%% Group by type class (groups different-arity tuples together).
256
Css1 = group(Gs, fun ({{T,_},_,_}) -> typeclass(T) end),
257
Gs1 = [{N, T, Cs} || Cs=[{{T,N},_,_}|_] <- Css1],
258
%% Sort type-groups by original clause order
262
%% Sort and group constructors.
263
Css = group(keysort(1, Cs1), fun ({D,_,_}) -> D end),
264
%% Sort each group "back" by line number, and move the descriptor
265
%% and line number to the wrapper for the group.
266
Gs = [finalize_congroup(Cs) || Cs <- Css],
267
%% Group by type only (put e.g. different-arity tuples together).
268
Gss = group(Gs, fun ({D,_,_}) -> con_desc_type(D) end),
269
%% Sort and wrap the type groups.
270
Ts = [finalize_typegroup(Gs) || Gs <- Gss],
271
%% Sort type-groups by first clause order
274
finalize_congroup(Cs) ->
275
[{D,N,_}|_] = Cs1 = keysort(2, Cs),
276
{D, N, [C || {_,_,C} <- Cs1]}.
278
finalize_typegroup(Gs) ->
279
[{D,N,_}|_] = Gs1 = keysort(2, Gs),
280
{con_desc_type(D), N, Gs1}.
261
282
%% Since Erlang clause patterns can contain "alias patterns", we must
262
283
%% eliminate these, by turning them into let-definitions in the guards
266
287
[P | Ps] = cerl:clause_pats(C),
267
288
B = cerl:clause_body(C),
268
unalias(P, V, Ps, B, C).
289
G = cerl:clause_guard(C),
290
unalias(P, V, Ps, B, G, C).
270
unalias(P, V, Ps, B, C) ->
292
unalias(P, V, Ps, B, G, C) ->
271
293
case cerl:type(P) of
273
B1 = make_let([cerl:alias_var(P)], V, B),
274
unalias(cerl:alias_pat(P), V, Ps, B1, C);
276
cerl:update_c_clause(C, [P | Ps], cerl:clause_guard(C), B)
279
%% This returns a constructor type, for sorting of clauses. It does not
280
%% distinguish between value instances of atoms, integers and floats.
287
{tuple, cerl:tuple_arity(E)};
291
case cerl:concrete(E) of
292
V when is_atom(V) -> atom;
293
V when is_integer(V) -> integer;
294
V when is_float(V) -> float;
295
T when is_tuple(T) -> {tuple, size(T)};
300
throw({bad_constructor, E})
303
%% Getting the generic class for type grouping.
305
typeclass({tuple, _}) -> tuple;
295
V1 = cerl:alias_var(P),
296
B1 = make_let([V1], V, B),
297
G1 = make_let([V1], V, G),
298
unalias(cerl:alias_pat(P), V, Ps, B1, G1, C);
300
cerl:update_c_clause(C, [P | Ps], G, B)
308
303
%% Generating a type-switch clause
310
typetest_clause({tuple, _}, V, E, _Env) ->
311
typetest_clause_1(is_tuple, V, E);
305
typetest_clause([], _V, E, _Env) ->
306
cerl:c_clause([cerl:c_nil()], E);
312
307
typetest_clause(atom, V, E, _Env) ->
313
308
typetest_clause_1(is_atom, V, E);
314
309
typetest_clause(integer, V, E, _Env) ->
318
313
typetest_clause(cons, _V, E, Env) ->
319
314
[V1, V2] = new_vars(2, Env),
320
315
cerl:c_clause([cerl:c_cons(V1, V2)], E); % there is no 'is cons'
321
typetest_clause([], _V, E, _Env) ->
322
cerl:c_clause([cerl:c_nil()], E);
316
typetest_clause(tuple, V, E, _Env) ->
317
typetest_clause_1(is_tuple, V, E);
323
318
typetest_clause(binary, V, E, _Env) ->
324
319
typetest_clause_1(is_binary, V, E).
330
325
%% This returns a constructor descriptor, to be used for grouping and
331
326
%% pattern generation. It consists of an identifier term and the arity.
333
-define(cons_id, [0]).
334
-define(tuple_id, {0}).
335
-define(binary_id, <<0>>).
336
-define(literal_id(V), V).
339
329
case cerl:type(E) of
340
330
cons -> {?cons_id, 2};
341
331
tuple -> {?tuple_id, cerl:tuple_arity(E)};
342
binary -> {?binary_id, cerl:binary_segs(E)};
332
binary -> {?binary_id, cerl:binary_segments(E)};
344
334
case cerl:concrete(E) of
345
335
[_|_] -> {?cons_id, 2};
350
340
throw({bad_constructor, E})
343
%% This returns the type class for a constructor descriptor, for
344
%% grouping of clauses. It does not distinguish between tuples of
345
%% different arity, nor between different values of atoms, integers and
348
con_desc_type({?literal_id([]), _}) -> [];
349
con_desc_type({?literal_id(V), _}) when is_atom(V) -> atom;
350
con_desc_type({?literal_id(V), _}) when is_integer(V) -> integer;
351
con_desc_type({?literal_id(V), _}) when is_float(V) -> float;
352
con_desc_type({?cons_id, 2}) -> cons;
353
con_desc_type({?tuple_id, _}) -> tuple;
354
con_desc_type({?binary_id, _}) -> binary.
353
356
%% This creates a new constructor pattern from a type descriptor and a
354
357
%% list of variables.
382
385
%% This avoids generating stupid things like "let X = ... in 'true'",
383
%% keeping the generated code cleaner.
386
%% and "let X = Y in X", keeping the generated code cleaner. It also
387
%% prevents expressions from being considered "non-lightweight" when
388
%% code duplication is disallowed (see is_lightweight for details).
385
390
make_let(Vs, A, B) ->
390
false -> cerl:c_let(Vs, A, B)
392
_ -> cerl:c_let(Vs, A, B)
391
cerl_lib:reduce_expr(cerl:c_let(Vs, A, B)).
395
%% ------------------------------------------------------------------------
393
%% ---------------------------------------------------------------------
396
394
%% Rewriting a module or other expression:
398
396
%% @spec expr(Expression::cerl(), Env) -> cerl()
463
462
B = expr(cerl:fun_body(E), Env1),
464
463
cerl:update_c_fun(E, Vs, B);
466
%% NOTE: No pattern matching compilation done here!
465
%% NOTE: No pattern matching compilation is done here! The
466
%% receive-clauses and patterns cannot be staged as long as
467
%% we are working with "normal" Core Erlang.
467
468
Cs = expr_list(cerl:receive_clauses(E), Env),
468
469
T = expr(cerl:receive_timeout(E), Env),
469
470
A = expr(cerl:receive_action(E), Env),
518
520
foldl(fun (V, Env) -> env__bind(cerl:var_name(V), [], Env) end,
521
524
add_defs(Ds, Env) ->
522
525
foldl(fun ({V, _F}, Env) ->
523
526
env__bind(cerl:var_name(V), [], Env)
526
%% For now, we duplicate code without limitations, as long as lifting
527
%% out the code always results in a full local function call even when
528
%% the code is in last call context, since this causes notable slowdown
531
is_lightweight(_) -> true.
533
%% is_lightweight(E) ->
534
%% case cerl:type(E) of
537
%% values -> all(fun is_simple/1, cerl:values_es(E));
538
%% cons -> is_simple(cerl:cons_hd(E))
539
%% andalso is_simple(cerl:cons_tl(E));
540
%% tuple -> all(fun is_simple/1, cerl:tuple_es(E));
541
%% 'let' -> (is_simple(cerl:let_arg(E)) andalso
542
%% is_lightweight(cerl:let_body(E)));
543
%% seq -> (is_simple(cerl:seq_arg(E)) andalso
544
%% is_lightweight(cerl:seq_body(E)));
546
%% is_simple(cerl:apply_op(E))
547
%% andalso all(fun is_simple/1, cerl:apply_args(E));
549
%% is_simple(cerl:call_module(E))
550
%% andalso is_simple(cerl:call_name(E))
551
%% andalso all(fun is_simple/1, cerl:call_args(E));
530
%% This decides whether an expression is worth lifting out to a separate
531
%% function instead of duplicating the code. In other words, whether its
532
%% cost is about the same or smaller than that of a local function call.
533
%% Note that variables must always be "lightweight"; otherwise, they may
534
%% get lifted out of the case switch that introduces them.
537
case get('cerl_pmatch_duplicate_code') of
538
never -> cerl:type(E) =:= var; % Avoids all code duplication
539
always -> true; % Does not lift code to new functions
540
_ -> is_lightweight_1(E)
543
is_lightweight_1(E) ->
548
values -> all(fun is_simple/1, cerl:values_es(E));
549
cons -> is_simple(cerl:cons_hd(E))
550
andalso is_simple(cerl:cons_tl(E));
551
tuple -> all(fun is_simple/1, cerl:tuple_es(E));
552
'let' -> (is_simple(cerl:let_arg(E)) andalso
553
is_lightweight_1(cerl:let_body(E)));
554
seq -> (is_simple(cerl:seq_arg(E)) andalso
555
is_lightweight_1(cerl:seq_body(E)));
557
all(fun is_simple/1, cerl:primop_args(E));
559
is_simple(cerl:apply_op(E))
560
andalso all(fun is_simple/1, cerl:apply_args(E));
562
is_simple(cerl:call_module(E))
563
andalso is_simple(cerl:call_name(E))
564
andalso all(fun is_simple/1, cerl:call_args(E));
566
%% The default is to lift the code to a new function.
570
%% "Simple" things have no (or negligible) runtime cost and are free
571
%% from side effects.
556
574
case cerl:type(E) of
564
%% ------------------------------------------------------------------------
583
case get(unique_label) of
585
put(unique_label, 1),
588
put(unique_label, N+1),
592
%% ---------------------------------------------------------------------
565
593
%% Abstract datatype: environment()
570
595
env__bind(Key, Val, Env) ->
571
596
rec_env:bind(Key, Val, Env).
573
%% `Es' should have type `[{Key, Val}]', and `Fun' should have type
574
%% `(Val, Env) -> T', mapping a value together with the recursive
575
%% environment itself to some term `T' to be returned when the entry is
578
599
%% env__bind_recursive(Ks, Vs, F, Env) ->
579
600
%% rec_env:bind_recursive(Ks, Vs, F, Env).