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

Code before:
        elseif isexpr(ex0, :.) && is_source_reflection
            # If `ex0` has the form A.B (or some chain A.B.C.D) and `fcn` reflects into the source,
            # `A` (or `A.B.C`) may be a module, in which case `fcn` is probably more interested in
            # the binding rather than the `getproperty` call.
            # If binding reflection is not supported, we generate an error; `getproperty(::Module, field)`
            # is not going to be interesting to reflect into, so best to allow future non-breaking support
            # for binding reflection in case the macro may eventually support that.
            fully_qualified_symbol = true
            ex1 = ex0
            while ex1 isa Expr && ex1.head === :.
                fully_qualified_symbol = (length(ex1.args) == 2 &&
                                            ex1.args[2] isa QuoteNode &&
                                            ex1.args[2].value isa Symbol)
                fully_qualified_symbol || break
                ex1 = ex1.args[1]
            end
            fully_qualified_symbol &= ex1 isa Symbol
            if fully_qualified_symbol || isexpr(ex1, :(::), 1)
                call_reflection = :($(fcn)(Base.getproperty, $(typesof_expr(ex0.args, where_params))))
                isexpr(ex0.args[1], :(::), 1) && return call_reflection
                if supports_binding_reflection
                    binding_reflection = :($fcn(arg1, $(ex0.args[2])))
                else
                    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)
            tt = rewrap_where(:(Tuple{$nt, $(get_typeof.(args)...)}), where_params)
            return :($(fcn)(Core.kwcall, $tt; $(kws...)))
        elseif ex0.head === :call

Review comment (bug):
This seems like a bad idea to find some random variable by name and then apply random mutation to it (mainly it seems it would result in incorrect code being executed if someone has a statement with multiple `begin` or `end` like `a[end][end]`)

Code after:
    new = replace_ref_begin_end!(__module__, ex)
    modified = ex.args .≠ args
    if any(modified) && (isexpr(arr, :(::), 1) || isexpr(arr, :(::), 2) || isexpr(arr, :..., 1))
        return Expr(:call, :error, "`begin` or `end` cannot be used with a type-annotated left-hand side argument for an indexing syntax")
    end
    call = f(ex)
    !any(modified) && return call
    fixup_hygiene_for_ref_temporary!(new)
    # We have to mutate `ex`, then return `new` which evaluates `arr` before use.
    ex.head = call.head
    ex.args = call.args
    return new
end

function fixup_hygiene_for_ref_temporary!(ex)
    # Match the local variable `##S#...` so we may escape its definition.
    # We don't want to use `escs = 1` in `replace_ref_begin_end_!` because
    # then we delegate escaping to this function, whereas we otherwise manage
    # ourselves the escaping in all other code paths.
    isexpr(ex, :block) || return
    decl = ex.args[1]
    isexpr(decl, :local, 1) || return
    assignment = decl.args[1]
    isexpr(assignment, :(=), 2) || return
    variable = assignment.args[1]
    startswith(string(variable), "##S#") || return
    decl.args[1] = esc(assignment)
end

is_code_macro(fcn) = startswith(string(fcn), "code_")

"""
    gen_call_with_extracted_types(__module__, fcn, ex, kws = Expr[]; is_source_reflection = !is_code_macro(fcn), supports_binding_reflection = false, use_signature_tuple = false)

Destructures the input expression `ex` into a function call or a binding access, then generates a call to either:
- `fcn(f, tt; kws...)`
- `fcn(sigt; kws...)` # if `use_signature_tuple = true`
- `fcn(mod, name; kws...)` # if `supports_binding_reflection = true`

## `fcn` API requirements

`fcn` is a user function expected to satisfy the following API:
- `fcn(f, tt)`: `f` is a value (such as `sum`, unlike `typeof(sum)`), and `tt := Tuple{argtypes...}`
  is a `Tuple` holding argument types. `f` may be a `Core.OpaqueClosure`.

If `use_signature_tuple = true`:
- `fcn(sigt)`: `sigt := Tuple{typeof(f), argtypes...}` represents the low-level signature tuple to be used for introspection.

If `supports_binding_reflection = true`:
- `fcn(mod::Module, name::Symbol)`: `name` is the name of a binding that may or may not exist in `mod`.