8
8
-module (elixir_dispatch ).
9
9
-export ([dispatch_import /6 , dispatch_require /7 ,
10
10
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 ,
12
12
default_functions /0 , default_macros /0 , default_requires /0 ,
13
13
find_import /4 , find_imports /3 , format_error /1 ]).
14
14
-include (" elixir.hrl" ).
@@ -115,7 +115,8 @@ dispatch_import(Meta, Name, Args, S, E, Callback) ->
115
115
_ -> false
116
116
end ,
117
117
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
119
120
{macro , Receiver , Expander } ->
120
121
check_deprecated (macro , Meta , Receiver , Name , Arity , E ),
121
122
Caller = {? line (Meta ), S , E },
@@ -159,7 +160,7 @@ dispatch_require(_Meta, Receiver, Name, _Args, _S, _E, Callback) ->
159
160
160
161
% % Macros expansion
161
162
162
- expand_import (Meta , Name , Arity , E , Extra , AllowLocals , Trace ) ->
163
+ expand_import (Meta , Name , Arity , E , Extra , AllowLocals , Trace , LocalForCallback ) ->
163
164
Tuple = {Name , Arity },
164
165
Module = ? key (E , module ),
165
166
Dispatch = find_import_by_name_arity (Meta , Tuple , Extra , E ),
@@ -172,7 +173,7 @@ expand_import(Meta, Name, Arity, E, Extra, AllowLocals, Trace) ->
172
173
do_expand_import (Dispatch , Meta , Name , Arity , Module , E , Trace );
173
174
174
175
_ ->
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 ),
176
177
177
178
case Dispatch of
178
179
% % There is a local and an import. This is a conflict unless
@@ -249,14 +250,22 @@ expander_macro_named(Meta, Receiver, Name, Arity, E) ->
249
250
fun (Args , Caller ) -> expand_macro_fun (Meta , Fun , Receiver , Name , Args , Caller , E ) end .
250
251
251
252
expand_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
260
269
end .
261
270
262
271
expand_quoted (Meta , Receiver , Name , Arity , Quoted , S , E ) ->
0 commit comments