Re:A Case for a Native Runtime Compilation Language
by eigenspace on Friday April 30, 2021 @07:40PM
(#27001069)
Julia does this. The only caveat is that if you write
function foo(a, xs)
function bar(b)
b * a
end
res = 0
for x in xs
res += bar(x)
end
res
end
what the author desires (the lifting of a to a compile time constant) won't happen automatically because compiling a new bar for every value of a is going to be a bad idea unless the loop over xs takes longer than compiling a function. Hence, we make people 'opt-in' to this by lifting a from a runtime variable to a type parameter (julia types are parametric and their parameters can contain values).
Hence, one way to do this would be to write
foo(a, xs) = foo(Val{a}, xs)
function foo(::Type{Val{a}}, xs) where {a}
function bar(b)
b * a
end
res = 0
for x in xs
res += bar(x)
end
res
end
Now, when you run foo(2, v) (where v is some iterable), this will turn into foo(Val{2}, v) which then gets specialized on the type parameter {2}, and then can compile a new bar function that's aware of the value of a.
Here's an example at the repl where we can inspect the generated code more easily:
julia> f(a) = f(Val{a})
f (generic function with 1 method)
julia> function f(::Type{Val{a}}) where {a}
function g(b)
b * a
end
end
f (generic function with 2 methods)
julia> g1 = f(1)
(::var"#g#4"{1}) (generic function with 1 method)
julia> @code_llvm debuginfo=:none g1(4)
define i64 @julia_g_442(i64 signext %0) {
top:
ret i64 %0
}
julia> g2 = f(2)
(::var"#g#4"{2}) (generic function with 1 method)
julia> @code_llvm debuginfo=:none g2(4)
define i64 @julia_g_444(i64 signext %0) {
top:
%1 = shl i64 %0, 1
ret i64 %1
}
Notice that g1 and g2 have different optimizations applied that depend on the different runtime values of a.
Hence, one way to do this would be to write
Now, when you run foo(2, v) (where v is some iterable), this will turn into foo(Val{2}, v) which then gets specialized on the type parameter {2}, and then can compile a new bar function that's aware of the value of a.Here's an example at the repl where we can inspect the generated code more easily:
Notice that g1 and g2 have different optimizations applied that depend on the different runtime values of a.