aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2010-03-12 09:39:23 +0100
committerBjörn Gustavsson <[email protected]>2010-06-02 11:51:25 +0200
commit7ac0808979534a94617c3391503c961d1ef72755 (patch)
treef929be0d00318569bef8d37ecf316512b17a1b19 /lib
parent1858cb81391d2bce29b4b7620574ca60128cebf7 (diff)
downloadotp-7ac0808979534a94617c3391503c961d1ef72755.tar.gz
otp-7ac0808979534a94617c3391503c961d1ef72755.tar.bz2
otp-7ac0808979534a94617c3391503c961d1ef72755.zip
Evaluate element/2 at compile-time using type information
The erl_expand_records compiler pass translates the following code: h(X) when X#r1.a =:= 1 -> ok. to (essentially): h({r1,V1,V2}=X) when element(2, X) =:= 1 -> ok. Since the guard can only be executed when the pattern matching has succeeded, we know that the second element in the tuple X must have been bound to V2. Thus we can eliminate the call to element/2 like this: h({r1,V1,V2}=X) when V1 =:= 1 -> ok.
Diffstat (limited to 'lib')
-rw-r--r--lib/compiler/src/sys_core_fold.erl29
-rw-r--r--lib/stdlib/test/qlc_SUITE.erl4
2 files changed, 19 insertions, 14 deletions
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 6202f07479..3e572d4b27 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -1194,19 +1194,22 @@ eval_element(Call, #c_literal{val=Pos}, #c_tuple{es=Es}, _Types) when is_integer
true ->
eval_failure(Call, badarg)
end;
-%% eval_element(Call, #c_literal{val=Pos}, #c_var{name=V}, Types)
-%% when is_integer(Pos) ->
-%% case orddict:find(V, Types#sub.t) of
-%% {ok,#c_tuple{es=Elements}} ->
-%% if
-%% 1 =< Pos, Pos =< length(Elements) ->
-%% lists:nth(Pos, Elements);
-%% true ->
-%% eval_failure(Call, badarg)
-%% end;
-%% error ->
-%% Call
-%% end;
+eval_element(Call, #c_literal{val=Pos}, #c_var{name=V}, Types)
+ when is_integer(Pos) ->
+ case orddict:find(V, Types#sub.t) of
+ {ok,#c_tuple{es=Elements}} ->
+ if
+ 1 =< Pos, Pos =< length(Elements) ->
+ case lists:nth(Pos, Elements) of
+ #c_alias{var=Alias} -> Alias;
+ Res -> Res
+ end;
+ true ->
+ eval_failure(Call, badarg)
+ end;
+ error ->
+ Call
+ end;
eval_element(Call, Pos, Tuple, _Types) ->
case is_not_integer(Pos) orelse is_not_tuple(Tuple) of
true ->
diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl
index aa12ed57da..e21de8770a 100644
--- a/lib/stdlib/test/qlc_SUITE.erl
+++ b/lib/stdlib/test/qlc_SUITE.erl
@@ -3184,7 +3184,9 @@ lookup2(Config) when is_list(Config) ->
[] = qlc:e(Q),
false = lookup_keys(Q)
end, [{1,b},{2,3}])">>,
- {warnings,[{{3,48},qlc,nomatch_filter}]}},
+ {warnings,[{2,sys_core_fold,nomatch_guard},
+ {3,qlc,nomatch_filter},
+ {3,sys_core_fold,{eval_failure,badarg}}]}},
<<"etsc(fun(E) ->
Q = qlc:q([X || {X} <- ets:table(E), element(1,{X}) =:= 1]),