# Save code generated by macro to file

**URL:** <https://discourse.julialang.org/t/save-code-generated-by-macro-to-file/64760>\
**Category:** General Usage\
**Tags:** macros\
**Created:** [July 16, 2021, 4:09pm UTC](https://discourse.julialang.org/t/save-code-generated-by-macro-to-file/64760 "2021-07-16T16:09:50Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![sloede](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sloede/32/44787_2.png) [@sloede](https://discourse.julialang.org/u/sloede)\
**Post date:** [July 16, 2021, 4:09pm UTC](https://discourse.julialang.org/t/save-code-generated-by-macro-to-file/64760/1 "2021-07-16T16:09:50Z")

</div>

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.

To be clear, I’d like to turn

```julia
module MyModule
  c"""
    // here be dragons
  """
end

```

into

```julia
module MyModule
  include("herebedragons.jl")
end

```

What would be the Julian way to achieve this?

---

<div class="post-metadata">

**Author:** ![abulak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abulak/32/28314_2.png) [@abulak](https://discourse.julialang.org/u/abulak)\
**Post date:** [July 16, 2021, 4:32pm UTC](https://discourse.julialang.org/t/save-code-generated-by-macro-to-file/64760/2 "2021-07-16T16:32:12Z")

</div>

the julian way is not to save it 😉

just generate the `MyModule` inside your package scope. code generation will happen once per precompilation

---

<div class="post-metadata">

**Author:** ![sloede](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sloede/32/44787_2.png) [@sloede](https://discourse.julialang.org/u/sloede)\
**Post date:** [July 16, 2021, 4:43pm UTC](https://discourse.julialang.org/t/save-code-generated-by-macro-to-file/64760/3 "2021-07-16T16:43:50Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [July 16, 2021, 5:12pm UTC](https://discourse.julialang.org/t/save-code-generated-by-macro-to-file/64760/4 "2021-07-16T17:12:38Z")

</div>

You could probably serialize the AST you get from `@macroexpand` and then to include it you deserialize and eval it.

```julia
julia> expr = @macroexpand @time 1+1;

julia> using Serialization

julia> serialize("ast.jls", expr);

julia> ast = deserialize("ast.jls");

julia> eval(ast)
  0.000000 seconds
2

```

---

<div class="post-metadata">

**Author:** ![genkuroki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/genkuroki/32/18030_2.png) [@genkuroki](https://discourse.julialang.org/u/genkuroki)\
**Post date:** [July 16, 2021, 6:01pm UTC](https://discourse.julialang.org/t/save-code-generated-by-macro-to-file/64760/5 "2021-07-16T18:01:33Z")

</div>

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`.

```julia
expr = @macroexpand g(x) = @time (sleep(1); sin(x))
write("foo.jl", string(Base.remove_linenums!(expr)))
println(read("def.jl", String)); println()
include("foo.jl")
@show g(π/6);

```

Output:

```julia
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

```

Edit: remove the redundant Base.remove\_linenums!

---

<div class="post-metadata">

**Author:** ![sloede](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sloede/32/44787_2.png) [@sloede](https://discourse.julialang.org/u/sloede)\
**Post date:** [July 16, 2021, 6:33pm UTC](https://discourse.julialang.org/t/save-code-generated-by-macro-to-file/64760/6 "2021-07-16T18:33:53Z")

</div>

> [@genkuroki](#):
>
> 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` .

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?

---

<div class="post-metadata">

**Author:** ![sloede](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sloede/32/44787_2.png) [@sloede](https://discourse.julialang.org/u/sloede)\
**Post date:** [July 16, 2021, 6:34pm UTC](https://discourse.julialang.org/t/save-code-generated-by-macro-to-file/64760/7 "2021-07-16T18:34:59Z")

</div>

Also, why do you need to call remove line numbers twice?

---

<div class="post-metadata">

**Author:** ![genkuroki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/genkuroki/32/18030_2.png) [@genkuroki](https://discourse.julialang.org/u/genkuroki)\
**Post date:** [July 16, 2021, 7:26pm UTC](https://discourse.julialang.org/t/save-code-generated-by-macro-to-file/64760/8 "2021-07-16T19:26:32Z")

</div>

> [@sloede](#):
>
> 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.

Example 1:

```julia
string_remove_linenums!(expr) = string(Base.remove_linenums!(expr))
expr = @macroexpand g(x) = @time (sleep(1); sin(x))
str = string_remove_linenums!(expr)
@show string_remove_linenums!(Meta.parse(str)) == str;

```

Result: `true`

Example 2:

```julia
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;

```

Result: true

> [@sloede](#):
>
> Also, why do you need to call remove line numbers twice?

Simple mistake. I edited and fixed it. 😉
