Repository: JuliaLang/julia
File: JuliaLowering/src/compat.jl (Julia)

Code before:
        QuoteNode(est_to_expr(st[1]))
    else
        # TODO: should handle post-lowering forms as well
        @assert !is_leaf(st) "est_to_expr should only be used pre-desugaring"
        # In a partially-expanded or quoted AST, there may be heads with no
        # corresponding kind
        head = Symbol(k === K"unknown_head" ? st.name_val : untokenize(k))
        out = Expr(head)

        # (Move the following assumptions to the docs if they turn out accurate)
        # The only mandatory LineNumberNode is the second macrocall argument.
        # Other than that, optional linenodes may show up anywhere within:
        # - `block`, unless the block is the first child of `for` or `let`
        # - `toplevel`
        # Macro authors are responsible for handling any linenodes that follow
        # the rules above (but the presence of optional linenodes can't be
        # counted upon).
        need_lnns = head in (:block, :toplevel) && !suppress_linenodes
        for (i, c) in enumerate(children(st))
            need_lnns && push!(out.args, source_location(LineNumberNode, c))
            let suppress_c = i == 1 && (k == K"for" || k == K"let")
                push!(out.args, est_to_expr(c, suppress_c))
            end
        end
        # Add extra linenodes to some blocks for better provenance
        @stm st begin
            ([K"block"], when=!suppress_linenodes) ->
                push!(out.args, source_location(LineNumberNode, st))
            [K"module" _... [K"block" _...]] ->
                pushfirst!(out.args[end].args, source_location(LineNumberNode, st))
            [K"function" _ [K"block" _...]] ->
                pushfirst!(out.args[end].args, source_location(LineNumberNode, st))
            [K"macro" _ [K"block" _...]] ->
                pushfirst!(out.args[end].args, source_location(LineNumberNode, st))
            [K"for" _ [K"block" _...]] ->
                push!(out.args[end].args, source_location(
                    LineNumberNode, sourcefile(st), last_byte(st)))
            [K"while" _ [K"block" _...]] ->
                push!(out.args[end].args, source_location(
                    LineNumberNode, sourcefile(st), last_byte(st)))
            _ -> nothing
        end
        out
    end
end

#-------------------------------------------------------------------------------
# EST->DST

# .op => (. op)
function _dst_separate_dotop(st::SyntaxTree)

Review comment (suggestion):
```suggestion
            let suppress_linenodes = i == 1 && (k == K"for" || k == K"let")
                push!(out.args, est_to_expr(c; suppress_linenodes))
            end
```

Code after:
        # Expr(st.value).
        isa_lowering_ast_node(v) ? QuoteNode(v) : v
    elseif k === K"inert"
        QuoteNode(est_to_expr(st[1]))
    else
        # TODO: should handle post-lowering forms as well
        @assert !is_leaf(st) "est_to_expr should only be used pre-desugaring"
        # In a partially-expanded or quoted AST, there may be heads with no
        # corresponding kind
        head = Symbol(k === K"unknown_head" ? st.name_val : untokenize(k))
        out = Expr(head)

        # (Move the following assumptions to the docs if they turn out accurate)
        # The only mandatory LineNumberNode is the second macrocall argument.
        # Other than that, optional linenodes may show up anywhere within:
        # - `block`, unless the block is the first child of `for` or `let`
        # - `toplevel`
        # Macro authors are responsible for handling any linenodes that follow
        # the rules above (but the presence of optional linenodes can't be
        # counted upon).
        need_lnns = head in (:block, :toplevel) && !suppress_linenodes
        for (i, c) in enumerate(children(st))
            need_lnns && push!(out.args, source_location(LineNumberNode, c))
            let suppress_c = i == 1 && (k == K"for" || k == K"let")
                push!(out.args, est_to_expr(c, suppress_c))
            end
        end
        # Add extra linenodes to some blocks for better provenance
        @stm st begin
            ([K"block"], when=!suppress_linenodes) ->
                push!(out.args, source_location(LineNumberNode, st))
            [K"module" _... [K"block" _...]] ->
                pushfirst!(out.args[end].args, source_location(LineNumberNode, st))
            [K"function" _ [K"block" _...]] ->
                pushfirst!(out.args[end].args, source_location(LineNumberNode, st))
            [K"macro" _ [K"block" _...]] ->
                pushfirst!(out.args[end].args, source_location(LineNumberNode, st))
            [K"for" _ [K"block" _...]] ->
                push!(out.args[end].args, source_location(
                    LineNumberNode, sourcefile(st), last_byte(st)))
            [K"while" _ [K"block" _...]] ->
                push!(out.args[end].args, source_location(
                    LineNumberNode, sourcefile(st), last_byte(st)))
            _ -> nothing
        end
        out
    end
end

#-------------------------------------------------------------------------------
# EST->DST