Hi everyone,
I have a macro question. It’s probably something about variables hygene as mentioned in this other topic, but I can’t quite figure out, any help would be appreciated
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/finally
statement 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[1].args[1].args[2]
N = length(eval(iterobj))
# get loop expressions
loop_header = $args[1].args[1]
loop_body = $args[1].args[2]
# 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[1].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 test
to:
function test()
x = 0
@track for i in 1:10
x += 1
sleep(0.005)
end
println(x)
end
I get:
ERROR: UndefVarError: x not defined
Stacktrace:
[1] top-level scope
@ ~/Documents/Github/Term.jl/temp2.jl:48 [inlined]
[2] top-level scope
@ ./none:0
Any idea what I should change to make this work?