Skip to content

Commit 3b96455

Browse files
Merge pull request #89 from SciML/getter
Add expression retrieval command
2 parents e13311f + b7328b6 commit 3b96455

File tree

4 files changed

+207
-1
lines changed

4 files changed

+207
-1
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "RuntimeGeneratedFunctions"
22
uuid = "7e49a35a-f44a-4d26-94aa-eba1b4ca6b47"
33
authors = ["Chris Rackauckas <accounts@chrisrackauckas.com> and contributors"]
4-
version = "0.5.12"
4+
version = "0.5.13"
55

66
[deps]
77
ExprTools = "e2ba6199-217a-4e67-a87a-7c52f15ade04"

README.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,101 @@ end
110110
f = g()
111111
@show f(1)
112112
```
113+
114+
## Retrieving Expressions
115+
116+
From a constructed RuntimeGeneratedFunction, you can retrieve the expressions using the
117+
`RuntimeGeneratedFunctions.get_expression` command. For example:
118+
119+
```julia
120+
ex = :((x) -> x^2)
121+
rgf = @RuntimeGeneratedFunction(ex)
122+
julia> RuntimeGeneratedFunctions.get_expression(rgf)
123+
#=
124+
quote
125+
#= c:\Users\accou\OneDrive\Computer\Desktop\test.jl:39 =#
126+
x ^ 2
127+
end
128+
=#
129+
```
130+
131+
This can be used to get the expression even if `drop_expr` has been performed.
132+
133+
### Example: Retrieving Expressions from ModelingToolkit.jl
134+
135+
[ModelingToolkit.jl](https://github.com/SciML/ModelingToolkit.jl) uses
136+
RuntimeGeneratedFunctions.jl for the construction of its functions to avoid issues of
137+
world-age. Take for example its tutorial:
138+
139+
```julia
140+
using ModelingToolkit, RuntimeGeneratedFunctions
141+
using ModelingToolkit: t_nounits as t, D_nounits as D
142+
143+
@mtkmodel FOL begin
144+
@parameters begin
145+
τ # parameters
146+
end
147+
@variables begin
148+
x(t) # dependent variables
149+
end
150+
@equations begin
151+
D(x) ~ (1 - x) / τ
152+
end
153+
end
154+
155+
using DifferentialEquations: solve
156+
@mtkbuild fol = FOL()
157+
prob = ODEProblem(fol, [fol.x => 0.0], (0.0, 10.0), [fol.τ => 3.0])
158+
```
159+
160+
If we check the function:
161+
162+
```julia
163+
julia> prob.f
164+
(::ODEFunction{true, SciMLBase.AutoSpecialize, ModelingToolkit.var"#f#697"{RuntimeGeneratedFunction{(:ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x2cce5cf2, 0xd20b0d73, 0xd14ed8a6, 0xa4d56c4f, 0x72958ea1), Nothing}, RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x7f3c227e, 0x8f116bb1, 0xb3528ad5, 0x9c57c605, 0x60f580c3), Nothing}}, UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, ModelingToolkit.var"#852#generated_observed#706"{Bool, ODESystem, Dict{Any, Any}, Vector{Any}}, Nothing, ODESystem, Nothing, Nothing}) (generic function with 1 method)
165+
```
166+
167+
It's a RuntimeGeneratedFunction. We can find the code for this system using the retrieval
168+
command on the function we want. For example, for the in-place function:
169+
170+
```julia
171+
julia> RuntimeGeneratedFunctions.get_expression(prob.f.f.f_iip)
172+
173+
:((ˍ₋out, ˍ₋arg1, ˍ₋arg2, t)->begin
174+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:373 =#
175+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:374 =#
176+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:375 =#
177+
begin
178+
begin
179+
begin
180+
#= C:\Users\accou\.julia\packages\Symbolics\HIg7O\src\build_function.jl:546 =#
181+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:422 =# @inbounds begin
182+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:418 =#
183+
ˍ₋out[1] = (/)((+)(1, (*)(-1, ˍ₋arg1[1])), ˍ₋arg2[1])
184+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:420 =#
185+
nothing
186+
end
187+
end
188+
end
189+
end
190+
end)
191+
```
192+
193+
or the out-of-place function:
194+
195+
```julia
196+
julia> RuntimeGeneratedFunctions.get_expression(prob.f.f.f_oop)
197+
:((ˍ₋arg1, ˍ₋arg2, t)->begin
198+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:373 =#
199+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:374 =#
200+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:375 =#
201+
begin
202+
begin
203+
begin
204+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:468 =#
205+
(SymbolicUtils.Code.create_array)(typeof(ˍ₋arg1), nothing, Val{1}(), Val{(1,)}(), (/)((+)(1, (*)(-1, ˍ₋arg1[1])), ˍ₋arg2[1]))
206+
end
207+
end
208+
end
209+
end)
210+
```

docs/src/index.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,103 @@ f = g()
102102
@show f(1)
103103
```
104104

105+
## Retrieving Expressions
106+
107+
From a constructed RuntimeGeneratedFunction, you can retrieve the expressions using the
108+
`RuntimeGeneratedFunctions.get_expression` command. For example:
109+
110+
```julia
111+
ex = :((x) -> x^2)
112+
rgf = @RuntimeGeneratedFunction(ex)
113+
julia> RuntimeGeneratedFunctions.get_expression(rgf)
114+
:((x,)->begin
115+
#= REPL[14]:1 =#
116+
x ^ 2
117+
end)
118+
```
119+
120+
This can be used to get the expression even if `drop_expr` has been performed.
121+
122+
### Example: Retrieving Expressions from ModelingToolkit.jl
123+
124+
[ModelingToolkit.jl](https://github.com/SciML/ModelingToolkit.jl) uses
125+
RuntimeGeneratedFunctions.jl for the construction of its functions to avoid issues of
126+
world-age. Take for example its tutorial:
127+
128+
```julia
129+
using ModelingToolkit, RuntimeGeneratedFunctions
130+
using ModelingToolkit: t_nounits as t, D_nounits as D
131+
132+
@mtkmodel FOL begin
133+
@parameters begin
134+
τ # parameters
135+
end
136+
@variables begin
137+
x(t) # dependent variables
138+
end
139+
@equations begin
140+
D(x) ~ (1 - x) / τ
141+
end
142+
end
143+
144+
using DifferentialEquations: solve
145+
@mtkbuild fol = FOL()
146+
prob = ODEProblem(fol, [fol.x => 0.0], (0.0, 10.0), [fol.τ => 3.0])
147+
```
148+
149+
If we check the function:
150+
151+
```julia
152+
julia> prob.f
153+
(::ODEFunction{true, SciMLBase.AutoSpecialize, ModelingToolkit.var"#f#697"{RuntimeGeneratedFunction{(:ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x2cce5cf2, 0xd20b0d73, 0xd14ed8a6, 0xa4d56c4f, 0x72958ea1), Nothing}, RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x7f3c227e, 0x8f116bb1, 0xb3528ad5, 0x9c57c605, 0x60f580c3), Nothing}}, UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, ModelingToolkit.var"#852#generated_observed#706"{Bool, ODESystem, Dict{Any, Any}, Vector{Any}}, Nothing, ODESystem, Nothing, Nothing}) (generic function with 1 method)
154+
```
155+
156+
It's a RuntimeGeneratedFunction. We can find the code for this system using the retrieval
157+
command on the function we want. For example, for the in-place function:
158+
159+
```julia
160+
julia> RuntimeGeneratedFunctions.get_expression(prob.f.f.f_iip)
161+
162+
:((ˍ₋out, ˍ₋arg1, ˍ₋arg2, t)->begin
163+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:373 =#
164+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:374 =#
165+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:375 =#
166+
begin
167+
begin
168+
begin
169+
#= C:\Users\accou\.julia\packages\Symbolics\HIg7O\src\build_function.jl:546 =#
170+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:422 =# @inbounds begin
171+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:418 =#
172+
ˍ₋out[1] = (/)((+)(1, (*)(-1, ˍ₋arg1[1])), ˍ₋arg2[1])
173+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:420 =#
174+
nothing
175+
end
176+
end
177+
end
178+
end
179+
end)
180+
```
181+
182+
or the out-of-place function:
183+
184+
```julia
185+
julia> RuntimeGeneratedFunctions.get_expression(prob.f.f.f_oop)
186+
:((ˍ₋arg1, ˍ₋arg2, t)->begin
187+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:373 =#
188+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:374 =#
189+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:375 =#
190+
begin
191+
begin
192+
begin
193+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:468 =#
194+
(SymbolicUtils.Code.create_array)(typeof(ˍ₋arg1), nothing, Val{1}(), Val{(1,)}(), (/)((+)(1, (*)(-1, ˍ₋arg1[1])), ˍ₋arg2[1]))
195+
end
196+
end
197+
end
198+
end)
199+
```
200+
201+
105202
## Reproducibility
106203

107204
```@raw html

src/RuntimeGeneratedFunctions.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,17 @@ function closures_to_opaque(ex::Expr, return_type = nothing)
331331
return Expr(head, Any[closures_to_opaque(x, return_type) for x in args]...)
332332
end
333333

334+
function get_expression(rgf::RuntimeGeneratedFunction{argnames, cache_tag,
335+
context_tag, id, B}) where {
336+
argnames,
337+
cache_tag,
338+
context_tag,
339+
id,
340+
B
341+
}
342+
func_expr = Expr(:->, Expr(:tuple, argnames...), _lookup_body(cache_tag, id))
343+
end
344+
334345
# We write an explicit serialize() and deserialize() here to manage caching of
335346
# the body on a remote node when using Serialization.jl (in Distributed.jl
336347
# and elsewhere)

0 commit comments

Comments
 (0)