How is destructuring transformed\lowered

#1

I have seen it mentioned before that:

function f((x,y))

is effectively transformed to

function f(temp)
    x , y = temp

But I don’t think that it is documented anywhere how x , y = temp is transformed.

Could somebody please explain?

0 Likes

#2
julia> Meta.@lower  x , y = temp
:($(Expr(:thunk, CodeInfo(
 1 ─ %1 = (Base.indexed_iterate)(temp, 1)                                         │
 │   %2 = (Core.getfield)(%1, 1)                                                  │
 │        x = %2                                                                  │
 │        #s1 = (Core.getfield)(%1, 2)                                            │
 │   %5 = (Base.indexed_iterate)(temp, 2, #s1)                                    │
 │   %6 = (Core.getfield)(%5, 1)                                                  │
 │        y = %6                                                                  │
 └──      return temp                                                             │
))))

It’s just a slightly fancier version of manually unrolled iteration.

1 Like

#3

How about the destructuring of next in the lowering of a for loop?
Does it get lower straight to a getfield?

0 Likes

#4

What do you mean next?

0 Likes

#5

https://docs.julialang.org/en/v1.2-dev/manual/interfaces/

for i in iter   # or  "for i = iter"
    # body
end

is translated into:

next = iterate(iter)
while next !== nothing
    (i, state) = next
    # body
    next = iterate(iter, state)
end

I know that portion of the documenation is out of date it is more like:

next = iterate(iter)
next === nothing && @goto loop_end
    @label loop_head
    (i, state) = next
    # body
    next = iterate(iter, state)
    next === nothing && @goto loop_end
    @goto loop_head
@label loop_end

But it appears that lowering of for today may be breaking the interface by skiping the indexed_iterate of destructuring and going straight to:

next = iterate(iter)
next === nothing && @goto loop_end
    @label loop_head
    i = getfield(next,1)
    state = getfield(next,2)
    # body
    next = iterate(iter, state)
    next === nothing && @goto loop_end
    @goto loop_head
@label loop_end
0 Likes

#6

Yup. We should add an assertion to guarantee that iterate returns a tuple like it’s supposed to. I’d guess it’s this way because for loops are extraordinarily performance sensitive.

1 Like

#7

I think I understand the reasoning but check out the benchmark here

0 Likes