1- mutable struct Box{T}
2- id:: Symbol
3- val:: T
4- end
5-
6- # # methods for Box
7- Box (x) = Box (gensym (), x)
8- Box {T} (x) where {T} = Box {T} (gensym (), x)
9- Base. show (io:: IO , box:: Box ) = print (io, " Box(" , box. id, " )" )
10-
111# # Instruction and TapedFunction
122
133abstract type AbstractInstruction end
@@ -41,7 +31,7 @@ mutable struct TapedFunction{F}
4131 ir:: Core.CodeInfo
4232 tape:: RawTape
4333 counter:: Int
44- bindings:: Dict{Symbol, Box{<: Any} }
34+ bindings:: Dict{Symbol, Any}
4535 retval:: Symbol
4636
4737 function TapedFunction (f:: F , args... ; cache= false ) where {F}
@@ -56,12 +46,10 @@ mutable struct TapedFunction{F}
5646 end
5747
5848 ir = CodeInfoTools. code_inferred (f, args_type... )
59- tf = new {F} () # leave some fields to be undef
60- tf. func, tf. arity, tf. ir = f, length (args), ir
61- tf. tape = RawTape ()
62- tf. counter = 1
49+ tape = RawTape ()
50+ bindings = translate! (tape, ir)
6351
64- translate! (tf, ir )
52+ tf = new {F} (f, length (args), ir, tape, 1 , bindings, :none )
6553 TRCache[cache_key] = tf # set cache
6654 return tf
6755 end
7563const TRCache = LRU {Tuple, TapedFunction} (maxsize= 10 )
7664
7765val (x) = x
78- val (x:: Box ) = x. val
79- val (x:: Box{GlobalRef} ) = val (x. val)
80- val (x:: Box{QuoteNode} ) = val (x. val)
8166val (x:: GlobalRef ) = getproperty (x. mod, x. name)
8267val (x:: QuoteNode ) = eval (x)
8368val (x:: TapedFunction ) = x. func
@@ -86,10 +71,10 @@ result(t::TapedFunction) = val(t.bindings[t.retval])
8671function (tf:: TapedFunction )(args... ; callback= nothing )
8772 # set args
8873 if tf. counter <= 1
89- haskey (tf. bindings, :_1 ) && (tf. bindings[ :_1 ] . val = tf. func)
74+ haskey (tf. bindings, :_1 ) && _update_var! (tf, :_1 , tf. func)
9075 for i in 1 : length (args)
9176 slot = Symbol (" _" , i + 1 )
92- haskey (tf. bindings, slot) && (tf. bindings[slot] . val = args[i])
77+ haskey (tf. bindings, slot) && _update_var! (tf, slot, args[i])
9378 end
9479 end
9580
@@ -148,15 +133,15 @@ end
148133
149134_lookup (tf:: TapedFunction , v) = v
150135_lookup (tf:: TapedFunction , v:: Symbol ) = tf. bindings[v]
136+ _update_var! (tf:: TapedFunction , v:: Symbol , c) = tf. bindings[v] = c
151137
152138function (instr:: Instruction{F} )(tf:: TapedFunction ) where F
153139 # catch run-time exceptions / errors.
154140 try
155141 func = val (_lookup (tf, instr. func))
156142 inputs = map (x -> val (_lookup (tf, x)), instr. input)
157143 output = func (inputs... )
158- output_box = _lookup (tf, instr. output)
159- output_box. val = output
144+ _update_var! (tf, instr. output, output)
160145 tf. counter += 1
161146 catch e
162147 println (" counter=" , tf. counter)
@@ -201,60 +186,60 @@ end
201186
202187# # Translation: CodeInfo -> Tape
203188
204- function var_boxer (var, boxes:: Dict{Symbol, Box{<:Any}} ) # for literal constants
205- box = Box (var)
206- boxes[box. id] = box
207- return box. id
189+ function bind_var! (var, bindings:: Dict{Symbol, Any} ) # for literal constants
190+ id = gensym ()
191+ bindings[id] = var
192+ return id
193+ end
194+ bind_var! (var:: Core.SSAValue , bindings:: Dict{Symbol, Any} ) = bind_var! (Symbol (var. id), bindings)
195+ bind_var! (var:: Core.TypedSlot , bindings:: Dict{Symbol, Any} ) =
196+ bind_var! (Symbol (:_ , var. id), bindings)
197+ bind_var! (var:: Core.SlotNumber , bindings:: Dict{Symbol, Any} ) =
198+ bind_var! (Symbol (:_ , var. id), bindings)
199+ function bind_var! (var:: Symbol , bindings:: Dict{Symbol, Any} )
200+ get! (bindings, var, nothing )
201+ return var
208202end
209- var_boxer (var:: Core.SSAValue , boxes:: Dict{Symbol, Box{<:Any}} ) = var_boxer (Symbol (var. id), boxes)
210- var_boxer (var:: Core.TypedSlot , boxes:: Dict{Symbol, Box{<:Any}} ) =
211- var_boxer (Symbol (:_ , var. id), boxes)
212- var_boxer (var:: Core.SlotNumber , boxes:: Dict{Symbol, Box{<:Any}} ) =
213- var_boxer (Symbol (:_ , var. id), boxes)
214- var_boxer (var:: Symbol , boxes:: Dict{Symbol, Box{<:Any}} ) =
215- get! (boxes, var, Box {Any} (var, nothing )). id
216-
217- function translate! (tf:: TapedFunction , ir:: Core.CodeInfo )
218- tape = tf. tape
219- boxes = Dict {Symbol, Box{<:Any}} ()
203+
204+ function translate! (tape:: RawTape , ir:: Core.CodeInfo )
205+ bindings = Dict {Symbol, Any} ()
220206
221207 for (idx, line) in enumerate (ir. code)
222208 isa (line, Core. Const) && (line = line. val) # unbox Core.Const
223- ins = translate!! (Core. SSAValue (idx), line, boxes , ir)
209+ ins = translate!! (Core. SSAValue (idx), line, bindings , ir)
224210 push! (tape, ins)
225211 end
226-
227- tf. bindings = boxes
212+ return bindings
228213end
229214
230215const IRVar = Union{Core. SSAValue, Core. SlotNumber}
231216
232217function translate!! (var:: IRVar , line:: Core.NewvarNode ,
233- boxes :: Dict{Symbol, Box{<: Any} } , @nospecialize (ir))
218+ bindings :: Dict{Symbol, Any} , @nospecialize (ir))
234219 # use a noop to ensure the 1-to-1 mapping from ir.code to instructions
235220 # on tape. see GotoInstruction.dest.
236221 return GotoInstruction (:_true , 0 )
237222end
238223
239224function translate!! (var:: IRVar , line:: GlobalRef ,
240- boxes :: Dict{Symbol, Box{<: Any} } , @nospecialize (ir))
241- return Instruction (() -> val (line), (), var_boxer (var, boxes ))
225+ bindings :: Dict{Symbol, Any} , @nospecialize (ir))
226+ return Instruction (() -> val (line), (), bind_var! (var, bindings ))
242227end
243228
244229function translate!! (var:: IRVar , line:: Core.SlotNumber ,
245- boxes :: Dict{Symbol, Box{<: Any} } , @nospecialize (ir))
246- return Instruction (identity, (var_boxer (line, boxes ),), var_boxer (var, boxes ))
230+ bindings :: Dict{Symbol, Any} , @nospecialize (ir))
231+ return Instruction (identity, (bind_var! (line, bindings ),), bind_var! (var, bindings ))
247232end
248233
249234function translate!! (var:: IRVar , line:: Core.TypedSlot ,
250- boxes :: Dict{Symbol, Box{<: Any} } , @nospecialize (ir))
251- input_box = var_boxer (Core. SlotNumber (line. id), boxes )
252- return Instruction (identity, (input_box,), var_boxer (var, boxes ))
235+ bindings :: Dict{Symbol, Any} , @nospecialize (ir))
236+ input_box = bind_var! (Core. SlotNumber (line. id), bindings )
237+ return Instruction (identity, (input_box,), bind_var! (var, bindings ))
253238end
254239
255240function translate!! (var:: IRVar , line:: Core.GotoIfNot ,
256- boxes :: Dict{Symbol, Box{<: Any} } , @nospecialize (ir))
257- _cond = var_boxer (line. cond, boxes )
241+ bindings :: Dict{Symbol, Any} , @nospecialize (ir))
242+ _cond = bind_var! (line. cond, bindings )
258243 cond = if isa (_cond, Bool)
259244 _cond ? :_true : :_false
260245 else
@@ -264,53 +249,53 @@ function translate!!(var::IRVar, line::Core.GotoIfNot,
264249end
265250
266251function translate!! (var:: IRVar , line:: Core.GotoNode ,
267- boxes :: Dict{Symbol, Box{<: Any} } , @nospecialize (ir))
252+ bindings :: Dict{Symbol, Any} , @nospecialize (ir))
268253 return GotoInstruction (:_false , line. label)
269254end
270255
271256function translate!! (var:: IRVar , line:: Core.ReturnNode ,
272- boxes :: Dict{Symbol, Box{<: Any} } , @nospecialize (ir))
273- return ReturnInstruction (var_boxer (line. val, boxes ))
257+ bindings :: Dict{Symbol, Any} , @nospecialize (ir))
258+ return ReturnInstruction (bind_var! (line. val, bindings ))
274259end
275260
276261function translate!! (var:: IRVar , line:: Expr ,
277- boxes :: Dict{Symbol, Box{<: Any} } , ir:: Core.CodeInfo )
262+ bindings :: Dict{Symbol, Any} , ir:: Core.CodeInfo )
278263 head = line. head
279- _box_fn = (x) -> var_boxer (x, boxes )
264+ _bind_fn = (x) -> bind_var! (x, bindings )
280265 if head === :new
281- args = map (_box_fn , line. args)
282- return Instruction (__new__, args |> Tuple, var_boxer (var, boxes ))
266+ args = map (_bind_fn , line. args)
267+ return Instruction (__new__, args |> Tuple, bind_var! (var, bindings ))
283268 elseif head === :call
284- args = map (_box_fn , line. args)
269+ args = map (_bind_fn , line. args)
285270 # args[1] is the function
286271 func = line. args[1 ]
287272 if Meta. isexpr (func, :static_parameter ) # func is a type parameter
288273 func = ir. parent. sparam_vals[func. args[1 ]]
289274 else # isa(func, GlobalRef) or a var?
290275 func = args[1 ] # a var(box)
291276 end
292- return Instruction (func, args[2 : end ] |> Tuple, var_boxer (var, boxes ))
277+ return Instruction (func, args[2 : end ] |> Tuple, bind_var! (var, bindings ))
293278 elseif head === :(= )
294279 # line.args[1] (the left hand side) is a SlotNumber, and it should be the output
295280 lhs = line. args[1 ]
296281 rhs = line. args[2 ] # the right hand side, maybe a Expr, or a var, or ...
297282 if Meta. isexpr (rhs, (:new , :call ))
298- return translate!! (lhs, rhs, boxes , ir)
283+ return translate!! (lhs, rhs, bindings , ir)
299284 else # rhs is a single value
300- return Instruction (identity, (_box_fn (rhs),), _box_fn (lhs))
285+ return Instruction (identity, (_bind_fn (rhs),), _bind_fn (lhs))
301286 end
302287 else
303288 @error " Unknown Expression: " typeof (var) var typeof (line) line
304289 throw (ErrorException (" Unknown Expression" ))
305290 end
306291end
307292
308- function translate!! (var, line, boxes , ir)
293+ function translate!! (var, line, bindings , ir)
309294 @error " Unknown IR code: " typeof (var) var typeof (line) line
310295 throw (ErrorException (" Unknown IR code" ))
311296end
312297
313- # # copy Box , TapedFunction
298+ # # copy Bindings , TapedFunction
314299
315300"""
316301 tape_copy(x)
@@ -329,12 +314,10 @@ tape_copy(x::Core.Box) = Core.Box(tape_copy(x.contents))
329314# tape_copy(x::Array) = deepcopy(x)
330315# tape_copy(x::Dict) = deepcopy(x)
331316
332- Base. copy (box:: Box{T} ) where T = Box {T} (box. id, tape_copy (box. val))
333-
334- function copy_bindings (old:: Dict{Symbol, Box{<:Any}} )
335- newb = Dict {Symbol, Box{<:Any}} ()
317+ function copy_bindings (old:: Dict{Symbol, Any} )
318+ newb = Dict {Symbol, Any} ()
336319 for (k, v) in old
337- newb[k] = copy (v)
320+ newb[k] = tape_copy (v)
338321 end
339322 return newb
340323end
0 commit comments