-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Description
When lowering code we have line-number provenance, but I want expression-provenance too.
I'd love it if
ex = quote
if Sys.islinux()
f() = 1; g() = 2
else
g() = 3
end
end
thunk, src = Meta.lower_logged(m, ex)resulted in something along the lines of
# Lowered result Corresponding src entry
:($(Expr(:thunk, CodeInfo(
@ REPL[3]:2 within `top-level scope'
1 ─ %1 = Base.getproperty(Sys, :islinux) :(Sys.islinux)
│ %2 = (%1)() :(Sys.islinux())
└── goto #3 if not %2 ex
@ REPL[3]:3 within `top-level scope'
2 ─ $(Expr(:thunk, CodeInfo( :(f() = 1)
@ none within `top-level scope'
1 ─ return $(Expr(:method, :f))
)))
│ $(Expr(:method, :f)) :(f() = 1)
│ %6 = Core.Typeof(f) :(f)
│ %7 = Core.svec(%6) :(f())
│ %8 = Core.svec() :(f())
│ %9 = Core.svec(%7, %8) :(f())
│ $(Expr(:method, :f, :(%9), CodeInfo(quote :(f() = 1)
return 1
end)))
│ $(Expr(:thunk, CodeInfo( :(g() = 2)
@ none within `top-level scope'
1 ─ return $(Expr(:method, :g))
)))
│ $(Expr(:method, :g)) :(g() = 2)
│ %13 = Core.Typeof(g) :(g)
│ %14 = Core.svec(%13) :(g())
│ %15 = Core.svec() :(g() )
│ %16 = Core.svec(%14, %15) :(g())
│ $(Expr(:method, :g, :(%16), CodeInfo(quote :(g() = 2)
return 2
end)))
└── return g :(g)
@ REPL[3]:5 within `top-level scope'
3 ─ $(Expr(:method, :g)) :(g() = 3)
│ %20 = Core.Typeof(g) :(g)
│ %21 = Core.svec(%20) :(g())
│ %22 = Core.svec() :(g())
│ %23 = Core.svec(%21, %22) :(g())
│ $(Expr(:method, :g, :(%23), CodeInfo(quote :(g() = 3)
return 3
end)))
└── return g :(g)
))))
src here doesn't contain any "new" expressions, just references to the nested contents of ex, specifically the object you've recursed into at the moment you inserted the corresponding line in thunk. It's essentially a log of "what I'm working on now."
You can sometimes get this from the line number info, but as this example partially demonstrates it's fragile (not guaranteed to return complete expressions) and incomplete (might correspond to a block independent of expressions). Moreover, if there aren't any LineNumberNodes in ex, it's impossible. In contrast, the log approach seems quite robust.
I'd implement this myself except for the fact that the key part of this work is in scheme, and I simply don't have time to develop the relevant mastery. I should therefore say I'm not particularly picky about the exact contents of each entry in src, this is just to convey the general idea.
There are interesting questions about whether logs should have sub-logs for the lowered bodies of methods and other internal :thunk expressions. Rather than returning src one could simply make this part of CodeInfo, and then the sub-logs would happen naturally. If one went that way, then there's question of whether this information should survive compression and later retrieval with uncompressed_ast. (I'm guessing that's not on the table as I think it would substantially slow Julia's startup due to pointer relocation.) I'm fine with having this information being transient; getting it out just when lowering manually would be a big win.