Hi everyone! I am trying to understand the building pieces of JuliaLowering.jl. I am very new to compilers so I apologise in advance if my questions have very obvious answers.
I don’t understand the behaviour of Bindings in the contexts created at each lowering step. Starting from this script I have a bunch of questions:
text = """
x::Int = 10
"""
in_mod = Module()
ex = parseall(JuliaLowering.SyntaxTree, text)
ctx1, ex_macroexpand = JuliaLowering.expand_forms_1(in_mod, ex)
ctx2, ex_desugar = JuliaLowering.expand_forms_2(ctx1, ex_macroexpand)
ctx3, ex_scoped = JuliaLowering.resolve_scopes(ctx2, ex_desugar)
ctx4, ex_converted = JuliaLowering.convert_closures(ctx3, ex_scoped)
ctx5, ex_compiled = JuliaLowering.linearize_ir(ctx4, ex_converted)
-
Should I expect
ctx*to have aBindingInfoforx? I thought yes, but there is none. Why is that? -
While there’s no binding for
x, there is a binding for the return value (I think?),return_tmp:JuliaLowering.BindingInfo(1, "return_tmp", :local, 26, nothing, nothing, 0, false, true, false, true, true, false, false). This only appears in thelinearize_irstep, but it seems that the other contexts are modified as well after each pass (ctx1doesn’t have that binding after runningexpand_forms_1but it does have it after runninglinearize_ir). What is the advantage of not having the contexts independent from each other? -
What is the (theoretical) difference between a lambda binding and a closure binding? My understanding is that lambda bindings are bindings for lambda functions parameters (
x = 2is a lambda binding in the context of the functionx -> x + 3being called with the argument2), while closure bindings are bindings for variables captured by a closure (y = 1is a closure binding in the context of the functionf(x) = x + ywithydefined somewhere above and it has the value1assigned to it). Is this correct? Does the concept of “binding” refer to a name → value association in a particular context, or does it describe something more complex? (For example, is the closure binding the association fromyto1in the context of the functionf(x) = x + ywithy = 1, or is it the entire closure, or something different?) -
Could you maybe point me somewhere I can find some explanations as to how the syntax graph changes from pass to pass? It is quite difficult for me to see this from the source code and I also can’t seem to come up with clarifying examples.
For using the package I followed the instructions in the README.
julia> versioninfo()
Julia Version 1.12.0-DEV.631
Commit a4e793ee31* (2024-05-30 19:25 UTC)
Platform Info:
OS: macOS (arm64-apple-darwin24.3.0)
CPU: 8 × Apple M1
WORD_SIZE: 64
LLVM: libLLVM-17.0.6 (ORCJIT, apple-m1)
Threads: 1 default, 0 interactive, 1 GC (on 4 virtual cores)