I have a string macro that generates a lot of code, and I would like to store this code in a Julia file such that I can just include it the next time it is required. How can I achieve this? I assume it has to be realized using @macroexpand somehow, but I’m wondering how to capture the output such that I get exactly the same behavior when including it as if I’d just left the macro in there.
Unfortunately, that’s not a option, otherwise that would’ve been my first choice. There are technical reasons due to which I cannot run this at precompilation time but need to pre-generate and store the macro output.
Using Serialization.jl is more robust, but you can also use a combination of write("foo.jl", string(expr)) and include("foo.jl"). However, this method can only be used if Meta.parse(string(expr)) is equivalent to expr.
g(x) = begin
begin
while false
end
local var"#30#stats" = Base.gc_num()
local var"#33#compile_elapsedtime" = Base.cumulative_compile_time_ns_before()
local var"#32#elapsedtime" = Base.time_ns()
local var"#31#val" = begin
sleep(1)
sin(x)
end
var"#32#elapsedtime" = Base.time_ns() - var"#32#elapsedtime"
var"#33#compile_elapsedtime" = Base.cumulative_compile_time_ns_after() - var"#33#compile_elapsedtime"
local var"#34#diff" = Base.GC_Diff(Base.gc_num(), var"#30#stats")
Base.time_print(var"#32#elapsedtime", (var"#34#diff").allocd, (var"#34#diff").total_time, Base.gc_alloc_count(var"#34#diff"), var"#33#compile_elapsedtime", true)
var"#31#val"
end
end
1.010495 seconds (145 allocations: 13.766 KiB)
g(π / 6) = 0.49999999999999994
This sounds like a good approach, since I also need to sanitize the macro output using regular expressions (change some hard-coded paths etc.). How can I verify that the equivalence you postulated as a requirement is indeed fulfilled?
Define string_remove_linenums!(expr) = string(Base.remove_linenums!(expr)), set str = string_remove_linenums!(expr), and then we can check whether string_remove_linenums!(Meta.parse(str)) == str is true or not.
macro h(x, p...)
ex = :($(p[end]))
for i in length(p)-1:-1:1
ex = :(muladd($(esc(x)), $ex, $(p[i])))
end
ex
end
string_remove_linenums!(expr) = string(Base.remove_linenums!(expr))
expr = @macroexpand f(x) = (x2 = x^2; x * @h(x2, 1.0, -0.16666666666666666, 0.008333333333333333))
str = string_remove_linenums!(expr)
@show string_remove_linenums!(Meta.parse(str)) == str;