@@ -241,32 +241,117 @@ julia> retrieve_code_info((typeof(foo), Float64, Float64)).slotnames
241241This allows to convert the names back to the original. Let's create a dictionary of assignments
242242as
243243``` julia
244- fun_vars = Dict (enumerate (ci. slotnames))
245- lower_vars = Dict (i => gensym (:left ) for i in 1 : length (ci. code))
246-
247- rename_args (ex:: Expr , fun_vars, lower_vars) = Expr (ex. head, rename_args (ex. args, fun_vars, lower_vars))
248- rename_args (args:: AbstractArray , fun_vars, lower_vars) = map (a -> rename_args (a, fun_vars, lower_vars), args)
249- rename_args (a:: Core.SlotNumber , fun_vars, lower_vars) = lower_vars[a. id]
250- rename_args (a:: Core.SSAValue , fun_vars, lower_vars) = fun_vars[a. id]
244+ slot_vars = Dict (enumerate (ci. slotnames))
245+ # ssa_vars = Dict(i => gensym(:left) for i in 1:length(ci.code))
246+ ssa_vars = Dict (i => Symbol (:L ,i) for i in 1 : length (ci. code))
247+
248+ rename_args (ex, slot_vars, ssa_vars) = ex
249+ rename_args (ex:: Expr , slot_vars, ssa_vars) = Expr (ex. head, rename_args (ex. args, slot_vars, ssa_vars)... )
250+ rename_args (args:: AbstractArray , slot_vars, ssa_vars) = map (a -> rename_args (a, slot_vars, ssa_vars), args)
251+ rename_args (r:: Core.ReturnNode , slot_vars, ssa_vars) = Core. ReturnNode (rename_args (r. val, slot_vars, ssa_vars))
252+ rename_args (a:: Core.SlotNumber , slot_vars, ssa_vars) = slot_vars[a. id]
253+ rename_args (a:: Core.SSAValue , slot_vars, ssa_vars) = ssa_vars[a. id]
251254```
252255and let's redo the rewriting once more while replacing the variables and inserting the left-hand equalities
256+ ``` julia
257+ slot_vars = Dict (enumerate (ci. slotnames))
258+ # ssa_vars = Dict(i => gensym(:left) for i in 1:length(ci.code))
259+ ssa_vars = Dict (i => Symbol (:L ,i) for i in 1 : length (ci. code))
253260exprs = []
254261for (i, ex) in enumerate (ci. code)
255- ex = rename_args(ex, fun_vars, lower_vars )
262+ ex = rename_args (ex, slot_vars, ssa_vars )
256263 if ! overdubbable (ctx, ex)
257264 push! (exprs, ex)
258265 continue
259266 end
260267 if timable (ctx, ex)
261268 push! (exprs, Expr (:call , :push! , :to , :start , ex. args[1 ]))
262269 # ex = Expr(ex.head, :overdub, :ctx, ex.args...)
263- #push!(exprs, :($(lower_vars [i]) = $(ex) )
270+ # push!(exprs, :($(ssa_vars [i]) = $(ex))
264271 push! (exprs, Expr (ex. head, :overdub , :ctx , ex. args... ))
265272 push! (exprs, Expr (:call , :push! , :to , :stop , ex. args[1 ]))
266273 else
267274 push! (exprs, ex)
268275 end
269276end
277+ Expr (:block , exprs... )
278+ ```
279+ The last trouble we are facing is that there are not assigning the lefthandside variables. This is certainly troublesome and needs to be fixed. We can either blindly assign all variables including those, which are never used or collect those, which will be used and assign only those. We will choose the latter one, as it is indeed "nicer". We first define bunch of variables that traverses expressions and assigns them
280+ ``` julia
281+ assigned_vars (ex) = []
282+ assigned_vars (ex:: Expr ) = assigned_vars (ex. args)
283+ assigned_vars (args:: AbstractArray ) = mapreduce (assigned_vars, vcat, args)
284+ assigned_vars (r:: Core.ReturnNode ) = assigned_vars (r. val)
285+ assigned_vars (a:: Core.SlotNumber ) = []
286+ assigned_vars (a:: Core.SSAValue ) = [a. id]
287+ ```
288+ and then add the assignement to our code where needed
289+ ``` julia
290+ using Dictionaries
291+ slot_vars = Dict (enumerate (ci. slotnames))
292+ # ssa_vars = Dict(i => gensym(:left) for i in 1:length(ci.code))
293+ ssa_vars = Dict (i => Symbol (:L ,i) for i in 1 : length (ci. code))
294+ used = assigned_vars (ci. code) |> distinct
295+ exprs = []
296+ for (i, ex) in enumerate (ci. code)
297+ ex = rename_args (ex, slot_vars, ssa_vars)
298+ if ! overdubbable (ctx, ex)
299+ ex = i ∈ used ? Expr (:(= ) , ssa_vars[i], ex) : ex
300+ push! (exprs, ex)
301+ continue
302+ end
303+ if timable (ctx, ex)
304+ push! (exprs, Expr (:call , :push! , :to , :start , ex. args[1 ]))
305+ ex = Expr (ex. head, :overdub , :ctx , ex. args... )
306+ ex = i ∈ used ? Expr (:(= ) , ssa_vars[i], ex) : ex
307+ push! (exprs, ex)
308+ push! (exprs, Expr (:call , :push! , :to , :stop , ex. args[1 ]))
309+ else
310+ push! (exprs, ex)
311+ end
312+ end
313+ Expr (:block , exprs... )
314+ ```
315+
316+
317+ ``` julia
318+ @generated function overdub (ctx:: Context , f:: F , args... ) where {F}
319+ @show (F, args... )
320+ ci = retrieve_code_info ((F, args... ))
321+ slot_vars = Dict (enumerate (ci. slotnames))
322+ # ssa_vars = Dict(i => gensym(:left) for i in 1:length(ci.code))
323+ ssa_vars = Dict (i => Symbol (:L ,i) for i in 1 : length (ci. code))
324+ used = assigned_vars (ci. code) |> distinct
325+ exprs = []
326+ for (i, ex) in enumerate (ci. code)
327+ ex = rename_args (ex, slot_vars, ssa_vars)
328+ if ! overdubbable (ex)
329+ ex = i ∈ used ? Expr (:(= ) , ssa_vars[i], ex) : ex
330+ push! (exprs, ex)
331+ continue
332+ end
333+ if timable (ex)
334+ push! (exprs, Expr (:call , :push! , :to , :start , ex. args[1 ]))
335+ ex = Expr (ex. head, :overdub , :ctx , ex. args... )
336+ ex = i ∈ used ? Expr (:(= ) , ssa_vars[i], ex) : ex
337+ push! (exprs, ex)
338+ push! (exprs, Expr (:call , :push! , :to , :stop , ex. args[1 ]))
339+ else
340+ push! (exprs, ex)
341+ end
342+ end
343+ Expr (:block , exprs... )
344+ end
345+ ```
346+
347+ ```
348+ macro meta (ex)
349+ isexpr (ex, :call ) || error (" @meta f(args...)" )
350+ f, args = ex. args[1 ], ex. args[2 : end ]
351+ :(meta (typesof ($ (esc .((f, args... ))... ))))
352+ end
353+ ```
354+
270355
271356``` julia
272357macro timeit (ex:: Expr )
0 commit comments