@@ -1966,42 +1966,95 @@ defmodule Macro do
19661966
19671967 def quoted_literal? ( { :%{} , _ , args } ) , do: quoted_literal? ( args )
19681968 def quoted_literal? ( { :{} , _ , args } ) , do: quoted_literal? ( args )
1969+ def quoted_literal? ( { :__MODULE__ , _ , ctx } ) when is_atom ( ctx ) , do: true
19691970 def quoted_literal? ( { left , right } ) , do: quoted_literal? ( left ) and quoted_literal? ( right )
19701971 def quoted_literal? ( list ) when is_list ( list ) , do: :lists . all ( & quoted_literal? / 1 , list )
19711972 def quoted_literal? ( term ) , do: is_atom ( term ) or is_number ( term ) or is_binary ( term )
19721973
1973- @ doc """
1974- Expands the `ast` representing a quoted literal within the given `env`.
1974+ @ doc false
1975+ @ deprecated "Use Macro.expand_literals/2 instead"
1976+ def expand_literal ( ast , env ) do
1977+ expand_literals ( ast , env )
1978+ end
19751979
1976- This function checks if the given AST represents a quoted literal
1977- (using `quoted_literal?/1`) and then expands all relevant nodes.
1978- If a literal node is not given, then it returns the AST as is.
1979- At the moment, the only expandable literal nodes in an AST are
1980- aliases, so this function only expands aliases.
1980+ @ doc """
1981+ Expands all literals in `ast` with the given `env`.
19811982
19821983 This function is mostly used to remove compile-time dependencies
19831984 from AST nodes. In such cases, the given environment is usually
1984- manipulate to represent a function:
1985+ manipulated to represent a function:
19851986
1986- Macro.expand_literal(ast, %{env | function: {:my_code, 1}})
1987+ Macro.expand_literals(ast, %{env | function: {:my_code, 1}})
1988+
1989+ At the moment, the only expandable literal nodes in an AST are
1990+ aliases, so this function only expands aliases.
19871991
19881992 However, be careful when removing compile-time dependencies between
19891993 modules. If you remove them but you still invoke the module at
1990- compile-time, you may end-up with broken behaviour.
1994+ compile-time, Elixir will be unable to properly recompile modules
1995+ when they change.
19911996 """
1992- @ doc since: "1.14.0"
1993- @ spec expand_literal ( t ( ) , Macro.Env . t ( ) ) :: t ( )
1994- def expand_literal ( ast , env ) do
1995- if quoted_literal? ( ast ) do
1996- prewalk ( ast , fn
1997- { :__aliases__ , _ , _ } = alias -> expand ( alias , env )
1998- other -> other
1999- end )
1997+ @ doc since: "1.14.1"
1998+ @ spec expand_literals ( t ( ) , Macro.Env . t ( ) ) :: t ( )
1999+ def expand_literals ( ast , env ) do
2000+ { ast , :ok } = expand_literals ( ast , :ok , fn node , :ok -> { expand ( node , env ) , :ok } end )
2001+ ast
2002+ end
2003+
2004+ @ doc """
2005+ Expands all literals in `ast` with the given `acc` and `fun`.
2006+
2007+ `fun` will be invoked with an expandable AST node and `acc` and
2008+ must return a new node with `acc`. This is a general version of
2009+ `expand_literals/2` which supports a custom expansion function.
2010+ Please check `expand_literals/2` for use cases and pitfalls.
2011+ """
2012+ @ doc since: "1.14.1"
2013+ @ spec expand_literals ( t ( ) , acc , ( t ( ) , acc -> { t ( ) , acc } ) ) :: t ( ) when acc: term ( )
2014+ def expand_literals ( ast , acc , fun )
2015+
2016+ def expand_literals ( { :__aliases__ , meta , args } , acc , fun ) do
2017+ { args , acc } = expand_literals ( args , acc , fun )
2018+
2019+ if :lists . all ( & is_atom / 1 , args ) do
2020+ fun . ( { :__aliases__ , meta , args } , acc )
20002021 else
2001- ast
2022+ { { :__aliases__ , meta , args } , acc }
20022023 end
20032024 end
20042025
2026+ def expand_literals ( { :__MODULE__ , _meta , ctx } = node , acc , fun ) when is_atom ( ctx ) do
2027+ fun . ( node , acc )
2028+ end
2029+
2030+ def expand_literals ( { :% , meta , [ left , right ] } , acc , fun ) do
2031+ { left , acc } = expand_literals ( left , acc , fun )
2032+ { right , acc } = expand_literals ( right , acc , fun )
2033+ { { :% , meta , [ left , right ] } , acc }
2034+ end
2035+
2036+ def expand_literals ( { :%{} , meta , args } , acc , fun ) do
2037+ { args , acc } = expand_literals ( args , acc , fun )
2038+ { { :%{} , meta , args } , acc }
2039+ end
2040+
2041+ def expand_literals ( { :{} , meta , args } , acc , fun ) do
2042+ { args , acc } = expand_literals ( args , acc , fun )
2043+ { { :{} , meta , args } , acc }
2044+ end
2045+
2046+ def expand_literals ( { left , right } , acc , fun ) do
2047+ { left , acc } = expand_literals ( left , acc , fun )
2048+ { right , acc } = expand_literals ( right , acc , fun )
2049+ { { left , right } , acc }
2050+ end
2051+
2052+ def expand_literals ( list , acc , fun ) when is_list ( list ) do
2053+ :lists . mapfoldl ( & expand_literals ( & 1 , & 2 , fun ) , acc , list )
2054+ end
2055+
2056+ def expand_literals ( term , acc , _fun ) , do: { term , acc }
2057+
20052058 @ doc """
20062059 Receives an AST node and expands it until it can no longer
20072060 be expanded.
0 commit comments