Skip to content

Commit c096c08

Browse files
Add expression retrieval command
1 parent e13311f commit c096c08

File tree

4 files changed

+213
-1
lines changed

4 files changed

+213
-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: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,103 @@ 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+
#=
174+
quote
175+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:373 =#
176+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:374 =#
177+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:375 =#
178+
begin
179+
begin
180+
begin
181+
#= C:\Users\accou\.julia\packages\Symbolics\HIg7O\src\build_function.jl:546 =#
182+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:422 =# @inbounds begin
183+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:418 =#
184+
ˍ₋out[1] = (/)((+)(1, (*)(-1, ˍ₋arg1[1])), ˍ₋arg2[1])
185+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:420 =#
186+
nothing
187+
end
188+
end
189+
end
190+
end
191+
end
192+
=#
193+
```
194+
195+
or the out-of-place function:
196+
197+
```julia
198+
julia> RuntimeGeneratedFunctions.get_expression(prob.f.f.f_oop)
199+
quote
200+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:373 =#
201+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:374 =#
202+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:375 =#
203+
begin
204+
begin
205+
begin
206+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:468 =#
207+
(SymbolicUtils.Code.create_array)(typeof(ˍ₋arg1), nothing, Val{1}(), Val{(1,)}(), (/)((+)(1, (*)(-1, ˍ₋arg1[1])), ˍ₋arg2[1]))
208+
end
209+
end
210+
end
211+
end
212+
```

docs/src/index.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,107 @@ 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+
#=
115+
quote
116+
#= c:\Users\accou\OneDrive\Computer\Desktop\test.jl:39 =#
117+
x ^ 2
118+
end
119+
=#
120+
```
121+
122+
This can be used to get the expression even if `drop_expr` has been performed.
123+
124+
### Example: Retrieving Expressions from ModelingToolkit.jl
125+
126+
[ModelingToolkit.jl](https://github.com/SciML/ModelingToolkit.jl) uses
127+
RuntimeGeneratedFunctions.jl for the construction of its functions to avoid issues of
128+
world-age. Take for example its tutorial:
129+
130+
```julia
131+
using ModelingToolkit, RuntimeGeneratedFunctions
132+
using ModelingToolkit: t_nounits as t, D_nounits as D
133+
134+
@mtkmodel FOL begin
135+
@parameters begin
136+
τ # parameters
137+
end
138+
@variables begin
139+
x(t) # dependent variables
140+
end
141+
@equations begin
142+
D(x) ~ (1 - x) / τ
143+
end
144+
end
145+
146+
using DifferentialEquations: solve
147+
@mtkbuild fol = FOL()
148+
prob = ODEProblem(fol, [fol.x => 0.0], (0.0, 10.0), [fol.τ => 3.0])
149+
```
150+
151+
If we check the function:
152+
153+
```julia
154+
julia> prob.f
155+
(::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)
156+
```
157+
158+
It's a RuntimeGeneratedFunction. We can find the code for this system using the retrieval
159+
command on the function we want. For example, for the in-place function:
160+
161+
```julia
162+
julia> RuntimeGeneratedFunctions.get_expression(prob.f.f.f_iip)
163+
164+
#=
165+
quote
166+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:373 =#
167+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:374 =#
168+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:375 =#
169+
begin
170+
begin
171+
begin
172+
#= C:\Users\accou\.julia\packages\Symbolics\HIg7O\src\build_function.jl:546 =#
173+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:422 =# @inbounds begin
174+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:418 =#
175+
ˍ₋out[1] = (/)((+)(1, (*)(-1, ˍ₋arg1[1])), ˍ₋arg2[1])
176+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:420 =#
177+
nothing
178+
end
179+
end
180+
end
181+
end
182+
end
183+
=#
184+
```
185+
186+
or the out-of-place function:
187+
188+
```julia
189+
julia> RuntimeGeneratedFunctions.get_expression(prob.f.f.f_oop)
190+
quote
191+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:373 =#
192+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:374 =#
193+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:375 =#
194+
begin
195+
begin
196+
begin
197+
#= C:\Users\accou\.julia\packages\SymbolicUtils\c0xQb\src\code.jl:468 =#
198+
(SymbolicUtils.Code.create_array)(typeof(ˍ₋arg1), nothing, Val{1}(), Val{(1,)}(), (/)((+)(1, (*)(-1, ˍ₋arg1[1])), ˍ₋arg2[1]))
199+
end
200+
end
201+
end
202+
end
203+
```
204+
205+
105206
## Reproducibility
106207

107208
```@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+
body = _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)