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

Code before:
    is_single_assign::Bool
    is_maybe_undef::Bool
    is_called::Bool
end

function compile_lambda(outer_ctx, ex)
    lambda_args = ex[1]
    static_parameters = ex[2]
    ret_var = numchildren(ex) == 4 ? ex[4] : nothing
    lambda_bindings = ex.lambda_bindings
    ctx = LinearIRContext(outer_ctx, ex.is_toplevel_thunk, lambda_bindings, ret_var)
    for arg in children(lambda_args)
        kind(arg) == K"Placeholder" && continue
        @assert kind(arg) == K"BindingId"
        id = arg.var_id
        binfo = get_binding(ctx, id)
        if binfo.is_assigned
            @assert !haskey(ctx.argmap, binfo.name)
            ctx.argmap[binfo.id] = new_local_binding(ctx, binding_ex(ctx, binfo), binfo.name)
        end
    end
    compile_body(ctx, ex[3])
    for (binding_id, local_slot) in pairs(ctx.argmap)
        binding = binding_ex(ctx, binding_id)
        pushfirst!(ctx.code, @ast ctx binding [K"=" local_slot binding])
    end
    slots = Vector{Slot}()
    slot_rewrites = Dict{IdTag,Int}()
    for arg in children(lambda_args)
        if kind(arg) == K"Placeholder"
            # Unused functions arguments like: `_` or `::T`
            push!(slots, Slot(arg.name_val, :argument, getmeta(arg, :nospecialize, false),
                              false, false, false, false))
        else
            @assert kind(arg) == K"BindingId"
            id = arg.var_id
            binfo = get_binding(ctx, id)
            @assert binfo.kind == :local || binfo.kind == :argument
            push!(slots, Slot(binfo.name, :argument, binfo.is_nospecialize,
                              binfo.is_read, binfo.is_assigned_once,
                              binfo.is_used_undef, binfo.is_called))
            slot_rewrites[id] = length(slots)
        end
    end
    # Sorting the lambda locals is required to remove dependence on Dict iteration order.
    for (id, is_capt) in sort(collect(pairs(lambda_bindings.locals_capt)), by=first)
        if !is_capt
            binfo = get_binding(ctx.bindings, id)
            if binfo.kind == :local
                push!(slots, Slot(binfo.name, :local, false,
                                  binfo.is_read, binfo.is_assigned_once,

Review comment (suggestion):
I wonder why flisp postpones this to after the `compile` call instead of just pushing the assignments first

Code after:
    name::String
    kind::Symbol
    is_nospecialize::Bool
    is_read::Bool
    is_single_assign::Bool
    is_maybe_undef::Bool
    is_called::Bool
end

function compile_lambda(outer_ctx, ex)
    lambda_args = ex[1]
    static_parameters = ex[2]
    ret_var = numchildren(ex) == 4 ? ex[4] : nothing
    lambda_bindings = ex.lambda_bindings
    ctx = LinearIRContext(outer_ctx, ex.is_toplevel_thunk, lambda_bindings, ret_var)
    for arg in children(lambda_args)
        kind(arg) == K"Placeholder" && continue
        @assert kind(arg) == K"BindingId"
        id = arg.var_id
        binfo = get_binding(ctx, id)
        if binfo.is_assigned
            @assert !haskey(ctx.argmap, binfo.id)
            ctx.argmap[binfo.id] = new_local_binding(ctx, binding_ex(ctx, binfo), binfo.name).var_id
        end
    end
    compile_body(ctx, ex[3])
    for (id, remapped) in pairs(ctx.argmap)
        binding = binding_ex(ctx, id)
        local_slot = binding_ex(ctx, remapped)
        pushfirst!(ctx.code, @ast ctx binding [K"=" local_slot binding])
    end
    slots = Vector{Slot}()
    slot_rewrites = Dict{IdTag,Int}()
    for arg in children(lambda_args)
        if kind(arg) == K"Placeholder"
            # Unused functions arguments like: `_` or `::T`
            push!(slots, Slot(arg.name_val, :argument, getmeta(arg, :nospecialize, false),
                              false, false, false, false))
        else
            @assert kind(arg) == K"BindingId"
            id = arg.var_id
            binfo = get_binding(ctx, id)
            @assert binfo.kind == :local || binfo.kind == :argument
            push!(slots, Slot(binfo.name, :argument, binfo.is_nospecialize,
                              binfo.is_read, binfo.is_assigned_once,
                              binfo.is_used_undef, binfo.is_called))
            slot_rewrites[id] = length(slots)
        end
    end
    # Sorting the lambda locals is required to remove dependence on Dict iteration order.
    for (id, is_capt) in sort(collect(pairs(lambda_bindings.locals_capt)), by=first)