Can you do array lookup at compile time?

Is it possible to do array lookup at compile time, that is, fully evaluated in macros? When generating functions, known variables can be interpolated all the way to the compiler:

x = 0
f = eval(:(y -> $x*y))
> @code_llvm f(1)
> ; @ REPL[4]:1 within `#3`
> define i64 @"julia_#3_151"(i64 signext %0) #0 {
> top:
> **ret** i64 0
> }

Also known tuples:

x = (0,1,2)
f = eval(:(y -> $x[1]*y))
@code_llvm f(1)
> ; @ REPL[7]:1 within `#5`
> define i64 @"julia_#5_168"(i64 signext %0) #0 {
> top:
> **ret** i64 0
> }

But not known arrays:

x = [0,1,2]
f = eval(:(y -> $x[1]*y))
@code_llvm f(1)
> ; @ REPL[10]:1 within `#7`
> define i64 @"julia_#7_170"(i64 signext %0) #0 {
> top:
> ; ┌ @ array.jl:861 within `getindex`
> %1 = **load** i64, i64* getelementptr ({ i8*, i64, i16, i16, i32 }, { i8*, i64, i16, i16, i32 }* inttoptr (i64 4561887056 to { i8*, i64, i16, i16, i32 }*), i64 0, i32 1), align 8
...

The interpolation doesn’t happen at compile time, it happens while constructing the expression at runtime. The anonymous function is compiled upon first call.

The actual issue is that you’re interpolating the entire x. In other words, $x[1] is equivalent to ($x)[1]. The tuple version works because the compiler is smart enough to figure out that a specific index of an immutable tuple is a constant. The array version doesn’t do that because the array is mutable, so the value at that index might be changed.

If you just want a value in the array to be interpolated, index then interpolate: $(x[1]).

2 Likes