Skip to content

Commit

Permalink
add macroexpand1 function and macro
Browse files Browse the repository at this point in the history
  • Loading branch information
jw3126 committed Jun 30, 2017
1 parent 197ca1c commit 7d99913
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 6 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ Library improvements
* `@test isequal(x, y)` and `@test isapprox(x, y)` now prints an evaluated expression when
the test fails ([#22296]).

* A new `macroexpand1` function and `@macroexpand1` macro for non recursive macro expansion ([#21662]).

Compiler/Runtime improvements
-----------------------------

Expand Down
2 changes: 2 additions & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,8 @@ export
expand,
gensym,
macroexpand,
macroexpand1,
@macroexpand1,
@macroexpand,
parse,

Expand Down
20 changes: 20 additions & 0 deletions base/expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,19 @@ expand(m::Module, x::ANY) = ccall(:jl_expand, Any, (Any, Any), x, m)
Takes the expression `x` and returns an equivalent expression with all macros removed (expanded)
for executing in module `m`.
For non recursive expansion, see [`macroexpand1`](@ref).
For more convenient interfaces, see [`@macroexpand`](@ref) and [`@macroexpand1`](@ref).
"""
macroexpand(m::Module, x::ANY) = ccall(:jl_macroexpand, Any, (Any, Any), x, m)

"""
macroexpand1(m, x)
Like `macroexpand(m, x)`, but only macros that are directly
called in `x` are expanded. Deeper levels of nested macrocalls are not expanded.
"""
macroexpand1(m::Module, x::ANY) = ccall(:jl_macroexpand1, Any, (Any, Any), x, m)

"""
@macroexpand
Expand Down Expand Up @@ -100,6 +110,16 @@ macro macroexpand(code)
return :(macroexpand($__module__, $(QuoteNode(code))))
end


"""
@macroexpand1
Macro version of [`macroexpand1`](@ref). See also [`@macroexpand`](@ref).
"""
macro macroexpand1(code)
return :(macroexpand1($__module__, $(QuoteNode(code))))
end

## misc syntax ##

"""
Expand Down
2 changes: 2 additions & 0 deletions doc/src/stdlib/base.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ Base.gc
Base.gc_enable
Base.macroexpand
Base.@macroexpand
Base.macroexpand1
Base.@macroexpand1
Base.expand
Base.code_lowered
Base.@code_lowered
Expand Down
6 changes: 6 additions & 0 deletions src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,12 @@ JL_DLLEXPORT jl_value_t *jl_macroexpand(jl_value_t *expr, jl_module_t *inmodule)
return jl_call_scm_on_ast("jl-macroexpand", expr, inmodule);
}

JL_DLLEXPORT jl_value_t *jl_macroexpand1(jl_value_t *expr, jl_module_t *inmodule)
{
JL_TIMING(LOWERING);
return jl_call_scm_on_ast("jl-macroexpand-1", expr, inmodule);
}

// wrap expr in a thunk AST
jl_code_info_t *jl_wrap_expr(jl_value_t *expr)
{
Expand Down
5 changes: 5 additions & 0 deletions src/jlfrontend.scm
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@
(parser-wrap (lambda ()
(julia-expand-macros expr))))

(define (jl-macroexpand-1 expr)
(reset-gensyms)
(parser-wrap (lambda ()
(julia-expand-macros-limited expr 1))))

; run whole frontend on a string. useful for testing.
(define (fe str)
(expand-toplevel-expr (julia-parse str)))
Expand Down
15 changes: 9 additions & 6 deletions src/macroexpand.scm
Original file line number Diff line number Diff line change
Expand Up @@ -466,11 +466,12 @@

;; macro expander entry point

(define (julia-expand-macros e)
(cond ((not (pair? e)) e)
(define (julia-expand-macros-limited e max-depth)
(cond ((= max-depth 0) e)
((not (pair? e)) e)
((eq? (car e) 'quote)
;; backquote is essentially a built-in macro at the moment
(julia-expand-macros (julia-bq-expand (cadr e) 0)))
(julia-expand-macros-limited (julia-bq-expand (cadr e) 0) max-depth))
((eq? (car e) 'inert) e)
((eq? (car e) 'macrocall)
;; expand macro
Expand All @@ -483,8 +484,10 @@
(m (cdr form)))
;; m is the macro's def module
(rename-symbolic-labels
(julia-expand-macros
(resolve-expansion-vars form m))))))
(julia-expand-macros-limited (resolve-expansion-vars form m) (- max-depth 1))
))))
((eq? (car e) 'module) e)
(else
(map julia-expand-macros e))))
(map (lambda (ex) (julia-expand-macros-limited ex max-depth) ) e))))

(define (julia-expand-macros e) (julia-expand-macros-limited e -1))
25 changes: 25 additions & 0 deletions test/replutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,31 @@ let
@test (@macroexpand @seven_dollar 1+$x) == :(1 + $(Expr(:$, :x)))
end

macro nest1(code)
code
end

macro nest2(code)
:(@nest1 $code)
end

macro nest2b(code)
:(@nest1($code); @nest1($code))
end

@testset "macroexpand1, @macroexpand1" begin
M = @__MODULE__
ex = :(@nest1 42)
@test macroexpand1(M,ex) == macroexpand(M,ex)
ex = :(@nest2 42)
@test macroexpand1(M,ex) != macroexpand(M,ex)
@test macroexpand1(M,macroexpand1(M,ex)) == macroexpand(M,ex)
ex = :(@nest2b 42)
@test macroexpand1(M,ex) != macroexpand(M,ex)
@test macroexpand1(M,macroexpand1(M,ex)) == macroexpand(M,ex)
@test (@macroexpand1 @nest2b 42) == macroexpand1(M,ex)
end

foo_9965(x::Float64; w=false) = x
foo_9965(x::Int) = 2x

Expand Down

0 comments on commit 7d99913

Please sign in to comment.