summaryrefslogtreecommitdiff
path: root/lib/stdlib/src/erl_expand_records.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib/src/erl_expand_records.erl')
-rw-r--r--lib/stdlib/src/erl_expand_records.erl32
1 files changed, 19 insertions, 13 deletions
diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl
index 7715f7d458..8cd78e597d 100644
--- a/lib/stdlib/src/erl_expand_records.erl
+++ b/lib/stdlib/src/erl_expand_records.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2022. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -55,8 +55,7 @@ compiler_options(Forms) ->
lists:flatten([C || {attribute,_,compile,C} <- Forms]).
init_calltype(Forms) ->
- Locals = [{{Name,Arity},local} || {function,_,Name,Arity,_} <- Forms],
- Ctype = maps:from_list(Locals),
+ Ctype = #{{Name,Arity} => local || {function,_,Name,Arity,_} <- Forms},
init_calltype_imports(Forms, Ctype).
init_calltype_imports([{attribute,_,import,{Mod,Fs}}|T], Ctype0) ->
@@ -289,6 +288,10 @@ expr({bc,Anno,E0,Qs0}, St0) ->
{Qs1,St1} = lc_tq(Anno, Qs0, St0),
{E1,St2} = expr(E0, St1),
{{bc,Anno,E1,Qs1},St2};
+expr({mc,Anno,E0,Qs0}, St0) ->
+ {Qs1,St1} = lc_tq(Anno, Qs0, St0),
+ {E1,St2} = expr(E0, St1),
+ {{mc,Anno,E1,Qs1},St2};
expr({tuple,Anno,Es0}, St0) ->
{Es1,St1} = expr_list(Es0, St0),
{{tuple,Anno,Es1},St1};
@@ -442,7 +445,9 @@ expr({op,Anno,Op,L0,R0}, St0) when Op =:= 'andalso';
expr({op,Anno,Op,L0,R0}, St0) ->
{L,St1} = expr(L0, St0),
{R,St2} = expr(R0, St1),
- {{op,Anno,Op,L,R},St2}.
+ {{op,Anno,Op,L,R},St2};
+expr(E={ssa_check_when,_,_,_,_,_}, St) ->
+ {E, St}.
expr_list([E0 | Es0], St0) ->
{E,St1} = expr(E0, St0),
@@ -513,6 +518,11 @@ lc_tq(Anno, [{b_generate,AnnoG,P0,G0} | Qs0], St0) ->
{P1,St2} = pattern(P0, St1),
{Qs1,St3} = lc_tq(Anno, Qs0, St2),
{[{b_generate,AnnoG,P1,G1} | Qs1],St3};
+lc_tq(Anno, [{m_generate,AnnoG,P0,G0} | Qs0], St0) ->
+ {G1,St1} = expr(G0, St0),
+ {P1,St2} = pattern(P0, St1),
+ {Qs1,St3} = lc_tq(Anno, Qs0, St2),
+ {[{m_generate,AnnoG,P1,G1} | Qs1],St3};
lc_tq(Anno, [F0 | Qs0], #exprec{calltype=Calltype,raw_records=Records}=St0) ->
%% Allow record/2 and expand out as guard test.
IsOverriden = fun(FA) ->
@@ -694,24 +704,20 @@ record_wildcard_init([]) -> none.
record_update(R, Name, Fs, Us0, St0) ->
Anno = element(2, R),
{Pre,Us,St1} = record_exprs(Us0, St0),
- Nf = length(Fs), %# of record fields
- Nu = length(Us), %# of update fields
- Nc = Nf - Nu, %# of copy fields
%% We need a new variable for the record expression
%% to guarantee that it is only evaluated once.
{Var,St2} = new_var(Anno, St1),
+ %% Honor the `strict_record_updates` option needed by `dialyzer`, otherwise
+ %% expand everything to chains of `setelement/3` as that's far more
+ %% efficient in the JIT.
StrictUpdates = strict_record_updates(St2#exprec.compile),
-
- %% Try to be intelligent about which method of updating record to use.
{Update,St} =
if
- Nu =:= 0 ->
- record_match(Var, Name, Anno, Fs, Us, St2);
- Nu =< Nc, not StrictUpdates -> %Few fields updated
+ not StrictUpdates, Us =/= [] ->
{record_setel(Var, Name, Fs, Us), St2};
- true -> %The wide area inbetween
+ true ->
record_match(Var, Name, Anno, Fs, Us, St2)
end,
{{block,Anno,Pre ++ [{match,Anno,Var,R},Update]},St}.