Skip to content

Commit ff1fd50

Browse files
committed
Use normal RuntimeGeneratedFunction constructor rather than macro
Now that users need to manually call init(), this macro really doesn't do much and obscures the scope which the function will pull global symbols from.
1 parent b1f9daa commit ff1fd50

File tree

3 files changed

+38
-42
lines changed

3 files changed

+38
-42
lines changed

src/RuntimeGeneratedFunctions.jl

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,16 @@ module RuntimeGeneratedFunctions
22

33
using ExprTools, Serialization, SHA
44

5-
export @RuntimeGeneratedFunction
5+
export RuntimeGeneratedFunction, @RuntimeGeneratedFunction
66

77

88
"""
9-
RuntimeGeneratedFunction
9+
RuntimeGeneratedFunction(module, function_expression)
1010
11-
This type should be constructed via the macro @RuntimeGeneratedFunction.
12-
"""
13-
struct RuntimeGeneratedFunction{argnames,moduletag,id} <: Function
14-
body::Expr
15-
function RuntimeGeneratedFunction(moduletag, ex)
16-
def = splitdef(ex)
17-
args, body = normalize_args(def[:args]), def[:body]
18-
id = expr_to_id(body)
19-
cached_body = _cache_body(moduletag, id, body)
20-
new{Tuple(args),moduletag,id}(cached_body)
21-
end
22-
end
23-
24-
"""
25-
@RuntimeGeneratedFunction(function_expression)
26-
27-
Construct a function from `function_expression` which can be called immediately
28-
without world age problems. Somewhat like using `eval(function_expression)` and
29-
then calling the resulting function. The differences are:
11+
Construct a function from `function_expression` in the scope of `module` which
12+
can be called immediately without world age problems. Somewhat like using
13+
`eval(function_expression)` and then calling the resulting function. The
14+
differences are:
3015
3116
* The result can be called immediately (immune to world age errors)
3217
* The result is not a named generic function, and doesn't participate in
@@ -41,21 +26,32 @@ RuntimeGeneratedFunctions.init(@__MODULE__) # Required at module top-level
4126
4227
function foo()
4328
expression = :((x,y)->x+y+1) # May be generated dynamically
44-
f = @RuntimeGeneratedFunction(expression)
29+
f = RuntimeGeneratedFunction(@__MODULE__, expression)
4530
f(1,2) # May be called immediately
4631
end
4732
```
4833
"""
49-
macro RuntimeGeneratedFunction(ex)
50-
quote
51-
if !($(esc(:(@isdefined($_tagname)))))
34+
struct RuntimeGeneratedFunction{argnames,moduletag,id} <: Function
35+
body::Expr
36+
function RuntimeGeneratedFunction(mod::Module, ex)
37+
if !isdefined(mod, _tagname)
5238
error("""You must use `RuntimeGeneratedFunctions.init(@__MODULE__)` at module
5339
top level before using runtime generated functions""")
5440
end
55-
RuntimeGeneratedFunction(
56-
$(esc(_tagname)),
57-
$(esc(ex))
58-
)
41+
moduletag = getfield(mod, _tagname)
42+
def = splitdef(ex)
43+
args, body = normalize_args(def[:args]), def[:body]
44+
id = expr_to_id(body)
45+
cached_body = _cache_body(moduletag, id, body)
46+
new{Tuple(args),moduletag,id}(cached_body)
47+
end
48+
end
49+
50+
51+
macro RuntimeGeneratedFunction(ex)
52+
Base.depwarn("`@RuntimeGeneratedFunction(ex)` is deprecated, use `RuntimeGeneratedFunction(@__MODULE__, ex)` instead.", :RuntimeGeneratedFunction)
53+
quote
54+
RuntimeGeneratedFunction(@__MODULE__, $(esc(ex)))
5955
end
6056
end
6157

@@ -68,7 +64,7 @@ end
6864
(f::RuntimeGeneratedFunction)(args::Vararg{Any,N}) where N = generated_callfunc(f, args...)
6965

7066
# We'll generate a method of this function in every module which wants to use
71-
# @RuntimeGeneratedFunction
67+
# RuntimeGeneratedFunction
7268
function generated_callfunc end
7369

7470
function generated_callfunc_body(argnames, moduletag, id, __args)
@@ -138,7 +134,7 @@ end
138134
RuntimeGeneratedFunctions.init(mod)
139135
140136
Use this at top level to set up your module `mod` before using
141-
`@RuntimeGeneratedFunction`.
137+
`RuntimeGeneratedFunction(mod, ...)`.
142138
"""
143139
function init(mod)
144140
lock(_cache_lock) do

test/precomp/RGFPrecompTest.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ module RGFPrecompTest
22
using RuntimeGeneratedFunctions
33
RuntimeGeneratedFunctions.init(@__MODULE__)
44

5-
f = @RuntimeGeneratedFunction(:((x,y)->x+y))
5+
f = RuntimeGeneratedFunction(@__MODULE__, :((x,y)->x+y))
66
end

test/runtests.jl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ ex3 = :(function (_du::T,_u::Vector{E},_p::P,_t::Any) where {T<:Vector,E,P}
2727
nothing
2828
end)
2929

30-
f1 = @RuntimeGeneratedFunction(ex1)
31-
f2 = @RuntimeGeneratedFunction(ex2)
32-
f3 = @RuntimeGeneratedFunction(ex3)
30+
f1 = RuntimeGeneratedFunction(@__MODULE__, ex1)
31+
f2 = RuntimeGeneratedFunction(@__MODULE__, ex2)
32+
f3 = RuntimeGeneratedFunction(@__MODULE__, ex3)
3333

3434
@test f1 isa Function
3535

@@ -62,7 +62,7 @@ function no_worldage()
6262
@inbounds _du[2] = _u[2]
6363
nothing
6464
end)
65-
f1 = @RuntimeGeneratedFunction(ex)
65+
f1 = RuntimeGeneratedFunction(@__MODULE__, ex)
6666
du = rand(2)
6767
u = rand(2)
6868
p = nothing
@@ -72,7 +72,7 @@ end
7272
@test no_worldage() === nothing
7373

7474
# Test show()
75-
@test sprint(show, @RuntimeGeneratedFunction(Base.remove_linenums!(:((x,y)->x+y+1)))) ==
75+
@test sprint(show, RuntimeGeneratedFunction(@__MODULE__, Base.remove_linenums!(:((x,y)->x+y+1)))) ==
7676
"""
7777
RuntimeGeneratedFunction(#=in $(@__MODULE__)=#, :((x, y)->begin
7878
x + y + 1
@@ -86,9 +86,9 @@ using RGFPrecompTest
8686

8787
# Test that RuntimeGeneratedFunction with identical body expressions (but
8888
# allocated separately) don't clobber each other when one is GC'd.
89-
f_gc = @RuntimeGeneratedFunction(Base.remove_linenums!(:((x,y)->x+y+100001)))
89+
f_gc = RuntimeGeneratedFunction(@__MODULE__, Base.remove_linenums!(:((x,y)->x+y+100001)))
9090
let
91-
@RuntimeGeneratedFunction(Base.remove_linenums!(:((x,y)->x+y+100001)))
91+
RuntimeGeneratedFunction(@__MODULE__, Base.remove_linenums!(:((x,y)->x+y+100001)))
9292
end
9393
GC.gc()
9494
@test f_gc(1,-1) == 100001
@@ -100,7 +100,7 @@ for k=1:4
100100
t = Threads.@spawn begin
101101
r = Bool[]
102102
for i=1:100
103-
f = @RuntimeGeneratedFunction(Base.remove_linenums!(:((x,y)->x+y+$i*$k)))
103+
f = RuntimeGeneratedFunction(@__MODULE__, Base.remove_linenums!(:((x,y)->x+y+$i*$k)))
104104
x = 1; y = 2;
105105
push!(r, f(x,y) == x + y + i*k)
106106
end
@@ -119,13 +119,13 @@ module GlobalsTest
119119
RuntimeGeneratedFunctions.init(@__MODULE__)
120120

121121
y = 40
122-
f = @RuntimeGeneratedFunction(:(x->x+y))
122+
f = RuntimeGeneratedFunction(@__MODULE__, :(x->x+y))
123123
end
124124

125125
@test GlobalsTest.f(2) == 42
126126

127127
@test_throws ErrorException @eval(module NotInitTest
128128
using RuntimeGeneratedFunctions
129129
# RuntimeGeneratedFunctions.init(@__MODULE__) # <-- missing
130-
f = @RuntimeGeneratedFunction(:(x->x+y))
130+
f = RuntimeGeneratedFunction(@__MODULE__, :(x->x+y))
131131
end)

0 commit comments

Comments
 (0)