News for hackers. Stuff that matters.
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.
Re:A Case for a Native Runtime Compilation Language by PhilipVinc on Friday April 30, 2021 @04:08PM (#26998637)
Isn’t this roughly what Julia does?
Re:A Case for a Native Runtime Compilation Language by brrrrrm on Friday April 30, 2021 @06:33PM (#27000345)
yes! Julia does compile this way. Julia emphasizes JIT compilation based on runtime types rather than runtime values. I couldn't get runtime captures to work, e.g.

    a = 2
    function f(n)
      return n * a
    end

    println(f(4))
    @code_llvm f(4)
    @code_native f(4)
Re:A Case for a Native Runtime Compilation Language by eigenspace on Friday April 30, 2021 @07:16PM (#27000796)
That's because defining `a = 2` at the top level is a global constant, which can be changed at any time. Hence, the compiler can't optimize it out. If you tell the compiler it's a `const` though, it'll indeed do the optimization you were hoping for

    const a = 2
    f(n) = n * a

    julia> @code_llvm f(4)
    ;  @ REPL[2]:1 within `f'
    define i64 @julia_f_290(i64 signext %0) {
    top:
    ;  @ REPL[2]:2 within `f'
    ; ┌ @ int.jl:88 within `*'
       %1 = shl i64 %0, 1
    ; └
      ret i64 %1
    }

    julia> @code_native f(4)
            .text
    ; ┌ @ REPL[2]:2 within `f'
    ; │┌ @ int.jl:88 within `*'
            leaq    (%rdi,%rdi), %rax
    ; │└
            retq
            nopw    %cs:(%rax,%rax)
    ; └
Re:A Case for a Native Runtime Compilation Language by daly on Sunday May 02, 2021 @04:26AM (#27013340)
Lisp?