I’m trying to do a macro that wraps around a for loop and does the following:
- adds some code before and inside the loop, specifically it creates and updates a Term.jl progressbar.
- it puts the loop inside a
try/finallystatement to correctly stop the progressbar if something goes wrong (otherwise this would cause issues).
I’ve got most of it to work, but if the body of the for loop uses a variable that is defined in the local scope where the loop is done, the macro can’t see it (hence why I think I should put an
esc somewhere, but don’t know where).
This is what I’ve got:
macro track(args...) quote # get pbar number of iterations iterobj = $args.args.args N = length(eval(iterobj)) # get loop expressions loop_header = $args.args loop_body = $args.args # do loop in try expression to ensure pbar stops pbar = nothing # to have access to it in the try scope try # start progressbar pbar = ProgressBar() start!(pbar) __pbarjob = addjob!(pbar; N=N) # create new expression for loop complete = Expr( $args.head, loop_header, Expr( loop_body.head, loop_body.args..., :(sleep(.01)), :(update!($__pbarjob)) ) ) # evaluate new expression eval(complete) finally stop!(pbar) end end end
complete is an
Expr that includes the original loop with an additional line in the body:
:(update!($__pbarjob)) to update the progressbar.
Then if I do something like this:
function test() @track for i in 1:10 sleep(0.005) end end test()
it works and I get a progress bar update at each iteration of the loop:
However, if I change
function test() x = 0 @track for i in 1:10 x += 1 sleep(0.005) end println(x) end
ERROR: UndefVarError: x not defined Stacktrace:  top-level scope @ ~/Documents/Github/Term.jl/temp2.jl:48 [inlined]  top-level scope @ ./none:0
Any idea what I should change to make this work?