From 988f7a19f98c78d0dad29f171a0a6e0c9b56ce53 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 24 Sep 2016 12:55:52 +0200 Subject: [PATCH 1/8] added @macroexpand --- base/exports.jl | 1 + base/expr.jl | 10 ++++++++++ test/choosetests.jl | 2 +- test/expr.jl | 18 ++++++++++++++++++ 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 test/expr.jl diff --git a/base/exports.jl b/base/exports.jl index e30494ed191a2..43986e7d5d9b2 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1052,6 +1052,7 @@ export expand, gensym, macroexpand, + @macroexpand, parse, # help and reflection diff --git a/base/expr.jl b/base/expr.jl index 6fc8a69239fb4..2f632c175711e 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -61,6 +61,16 @@ Takes the expression `x` and returns an equivalent expression with all macros re """ macroexpand(x::ANY) = ccall(:jl_macroexpand, Any, (Any,), x) +""" +@macroexpand + +Return equivalent expression with all macros removed (expanded). +""" +macro macroexpand(code) + code_expanded = macroexpand(code) + Expr(:quote, code_expanded) +end + ## misc syntax ## """ diff --git a/test/choosetests.jl b/test/choosetests.jl index 6d812e7aeeda3..e0d0f58e51740 100644 --- a/test/choosetests.jl +++ b/test/choosetests.jl @@ -33,7 +33,7 @@ function choosetests(choices = []) "markdown", "base64", "serialize", "misc", "threads", "enums", "cmdlineargs", "i18n", "workspace", "libdl", "int", "checked", "intset", "floatfuncs", "compile", "parallel", "inline", - "boundscheck", "error", "ambiguous", "cartesian", "asmvariant" + "boundscheck", "error", "ambiguous", "cartesian", "asmvariant", "expr" ] if Base.USE_GPL_LIBS diff --git a/test/expr.jl b/test/expr.jl new file mode 100644 index 0000000000000..9bc408e129680 --- /dev/null +++ b/test/expr.jl @@ -0,0 +1,18 @@ + +# @macroexpand tests +macro seven_dollar(ex) + # simonbyrne example 18240 + isa(ex,Expr) && ex.head == :$ ? 7 : ex +end + +let + @test (@macroexpand @macroexpand x) == macroexpand(:(@macroexpand x)) + @test (@macroexpand :(1+$y) ) == macroexpand(:( :(1+ $y))) + @test (@macroexpand @fastmath 1+2 ) == :(Base.FastMath.add_fast(1,2)) + @test (@macroexpand @fastmath + ) == :(Base.FastMath.add_fast) + @test (@macroexpand @fastmath min(1) ) == :(Base.FastMath.min_fast(1)) + @test (@macroexpand @doc "" f() = @x) == Expr(:error, UndefVarError(Symbol("@x"))) + @test (@macroexpand @seven_dollar $bar) == 7 + x = 2 + @test (@macroexpand @seven_dollar 1+$x) == :(1 + 2) +end From bff375b7aec8fe8cabcb2d5f7d4f97714973df23 Mon Sep 17 00:00:00 2001 From: jw3126 Date: Sat, 24 Sep 2016 13:57:57 +0200 Subject: [PATCH 2/8] Update expr.jl --- base/expr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/expr.jl b/base/expr.jl index 2f632c175711e..258391fbf5c41 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -62,7 +62,7 @@ Takes the expression `x` and returns an equivalent expression with all macros re macroexpand(x::ANY) = ccall(:jl_macroexpand, Any, (Any,), x) """ -@macroexpand + @macroexpand Return equivalent expression with all macros removed (expanded). """ From 0b2c3caf0d5519e1038f0fa81efc4d6679871231 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 24 Sep 2016 15:38:42 +0200 Subject: [PATCH 3/8] added @macroexpand to rst --- doc/stdlib/base.rst | 6 ++++++ doc/stdlib/io-network.rst | 1 + 2 files changed, 7 insertions(+) diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index 472fde947af30..9fb481e412897 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -1517,6 +1517,12 @@ Internals Takes the expression ``x`` and returns an equivalent expression with all macros removed (expanded). +.. function:: @macroexpand + + .. Docstring generated from Julia source + + Return equivalent expression with all macros removed (expanded). + .. function:: expand(x) .. Docstring generated from Julia source diff --git a/doc/stdlib/io-network.rst b/doc/stdlib/io-network.rst index 6c82c0a052eb0..76450b2d1cfb5 100644 --- a/doc/stdlib/io-network.rst +++ b/doc/stdlib/io-network.rst @@ -1078,3 +1078,4 @@ Network I/O .. Docstring generated from Julia source The 32-bit byte-order-mark indicates the native byte order of the host machine. Little-endian machines will contain the value ``0x04030201``\ . Big-endian machines will contain the value ``0x01020304``\ . + From 2dfe407cf78a3ee2b61faa709eefd2dab123d5df Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sun, 25 Sep 2016 09:06:24 +0200 Subject: [PATCH 4/8] fix --- base/expr.jl | 2 +- test/expr.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/base/expr.jl b/base/expr.jl index 258391fbf5c41..3d4c4f8e32c49 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -68,7 +68,7 @@ Return equivalent expression with all macros removed (expanded). """ macro macroexpand(code) code_expanded = macroexpand(code) - Expr(:quote, code_expanded) + QuoteNode(code_expanded) end ## misc syntax ## diff --git a/test/expr.jl b/test/expr.jl index 9bc408e129680..76d2ba9fcadd1 100644 --- a/test/expr.jl +++ b/test/expr.jl @@ -14,5 +14,5 @@ let @test (@macroexpand @doc "" f() = @x) == Expr(:error, UndefVarError(Symbol("@x"))) @test (@macroexpand @seven_dollar $bar) == 7 x = 2 - @test (@macroexpand @seven_dollar 1+$x) == :(1 + 2) + @test (@macroexpand @seven_dollar 1+$x) == :(1 + $(Expr(:$, :x))) end From 691052d83a65e79d1cfb4a25c1de96df2512d46c Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Thu, 29 Sep 2016 20:49:37 +0200 Subject: [PATCH 5/8] fixup: improving docu and removing test/expr.jl --- base/expr.jl | 26 ++++++++++++++++++++++++++ doc/stdlib/base.rst | 26 ++++++++++++++++++++++++++ test/expr.jl | 18 ------------------ test/replutil.jl | 19 +++++++++++++++++++ 4 files changed, 71 insertions(+), 18 deletions(-) delete mode 100644 test/expr.jl diff --git a/base/expr.jl b/base/expr.jl index 3d4c4f8e32c49..263dee470c866 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -65,6 +65,32 @@ macroexpand(x::ANY) = ccall(:jl_macroexpand, Any, (Any,), x) @macroexpand Return equivalent expression with all macros removed (expanded). + +There is a subtle difference between `@macroexpand` and `macroexpand` in that expansion takes place in +different contexts. This is best seen in the following example: + +```jldoctest +julia> module M + macro m() + 1 + end + function f() + (@macroexpand(@m), macroexpand(:(@m))) + end + end +M + +julia> macro m() + 2 + end +@m (macro with 1 method) + +julia> M.f() +(1,2) +``` +With @macroexpand the expression expands where @macroexpand appears in the code (module M). +With macroexpand the expressions expands in the current module where the code was finally called. +Note that when calling macroexpand or @macroexpand directly from the REPL, both of these contexts coincide, hence there is no difference. """ macro macroexpand(code) code_expanded = macroexpand(code) diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index 9fb481e412897..2dc50f71fc212 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -1523,6 +1523,32 @@ Internals Return equivalent expression with all macros removed (expanded). + There is a subtle difference between ``@macroexpand`` and ``macroexpand`` in that expansion takes place in different contexts. This is best seen in the following example + + .. doctest:: + + julia> module M + macro m() + 1 + end + function f() + (@macroexpand(@m), macroexpand(:(@m))) + end + end + M + + julia> macro m() + 2 + end + @m (macro with 1 method) + + julia> M.f() + (1,2) + + With @macroexpand the expression expands, where @macroexpand appears in the code (module M). With macroexpand the expressions expands in the current module, where the code was finally called. + + Note that when calling macroexpand or @macroexpand directly from the REPL, both of these contexts coincide, hence there is no difference. + .. function:: expand(x) .. Docstring generated from Julia source diff --git a/test/expr.jl b/test/expr.jl deleted file mode 100644 index 76d2ba9fcadd1..0000000000000 --- a/test/expr.jl +++ /dev/null @@ -1,18 +0,0 @@ - -# @macroexpand tests -macro seven_dollar(ex) - # simonbyrne example 18240 - isa(ex,Expr) && ex.head == :$ ? 7 : ex -end - -let - @test (@macroexpand @macroexpand x) == macroexpand(:(@macroexpand x)) - @test (@macroexpand :(1+$y) ) == macroexpand(:( :(1+ $y))) - @test (@macroexpand @fastmath 1+2 ) == :(Base.FastMath.add_fast(1,2)) - @test (@macroexpand @fastmath + ) == :(Base.FastMath.add_fast) - @test (@macroexpand @fastmath min(1) ) == :(Base.FastMath.min_fast(1)) - @test (@macroexpand @doc "" f() = @x) == Expr(:error, UndefVarError(Symbol("@x"))) - @test (@macroexpand @seven_dollar $bar) == 7 - x = 2 - @test (@macroexpand @seven_dollar 1+$x) == :(1 + $(Expr(:$, :x))) -end diff --git a/test/replutil.jl b/test/replutil.jl index 642d8bfe39ff6..9fbb928a577e0 100644 --- a/test/replutil.jl +++ b/test/replutil.jl @@ -447,3 +447,22 @@ let d = Dict(1 => 2, 3 => 45) @test contains(replace(result, " ", ""), string(el)) end end + + +# @macroexpand tests +macro seven_dollar(ex) + # simonbyrne example 18240 + isa(ex,Expr) && ex.head == :$ ? 7 : ex +end + +let + @test (@macroexpand @macroexpand x) == macroexpand(:(@macroexpand x)) + @test (@macroexpand :(1+$y) ) == macroexpand(:( :(1+ $y))) + @test (@macroexpand @fastmath 1+2 ) == :(Base.FastMath.add_fast(1,2)) + @test (@macroexpand @fastmath + ) == :(Base.FastMath.add_fast) + @test (@macroexpand @fastmath min(1) ) == :(Base.FastMath.min_fast(1)) + @test (@macroexpand @doc "" f() = @x) == Expr(:error, UndefVarError(Symbol("@x"))) + @test (@macroexpand @seven_dollar $bar) == 7 + x = 2 + @test (@macroexpand @seven_dollar 1+$x) == :(1 + $(Expr(:$, :x))) +end From ebe9b53fbec6008091db105a4ca1a5da59e6f939 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Thu, 29 Sep 2016 20:58:30 +0200 Subject: [PATCH 6/8] fixup --- doc/stdlib/base.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index 2dc50f71fc212..b2385c9ac1933 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -1523,7 +1523,7 @@ Internals Return equivalent expression with all macros removed (expanded). - There is a subtle difference between ``@macroexpand`` and ``macroexpand`` in that expansion takes place in different contexts. This is best seen in the following example + There is a subtle difference between ``@macroexpand`` and ``macroexpand`` in that expansion takes place in different contexts. This is best seen in the following example: .. doctest:: @@ -1545,9 +1545,7 @@ Internals julia> M.f() (1,2) - With @macroexpand the expression expands, where @macroexpand appears in the code (module M). With macroexpand the expressions expands in the current module, where the code was finally called. - - Note that when calling macroexpand or @macroexpand directly from the REPL, both of these contexts coincide, hence there is no difference. + With @macroexpand the expression expands where @macroexpand appears in the code (module M). With macroexpand the expressions expands in the current module where the code was finally called. Note that when calling macroexpand or @macroexpand directly from the REPL, both of these contexts coincide, hence there is no difference. .. function:: expand(x) From c66c096d180a18ab14482fa6843c08fac12c200c Mon Sep 17 00:00:00 2001 From: jw3126 Date: Thu, 29 Sep 2016 21:09:28 +0200 Subject: [PATCH 7/8] Update expr.jl --- base/expr.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/expr.jl b/base/expr.jl index 263dee470c866..391ce27fe4a74 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -88,9 +88,9 @@ julia> macro m() julia> M.f() (1,2) ``` -With @macroexpand the expression expands where @macroexpand appears in the code (module M). -With macroexpand the expressions expands in the current module where the code was finally called. -Note that when calling macroexpand or @macroexpand directly from the REPL, both of these contexts coincide, hence there is no difference. +With `@macroexpand` the expression expands where `@macroexpand` appears in the code (module `M`). +With `macroexpand` the expressions expands in the current module where the code was finally called (REPL). +Note that when calling `macroexpand` or `@macroexpand` directly from the REPL, both of these contexts coincide, hence there is no difference. """ macro macroexpand(code) code_expanded = macroexpand(code) From f8157dc35608d520c5273aaa931e503e26c9cb2f Mon Sep 17 00:00:00 2001 From: jw3126 Date: Thu, 29 Sep 2016 22:06:35 +0200 Subject: [PATCH 8/8] Update choosetests.jl --- test/choosetests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/choosetests.jl b/test/choosetests.jl index e0d0f58e51740..6d812e7aeeda3 100644 --- a/test/choosetests.jl +++ b/test/choosetests.jl @@ -33,7 +33,7 @@ function choosetests(choices = []) "markdown", "base64", "serialize", "misc", "threads", "enums", "cmdlineargs", "i18n", "workspace", "libdl", "int", "checked", "intset", "floatfuncs", "compile", "parallel", "inline", - "boundscheck", "error", "ambiguous", "cartesian", "asmvariant", "expr" + "boundscheck", "error", "ambiguous", "cartesian", "asmvariant" ] if Base.USE_GPL_LIBS