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

Code before:
#-------------------------------------------------------------------------------
function set_scope_layer(ctx, ex, layer_id, force)
    k = kind(ex)
    scope_layer = force ? layer_id : get(ex, :scope_layer, layer_id)
    if k == K"module" || k == K"toplevel" || k == K"inert"
        makenode(ctx, ex, ex, children(ex);
                 scope_layer=scope_layer)
    elseif k == K"."
        makenode(ctx, ex, ex, set_scope_layer(ctx, ex[1], layer_id, force), ex[2],
                 scope_layer=scope_layer)
    elseif !is_leaf(ex)
        mapchildren(e->set_scope_layer(ctx, e, layer_id, force), ctx, ex;
                    scope_layer=scope_layer)
    else
        makeleaf(ctx, ex, ex;
                 scope_layer=scope_layer)
    end
end

"""
    adopt_scope(ex, ref)

Copy `ex`, adopting the scope layer of `ref`.
"""
function adopt_scope(ex::SyntaxTree, scope_layer::LayerId)
    set_scope_layer(ex, ex, scope_layer, true)
end

function adopt_scope(ex::SyntaxTree, layer::ScopeLayer)
    adopt_scope(ex, layer.id)
end

function adopt_scope(ex::SyntaxTree, ref::SyntaxTree)
    adopt_scope(ex, ref.scope_layer)
end

function adopt_scope(exs::SyntaxList, ref)
    out = SyntaxList(syntax_graph(exs))
    for e in exs
        push!(out, adopt_scope(e, ref))
    end
    return out
end

# Type for `meta` attribute, to replace `Expr(:meta)`.
# It's unclear how much flexibility we need here - is a dict good, or could we
# just use a struct? Likely this will be sparse. Alternatively we could just
# use individual attributes but those aren't easy to add on an ad-hoc basis in
# the middle of a pass.
const CompileHints = Base.ImmutableDict{Symbol,Any}


Review comment (suggestion):
I ran JETLS on JuliaLowering today and found this `children` is undefined.

Code after:
    elseif src1 isa NodeId
        _copy_ast(graph2, graph1, src1, seen, copy_source)
    elseif src1 isa Tuple
        map(i->_copy_ast(graph2, graph1, i, seen, copy_source), src1)
    else
        src1
    end
    copy_attrs!(SyntaxTree(graph2, id2), SyntaxTree(graph1, id1), true)
    setattr!(graph2, id2, :source, src2)
    if !is_leaf(graph1, id1)
        cs = NodeId[]
        for cid in children(graph1, id1)
            push!(cs, _copy_ast(graph2, graph1, cid, seen, copy_source))
        end
        setchildren!(graph2, id2, cs)
    end
    return id2
end

#-------------------------------------------------------------------------------
function set_scope_layer(ctx, ex, layer_id, force)
    k = kind(ex)
    new_layer = force ? layer_id : get(ex, :scope_layer, layer_id)

    ex2 = if k == K"module" || k == K"toplevel" || k == K"inert"
        makenode(ctx, ex, ex, children(ex))
    elseif k == K"."
        children = NodeId[set_scope_layer(ctx, ex[1], layer_id, force), ex[2]]
        makenode(ctx, ex, ex, children)
    elseif !is_leaf(ex)
        mapchildren(e->set_scope_layer(ctx, e, layer_id, force), ctx, ex)
    else
        makeleaf(ctx, ex, ex)
    end
    setattr!(ex2, :scope_layer, new_layer)
end

"""
    adopt_scope(ex, ref)

Copy `ex`, adopting the scope layer of `ref`.
"""
function adopt_scope(ex::SyntaxTree, scope_layer::LayerId)
    set_scope_layer(ex._graph, ex, scope_layer, true)
end

function adopt_scope(ex::SyntaxTree, layer::ScopeLayer)
    adopt_scope(ex, layer.id)
end

function adopt_scope(ex::SyntaxTree, ref::SyntaxTree)