88-module (elixir_dispatch ).
99-export ([dispatch_import /6 , dispatch_require /7 ,
1010 require_function /5 , import_function /4 ,
11- expand_import /7 , expand_require /6 , check_deprecated /6 ,
11+ expand_import /8 , expand_require /6 , check_deprecated /6 ,
1212 default_functions /0 , default_macros /0 , default_requires /0 ,
1313 find_import /4 , find_imports /3 , format_error /1 ]).
1414-include (" elixir.hrl" ).
@@ -115,7 +115,8 @@ dispatch_import(Meta, Name, Args, S, E, Callback) ->
115115 _ -> false
116116 end ,
117117
118- case expand_import (Meta , Name , Arity , E , [], AllowLocals , true ) of
118+ DefaultLocalForCallback = fun (M , N , A , K , Env ) -> elixir_def :local_for (M , N , A , K , Env ) end ,
119+ case expand_import (Meta , Name , Arity , E , [], AllowLocals , true , DefaultLocalForCallback ) of
119120 {macro , Receiver , Expander } ->
120121 check_deprecated (macro , Meta , Receiver , Name , Arity , E ),
121122 Caller = {? line (Meta ), S , E },
@@ -159,7 +160,7 @@ dispatch_require(_Meta, Receiver, Name, _Args, _S, _E, Callback) ->
159160
160161% % Macros expansion
161162
162- expand_import (Meta , Name , Arity , E , Extra , AllowLocals , Trace ) ->
163+ expand_import (Meta , Name , Arity , E , Extra , AllowLocals , Trace , LocalForCallback ) ->
163164 Tuple = {Name , Arity },
164165 Module = ? key (E , module ),
165166 Dispatch = find_import_by_name_arity (Meta , Tuple , Extra , E ),
@@ -172,7 +173,7 @@ expand_import(Meta, Name, Arity, E, Extra, AllowLocals, Trace) ->
172173 do_expand_import (Dispatch , Meta , Name , Arity , Module , E , Trace );
173174
174175 _ ->
175- Local = AllowLocals andalso elixir_def : local_for (Meta , Name , Arity , [defmacro , defmacrop ], E ),
176+ Local = AllowLocals andalso LocalForCallback (Meta , Name , Arity , [defmacro , defmacrop ], E ),
176177
177178 case Dispatch of
178179 % % There is a local and an import. This is a conflict unless
@@ -249,14 +250,22 @@ expander_macro_named(Meta, Receiver, Name, Arity, E) ->
249250 fun (Args , Caller ) -> expand_macro_fun (Meta , Fun , Receiver , Name , Args , Caller , E ) end .
250251
251252expand_macro_fun (Meta , Fun , Receiver , Name , Args , Caller , E ) ->
252- try
253- apply (Fun , [Caller | Args ])
254- catch
255- Kind :Reason :Stacktrace ->
256- Arity = length (Args ),
257- MFA = {Receiver , elixir_utils :macro_name (Name ), Arity + 1 },
258- Info = [{Receiver , Name , Arity , [{file , " expanding macro" }]}, caller (? line (Meta ), E )],
259- erlang :raise (Kind , Reason , prune_stacktrace (Stacktrace , MFA , Info , {ok , Caller }))
253+ % % Check if Fun is actually a function, as it might be a fake value for local macros
254+ % % when using custom local_for_callback
255+ case is_function (Fun ) of
256+ true ->
257+ try
258+ apply (Fun , [Caller | Args ])
259+ catch
260+ Kind :Reason :Stacktrace ->
261+ Arity = length (Args ),
262+ MFA = {Receiver , elixir_utils :macro_name (Name ), Arity + 1 },
263+ Info = [{Receiver , Name , Arity , [{file , " expanding macro" }]}, caller (? line (Meta ), E )],
264+ erlang :raise (Kind , Reason , prune_stacktrace (Stacktrace , MFA , Info , {ok , Caller }))
265+ end ;
266+ false ->
267+ % % Return a fake value and omit expansion when Fun is not a function
268+ ok
260269 end .
261270
262271expand_quoted (Meta , Receiver , Name , Arity , Quoted , S , E ) ->
0 commit comments