aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2011-11-07 14:01:06 +0100
committerBjörn Gustavsson <[email protected]>2011-11-07 14:01:06 +0100
commitd0f1b81f1f0a8955c09d8a626d2d747950c52459 (patch)
tree6a4c727e7d122cb73ecffd6db8d39d4daf7874df /lib/compiler
parent2d4f4dca7a511dd61cc99f01bdf2a3dadaef9e5e (diff)
parentff432e262e65243cbc983fcb002527f8fae8c78b (diff)
downloadotp-d0f1b81f1f0a8955c09d8a626d2d747950c52459.tar.gz
otp-d0f1b81f1f0a8955c09d8a626d2d747950c52459.tar.bz2
otp-d0f1b81f1f0a8955c09d8a626d2d747950c52459.zip
Merge branch 'bjorn/external-funs/OTP-9643'
* bjorn/external-funs/OTP-9643: EEP-23: Allow variables in fun M:F/A Reference manual: Improve the documentation for external funs Test calling a parameterized module within a fun beam_loader: Support external funs in the literal pool
Diffstat (limited to 'lib/compiler')
-rw-r--r--lib/compiler/src/sys_pre_expand.erl11
-rw-r--r--lib/compiler/src/v3_core.erl7
-rw-r--r--lib/compiler/test/fun_SUITE.erl52
-rw-r--r--lib/compiler/test/pmod_SUITE.erl4
4 files changed, 68 insertions, 6 deletions
diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl
index 0fa1fea09f..7facbafb6d 100644
--- a/lib/compiler/src/sys_pre_expand.erl
+++ b/lib/compiler/src/sys_pre_expand.erl
@@ -554,9 +554,14 @@ fun_tq(Lf, {function,F,A}=Function, St0) ->
{{'fun',Lf,Function,{Index,Uniq,Fname}},
St2#expand{fun_index=Index+1}}
end;
-fun_tq(L, {function,M,F,A}, St) ->
- {{call,L,{remote,L,{atom,L,erlang},{atom,L,make_fun}},
- [{atom,L,M},{atom,L,F},{integer,L,A}]},St};
+fun_tq(L, {function,M,F,A}, St) when is_atom(M), is_atom(F), is_integer(A) ->
+ %% This is the old format for external funs, generated by a pre-R15
+ %% compiler. That means that a tool, such as the debugger or xref,
+ %% directly invoked this module with the abstract code from a
+ %% pre-R15 BEAM file. Be helpful, and translate it to the new format.
+ fun_tq(L, {function,{atom,L,M},{atom,L,F},{integer,L,A}}, St);
+fun_tq(Lf, {function,_,_,_}=ExtFun, St) ->
+ {{'fun',Lf,ExtFun},St};
fun_tq(Lf, {clauses,Cs0}, St0) ->
Uniq = erlang:hash(Cs0, (1 bsl 27)-1),
{Cs1,St1} = fun_clauses(Cs0, St0),
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index 6f3590b156..6885405ae0 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -573,6 +573,13 @@ expr({'catch',L,E0}, St0) ->
expr({'fun',L,{function,F,A},{_,_,_}=Id}, St) ->
Lanno = lineno_anno(L, St),
{#c_var{anno=Lanno++[{id,Id}],name={F,A}},[],St};
+expr({'fun',L,{function,M,F,A}}, St0) ->
+ {As,Aps,St1} = safe_list([M,F,A], St0),
+ Lanno = lineno_anno(L, St1),
+ {#icall{anno=#a{anno=Lanno},
+ module=#c_literal{val=erlang},
+ name=#c_literal{val=make_fun},
+ args=As},Aps,St1};
expr({'fun',L,{clauses,Cs},Id}, St) ->
fun_tq(Id, Cs, L, St);
expr({call,L,{remote,_,M,F},As0}, #core{wanted=Wanted}=St0) ->
diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl
index 368a5815bf..6067ee8e06 100644
--- a/lib/compiler/test/fun_SUITE.erl
+++ b/lib/compiler/test/fun_SUITE.erl
@@ -20,7 +20,11 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
- test1/1,overwritten_fun/1,otp_7202/1,bif_fun/1]).
+ test1/1,overwritten_fun/1,otp_7202/1,bif_fun/1,
+ external/1]).
+
+%% Internal export.
+-export([call_me/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -28,7 +32,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
test_lib:recompile(?MODULE),
- [test1, overwritten_fun, otp_7202, bif_fun].
+ [test1,overwritten_fun,otp_7202,bif_fun,external].
groups() ->
[].
@@ -45,7 +49,6 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
%%% The help functions below are copied from emulator:bs_construct_SUITE.
-define(T(B, L), {B, ??B, L}).
@@ -152,4 +155,47 @@ bif_fun(Config) when is_list(Config) ->
?line F = fun abs/1,
?line 5 = F(-5),
ok.
+
+-define(APPLY(M, F, A), (fun(Fun) -> {ok,{a,b}} = Fun({a,b}) end)(fun M:F/A)).
+-define(APPLY2(M, F, A),
+ (fun(Map) ->
+ Id = fun(I) -> I end,
+ List = [x,y],
+ List = Map(Id, List),
+ {type,external} = erlang:fun_info(Map, type)
+ end)(fun M:F/A)).
+external(Config) when is_list(Config) ->
+ Mod = id(?MODULE),
+ Func = id(call_me),
+ Arity = id(1),
+
+ ?APPLY(?MODULE, call_me, 1),
+ ?APPLY(?MODULE, call_me, Arity),
+ ?APPLY(?MODULE, Func, 1),
+ ?APPLY(?MODULE, Func, Arity),
+ ?APPLY(Mod, call_me, 1),
+ ?APPLY(Mod, call_me, Arity),
+ ?APPLY(Mod, Func, 1),
+ ?APPLY(Mod, Func, Arity),
+
+ ListsMod = id(lists),
+ ListsMap = id(map),
+ ListsArity = id(2),
+
+ ?APPLY2(lists, map, 2),
+ ?APPLY2(lists, map, ListsArity),
+ ?APPLY2(lists, ListsMap, 2),
+ ?APPLY2(lists, ListsMap, ListsArity),
+ ?APPLY2(ListsMod, map, 2),
+ ?APPLY2(ListsMod, map, ListsArity),
+ ?APPLY2(ListsMod, ListsMap, 2),
+ ?APPLY2(ListsMod, ListsMap, ListsArity),
+
+ ok.
+
+call_me(I) ->
+ {ok,I}.
+
+id(I) ->
+ I.
diff --git a/lib/compiler/test/pmod_SUITE.erl b/lib/compiler/test/pmod_SUITE.erl
index 9a317b5762..3d02adaf52 100644
--- a/lib/compiler/test/pmod_SUITE.erl
+++ b/lib/compiler/test/pmod_SUITE.erl
@@ -96,6 +96,10 @@ basic_1(Config, Opts) ->
?line error = Prop4:bar_bar({s,a,b}),
?line error = Prop4:bar_bar([]),
+ %% Call from a fun.
+ Fun = fun(Arg) -> Prop4:bar(Arg) end,
+ ?line ok = Fun({s,0}),
+
ok.
otp_8447(Config) when is_list(Config) ->