1010-export ([start /2 , stop /1 , config_change /3 ]).
1111-export ([
1212 string_to_tokens /5 , tokens_to_quoted /3 , string_to_quoted /5 , 'string_to_quoted!' /5 ,
13- env_for_eval /1 , quoted_to_erl /2 , eval_forms /3 , eval_quoted /3 ,
14- eval_quoted /4 , eval_local_handler /2 , eval_external_handler /3 ,
15- emit_warnings /3
13+ env_for_eval /1 , quoted_to_erl /2 , eval_forms /3 , eval_quoted /3 , eval_quoted /4 ,
14+ erl_eval /3 , eval_local_handler /2 , eval_external_handler /3 , emit_warnings /3
1615]).
1716-include (" elixir.hrl" ).
1817-define (system , 'Elixir.System' ).
@@ -92,16 +91,17 @@ start(_Type, _Args) ->
9291 {no_halt , false },
9392
9493 % % Compiler options
94+ {debug_info , true },
9595 {docs , true },
9696 {ignore_already_consolidated , false },
9797 {ignore_module_conflict , false },
98- {initial_dbg_callback , InitialDbgCallback },
9998 {infer_signatures , [elixir ]},
99+ {initial_dbg_callback , InitialDbgCallback },
100+ {module_definition , compiled },
101+ {no_warn_undefined , []},
100102 {on_undefined_variable , raise },
101103 {parser_options , [{columns , true }]},
102- {debug_info , true },
103104 {relative_paths , true },
104- {no_warn_undefined , []},
105105 {tracers , []}
106106 | URIConfig
107107 ],
@@ -324,33 +324,7 @@ eval_forms(Tree, Binding, OrigE, Opts) ->
324324 end ;
325325
326326 _ ->
327- Exprs =
328- case Erl of
329- {block , _ , BlockExprs } -> BlockExprs ;
330- _ -> [Erl ]
331- end ,
332-
333- % % We use remote names so eval works across Elixir versions.
334- LocalHandler = {value , fun ? MODULE :eval_local_handler /2 },
335- ExternalHandler = {value , fun ? MODULE :eval_external_handler /3 },
336-
337- {value , Value , NewBinding } =
338- try
339- % % ?elixir_eval_env is used by the external handler.
340- % %
341- % % The reason why we use the process dictionary to pass the environment
342- % % is because we want to avoid passing closures to erl_eval, as that
343- % % would effectively tie the eval code to the Elixir version and it is
344- % % best if it depends solely on Erlang/OTP.
345- % %
346- % % The downside is that functions that escape the eval context will no
347- % % longer have the original environment they came from.
348- erlang :put (? elixir_eval_env , NewE ),
349- erl_eval :exprs (Exprs , ErlBinding , LocalHandler , ExternalHandler )
350- after
351- erlang :erase (? elixir_eval_env )
352- end ,
353-
327+ {value , Value , NewBinding } = erl_eval (Erl , ErlBinding , NewE ),
354328 PruneBefore = if Prune -> length (Binding ); true -> - 1 end ,
355329
356330 {DumpedBinding , DumpedVars } =
@@ -359,6 +333,28 @@ eval_forms(Tree, Binding, OrigE, Opts) ->
359333 {Value , DumpedBinding , NewE #{versioned_vars := DumpedVars }}
360334 end .
361335
336+ % % Evaluate Erlang code with careful handling of local and external functions
337+ erl_eval (Expr , Binding , Env ) ->
338+ % % We use remote names so eval works across Elixir versions
339+ LocalHandler = {value , fun ? MODULE :eval_local_handler /2 },
340+ ExternalHandler = {value , fun ? MODULE :eval_external_handler /3 },
341+
342+ try
343+ % % ?elixir_eval_env is used by the external handler.
344+ % %
345+ % % The reason why we use the process dictionary to pass the environment
346+ % % is because we want to avoid passing closures to erl_eval, as that
347+ % % would effectively tie the eval code to the Elixir version and it is
348+ % % best if it depends solely on Erlang/OTP.
349+ % %
350+ % % The downside is that functions that escape the eval context will no
351+ % % longer have the original environment they came from.
352+ erlang :put (? elixir_eval_env , Env ),
353+ erl_eval :expr (Expr , Binding , LocalHandler , ExternalHandler )
354+ after
355+ erlang :erase (? elixir_eval_env )
356+ end .
357+
362358eval_local_handler (FunName , Args ) ->
363359 {current_stacktrace , Stack } = erlang :process_info (self (), current_stacktrace ),
364360 Opts = [{module , nil }, {function , FunName }, {arity , length (Args )}, {reason , 'undefined local' }],
@@ -405,10 +401,8 @@ eval_external_handler(Ann, FunOrModFun, Args) ->
405401 % % Add file+line information at the bottom
406402 Bottom =
407403 case erlang :get (? elixir_eval_env ) of
408- #{file := File } ->
409- [{elixir_eval , '__FILE__' , 1 ,
410- [{file , elixir_utils :characters_to_list (File )}, {line , erl_anno :line (Ann )}]}];
411-
404+ #{'__struct__' := 'Elixir.Macro.Env' } = E ->
405+ 'Elixir.Macro.Env' :stacktrace (E #{line := erl_anno :line (Ann )});
412406 _ ->
413407 []
414408 end ,
0 commit comments