Hello everyone,
I am currently playing with lowered code and I would like to understand how to identify pathological cases. In the following example, a variable b
gets conditionnaly assigned at step 1
of the loop and then used to double the value of a
at other steps.
When we look at the lowered code below (with Meta.lower(Main,e)
), we see at step 15
that a SlotNumber
for the variable b
is assigned and used at step 17
, so by looking at the lowered code it seems that we shouldn’t get an error when executing it.
I understand why we get an error during execution since simply changing the condition to i!=1
gives a pathological case. So in general this code is wrong since we need execution to get the value for the branching at step 12.
So my question is: Does Julia provide another representation showing that this code is pathological ?
I tried looking at code_typed(f,())
or code_llvm(f,();optimize=false)
but before going further I would like to know your thoughts about this.
julia> e=quote function f()
a=1
for i in 1:10
if i==1
a+=1
b=2
else
a*=b
end
end
a
end end;
julia> eval(e)();
ERROR: UndefVarError: b not defined
Stacktrace:
[1] f() at .\REPL[43]:8
[2] top-level scope at REPL[44]:1
julia> collect(enumerate(getci(e).code))
23-element Array{Tuple{Int64,Any},1}:
(1, :(a = 1))
(2, :(1:10))
(3, :(_1 = Base.iterate(%2)))
(4, :(_1 === nothing))
(5, :(Base.not_int(%4)))
(6, :(unless %5 goto %23))
(7, Core.NewvarNode(:(_3)))
(8, Core.NewvarNode(:(_4)))
(9, :(_1))
(10, :(_2 = Core.getfield(%9, 1)))
(11, :(Core.getfield(%9, 2)))
(12, :(_2 == 1))
(13, :(unless %12 goto %17))
(14, :(_4 = _4 + 1))
(15, :(_3 = 2))
(16, :(goto %18))
(17, :(_4 = _4 * _3))
(18, :(_1 = Base.iterate(%2, %11)))
(19, :(_1 === nothing))
(20, :(Base.not_int(%19)))
(21, :(unless %20 goto %23))
(22, :(goto %7))
(23, :(return a))