# using Pkg # Pkg.add("https://github.com/genkuroki/InteractiveUtilsPlus.jl") # using InteractiveUtilsPlus using Base64 showimg(mime, fn; tag="img") = open(fn) do f base64 = base64encode(f) display("text/html", """<$tag src="data:$mime;base64,$base64" />""") end module A macro insert_before_after(funcdef, before, after) funcdef.args[2] = Expr(:block, before, funcdef.args[2], after) esc(funcdef) end end # マクロの展開のされ方 expr = @macroexpand A.@insert_before_after function printadd(a, b) println(a, " + ", b, " = ", a + b) end begin t_start = time() println("start at ", t_start) end begin t_end = time() println("end at ", t_end) println("time elapsed: ", t_end - t_start) end Base.remove_linenums!(expr) A.@insert_before_after function printadd(a, b) println(a, " + ", b, " = ", a + b) end begin t_start = time() println("start at ", t_start) end begin t_end = time() println("end at ", t_end) println("time elapsed: ", t_end - t_start) end printadd(3, 7) printadd(big"2"^200, big"2"^300) @show_tree function printadd(a::T, b::T; c::T=1, d::T=2) where T<:Integer println(a + b + c + d) end Meta.@dump function printadd(a::T, b::T; c::T=1, d::T=2) where T<:Integer println(a + b + c + d) end module B macro insert_before_after(funcdef, before, after) val = gensym() body = Expr(:(=), val, funcdef.args[2]) funcdef.args[2] = Expr(:block, before, body, after, val) esc(funcdef) end end # マクロの展開のされ方 expr = @macroexpand B.@insert_before_after function printadd(a, b) println(a, " + ", b, " = ", a + b) a + b end begin t_start = time() println("start at ", t_start) end begin t_end = time() println("end at ", t_end) println("time elapsed: ", t_end - t_start) end Base.remove_linenums!(expr) print_tree(expr, 10) B.@insert_before_after function printadd(a, b) println(a, " + ", b, " = ", a + b) a + b end begin t_start = time() println("start at ", t_start) end begin t_end = time() println("end at ", t_end) println("time elapsed: ", t_end - t_start) end printadd(123, 456) B.@insert_before_after function foo(a::T; b=456) where T<:Real println(a, " + ", b, " = ", a + b) a + b end begin t_start = time() println("start at ", t_start) end begin t_end = time() println("end at ", t_end) println("time elapsed: ", t_end - t_start) end foo(123) expr = @macroexpand B.@insert_before_after function foo(a::T; b=456) where T<:Real println(a, " + ", b, " = ", a + b) a + b end begin t_start = time() println("start at ", t_start) end begin t_end = time() println("end at ", t_end) println("time elapsed: ", t_end - t_start) end Base.remove_linenums!(expr) print_tree(expr, 10) # original expr_original = :(function bar(a::T; b=456) where T<:Real println(a, " + ", b, " = ", a + b) a + b end) Base.remove_linenums!(expr_original) expr_modified = @macroexpand B.@insert_before_after function bar(a::T; b=456) where T<:Real println(a, " + ", b, " = ", a + b) a + b end println("bar: write start log") println("bar: write end log") Base.remove_linenums!(expr_modified) print_tree(expr_original, 10) print_tree(expr_modified, 10) sleep(0.1) showimg("image/png", "HowToModifyAST.png", tag="img width=90%") function start_log(func_name) println("$(func_name): write start log") end function end_log(func_name) println("$(func_name): write end log") end macro withlog_simple(ex) if Meta.isexpr(ex, :function) s = string(ex.args[1].args[1]) quote function $(esc(ex.args[1].args[1]))($(esc.(ex.args[1].args[2:end])...)) start_log($s) $(esc(ex.args[2])) end_log($s) end end else esc(ex) end end @withlog_simple function bar(a; b=456) println(a, " + ", b, " = ", a + b) a + b end bar(123; b=456) @withlog_simple function bar(a::T; b=456) where T<:Real println(a, " + ", b, " = ", a + b) a + b end expr = @macroexpand @withlog_simple function bar(a::T; b=456) where T<:Real println(a, " + ", b, " = ", a + b) a + b end Base.remove_linenums!(expr) using MacroTools macro withlog(ex) fndef = splitdef(ex) s = string(fndef[:name]) quote function $(esc(fndef[:name]))($(esc.(fndef[:args])...)) start_log($s) $(esc(fndef[:body])) end_log($s) end end # fndef[:name] = esc(fndef[:name]) # fndef[:args] = esc.(fndef[:args]) # bdy = quote # start_log($s) # $(esc(fndef[:body])) # end_log($s) # end # fndef[:body] = bdy # MacroTools.combinedef(fndef) end @withlog function bar(a; b=456) println(a, " + ", b, " = ", a + b) a + b end bar(123; b=456) @withlog function bar(a::T; b=456) where T<:Real println(a, " + ", b, " = ", a + b) a + b end expr = @macroexpand @withlog function bar(a::T; b=456) where T<:Real println(a, " + ", b, " = ", a + b) a + b end Base.remove_linenums!(expr) B.@insert_before_after function bar(a::T; b=456) where T<:Real println(a, " + ", b, " = ", a + b) a + b end println("bar: write start log") println("bar: write end log") bar(123) splitdef(:(function bar(a; b=456) println(a, " + ", b, " = ", a + b) a + b end)) splitdef(:(function bar(a::T; b=456) where T<:Real println(a, " + ", b, " = ", a + b) a + b end))