diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 4549c098438d1..dd6b512a493ca 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -2178,4 +2178,11 @@ The base library of Julia. `Base` is a module that contains basic functionality """ Base.Base +""" + QuoteNode + +A quoted piece of code, that does not support interpolation. See the [manual section about QuoteNodes](@ref man-quote-node) for details. +""" +QuoteNode + end diff --git a/base/meta.jl b/base/meta.jl index 0d572ab1f6a99..4798d37cf9d28 100644 --- a/base/meta.jl +++ b/base/meta.jl @@ -12,15 +12,70 @@ export quot, show_sexpr, @dump +""" + quot(ex)::Expr + +Quote expression `ex` to produce an expression with head `quote`. This can for instance be used to represent objects of type `Expr` in the AST. +See also the manual section about [QuoteNode](@ref man-quote-node). + +# Examples +```jldoctest +julia> eval(quot(:x)) +:x + +julia> dump(quot(:x)) +Expr + head: Symbol quote + args: Array{Any}((1,)) + 1: Symbol x + +julia> eval(quot(:(1+2))) +:(1 + 2) +``` +""" quot(ex) = Expr(:quote, ex) +""" + isexpr(ex, head[, n])::Bool + +Check if `ex` is an expression with head `head` and `n` arguments. + +# Examples +```jldoctest +julia> ex = :(f(x)) +:(f(x)) + +julia> isexpr(ex, :block) +false + +julia> isexpr(ex, :call) +true + +julia> isexpr(ex, [:block, :call]) # multiple possible heads +true + +julia> isexpr(ex, :call, 1) +false + +julia> isexpr(ex, :call, 2) +true +``` +""" isexpr(@nospecialize(ex), head::Symbol) = isa(ex, Expr) && ex.head === head isexpr(@nospecialize(ex), heads::Union{Set,Vector,Tuple}) = isa(ex, Expr) && in(ex.head, heads) isexpr(@nospecialize(ex), heads, n::Int) = isexpr(ex, heads) && length(ex.args) == n +""" + show_sexpr([io::IO,], ex) -# ---- show_sexpr: print an AST as an S-expression ---- +Show expression `ex` as a lisp style S-expression. +# Examples +```jldoctest +julia> show_sexpr(:(f(x, g(y,z)))) +(:call, :f, :x, (:call, :g, :y, :z)) +``` +""" show_sexpr(ex) = show_sexpr(stdout, ex) show_sexpr(io::IO, ex) = show_sexpr(io, ex, 0) show_sexpr(io::IO, ex, indent::Int) = show(io, ex) diff --git a/doc/src/base/base.md b/doc/src/base/base.md index e7fe19d7517e8..a2b6a0a9e6cf4 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -397,6 +397,7 @@ Meta.@lower Meta.parse(::AbstractString, ::Int) Meta.parse(::AbstractString) Meta.ParseError +Core.QuoteNode Base.macroexpand Base.@macroexpand Base.@macroexpand1 @@ -404,3 +405,10 @@ Base.code_lowered Base.code_typed Base.precompile ``` + +## Meta +```@docs +Meta.quot +Meta.isexpr +Meta.show_sexpr +``` diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index fcfe422e8d64e..8fdad8147c042 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -308,7 +308,7 @@ The intuition behind this behavior is that `x` is evaluated once for each `$`: one `$` works similarly to `eval(:x)`, giving `x`'s value, while two `$`s do the equivalent of `eval(eval(:x))`. -### QuoteNode +### [QuoteNode](@id man-quote-node) The usual representation of a `quote` form in an AST is an [`Expr`](@ref) with head `:quote`: @@ -328,9 +328,15 @@ Expr As we have seen, such expressions support interpolation with `$`. However, in some situations it is necessary to quote code *without* performing interpolation. This kind of quoting does not yet have syntax, but is represented internally -as an object of type `QuoteNode`. -The parser yields `QuoteNode`s for simple quoted items like symbols: +as an object of type `QuoteNode`: +```jldoctest interp1 +julia> eval(quot(Expr(:$, :(1+2)))) +3 +julia> eval(QuoteNode(Expr(:$, :(1+2)))) +:($(Expr(:$, :(1 + 2)))) +``` +The parser yields `QuoteNode`s for simple quoted items like symbols: ```jldoctest interp1 julia> dump(Meta.parse(":x")) QuoteNode