Repository: JuliaLang/julia
File: stdlib/InteractiveUtils/src/macros.jl (Julia)

Code before:
end

for fname in [:which, :less, :edit, :functionloc]
    @eval begin
        macro ($fname)(ex0)
            gen_call_with_extracted_types(__module__, $(Expr(:quote, fname)), ex0, Expr[];
                                          is_source_reflection = true,
                                          supports_binding_reflection = $(fname === :which))
        end
    end
end

macro which(ex0::Symbol)
    ex0 = QuoteNode(ex0)
    return :(which($__module__, $ex0))
end

for fname in [:code_warntype, :code_llvm, :code_native,
              :infer_return_type, :infer_effects, :infer_exception_type]
    @eval macro ($fname)(ex0...)
        gen_call_with_extracted_types_and_kwargs(__module__, $(QuoteNode(fname)), ex0; is_source_reflection = false)
    end
end

for fname in [:code_typed, :code_lowered, :code_ircode]
    @eval macro ($fname)(ex0...)
        thecall = gen_call_with_extracted_types_and_kwargs(__module__, $(QuoteNode(fname)), ex0; is_source_reflection = false)
        quote
            local results = $thecall
            length(results) == 1 ? results[1] : results
        end
    end
end

"""
    @functionloc

Applied to a function or macro call, it evaluates the arguments to the specified call, and
returns a tuple `(filename,line)` giving the location for the method that would be called for those arguments.
It calls out to the [`functionloc`](@ref) function.
"""
:@functionloc

"""
    @which

Applied to a function or macro call, it evaluates the arguments to the specified call, and
returns the `Method` object for the method that would be called for those arguments. Applied
to a variable, it returns the module in which the variable was bound. It calls out to the
[`which`](@ref) function.


Review comment (suggestion):
This seems very sketchy, since `Ref(nt)` is a perfectly fine, and somewhat common, thing to normally encounter in an AST already (after this function called macroexpand). There should not be any unique behavior of calling `typeof` based on the value of a object found in the code.

Code after:
                    binding_reflection = :(error("expression is not a function call"))
                end
                return quote
                    local arg1 = $(esc(ex0.args[1]))
                    if isa(arg1, Module)
                        $binding_reflection
                    else
                        $call_reflection
                    end
                end
            end
        end
        if is_broadcasting_expr(ex0)
            return Expr(:call, :error, "dot expressions are not lowered to "
                * "a single function call, so @$fcn cannot analyze "
                * "them. You may want to use Meta.@lower to identify "
                * "which function call to target.")
        end
        if any(@nospecialize(a)->(isexpr(a, :kw) || isexpr(a, :parameters)), ex0.args)
            args, kwargs = separate_kwargs(ex0.args)
            are_kwargs_valid(kwargs) || return quote
                error("keyword argument format unrecognized; they must be of the form `x` or `x = <value>`")
                $(esc(ex0)) # trigger syntax errors if any
            end
            nt = generate_merged_namedtuple_type(kwargs)
            nt = Ref(nt) # ignore `get_typeof` handling
            return gen_call(fcn, Any[Core.kwcall, nt, args...], where_params, kws; use_signature_tuple)
        elseif ex0.head === :call
            args = copy(ex0.args)
            if ex0.args[1] === :^ && length(ex0.args) >= 3 && isa(ex0.args[3], Int)
                pushfirst!(args, Base.literal_pow)
                args[4] = :(Val($(ex0.args[3])))
            end
            return gen_call(fcn, args, where_params, kws; use_signature_tuple, not_an_opaque_closure = false)
        elseif ex0.head === :(=) && length(ex0.args) == 2
            lhs, rhs = ex0.args
            if isa(lhs, Expr)
                if lhs.head === :(.)
                    return gen_call(fcn, Any[Base.setproperty!, lhs.args..., rhs], where_params, kws; use_signature_tuple)
                elseif lhs.head === :ref
                    return expand_ref_begin_end!(lhs, __module__) do ex
                        gen_call(fcn, Any[setindex!, ex.args[1], rhs, ex.args[2:end]...], where_params, kws; use_signature_tuple)
                    end
                end
            end
        elseif ex0.head === :vcat || ex0.head === :typed_vcat
            if ex0.head === :vcat
                f, hf = Base.vcat, Base.hvcat
                args = ex0.args
            else
                f, hf = Base.typed_vcat, Base.typed_hvcat