When working on a possible PR for the new Base.Test infrastructure I run 
into a design problem of how to allow flexible control of how the expr 
available to a macro is executed. Sorry if this is trivial but I'd 
appreciate any design ideas/pointers. Simplified code below to try and 
explain what I mean.

# A macro can eval in the calling context:
macro foo(ex)
  quote
      $(esc(ex))
  end
end
a = 1
@foo begin
  a += 1
end
@show(a); # a = 2

# But lets say I want to be able to dynamically control how the expr
# of a macro is executed via a Runner (this is a convoluted/dummy example 
but 
# simplified from a more complex case where there are multiple types 
# of Runners)
type Runner
  reps::Int64
  Runner() = new(2)
end
run(f::Function, r::Runner) = begin
  for i in 1:r.reps
    f()
  end
end

# Is there any way I can "package" the expr a macro has so that its 
execution
# is controlled by an instance of the Runner above while still evaluating
# the expr in the scope where the macro is called?

# First try:
macro foo1(ex)
  quote
    r = Runner()
    run(r) do # UndefVarError since do-block creates new scope?
      $(esc(ex))
    end
  end
end
@foo1 begin
  a += 1 # UndefVarError!
end
@show(a);

# What I could do is maybe have dispatch on Type{Runner}to  generate the 
run code to be spliced into
# the macro but this seems inelegant and maybe error prone since it mixes 
compile-time
# and runtime (since Type{Runner} is needed at macro expansion time).
# Any ideas on a clean and elegant way to accomplish this? 

# Further details at the bottom 
of: https://github.com/JuliaLang/julia/pull/14971

Thanks!

Reply via email to