@@ -13,15 +13,17 @@ function assign_this!(frame, value)
1313 frame. framedata. ssavalues[frame. pc] = value
1414end
1515
16+ # TODO Define abstract type MethodInfo end
17+
1618# This defines the API needed to store signatures using methods_by_execution!
1719# This default version is simple and only used for testing purposes.
1820# The "real" one is CodeTrackingMethodInfo in Revise.jl.
1921const MethodInfo = IdDict{Type,LineNumberNode}
20- add_signature!(methodinfo:: MethodInfo , @nospecialize(sig), ln) = push!(methodinfo, sig=> ln)
21- push_expr!(methodinfo:: MethodInfo , mod:: Module , ex:: Expr ) = methodinfo
22- pop_expr!(methodinfo:: MethodInfo ) = methodinfo
23- add_dependencies!(methodinfo:: MethodInfo , be:: CodeEdges , src, isrequired) = methodinfo
24- add_includes!(methodinfo:: MethodInfo , mod:: Module , filename) = methodinfo
22+ add_signature!(methodinfo, @nospecialize(sig), ln) = push!(methodinfo, sig=> ln)
23+ push_expr!(methodinfo, mod:: Module , ex:: Expr ) = methodinfo
24+ pop_expr!(methodinfo) = methodinfo
25+ add_dependencies!(methodinfo, be:: CodeEdges , src, isrequired) = methodinfo
26+ add_includes!(methodinfo, mod:: Module , filename) = methodinfo
2527
2628function is_some_include(@nospecialize(f))
2729 @assert ! isa(f, Core. SSAValue) && ! isa(f, JuliaInterpreter. SSAValue)
@@ -187,11 +189,11 @@ function minimal_evaluation!(@nospecialize(predicate), methodinfo, mod::Module,
187189 add_dependencies!(methodinfo, edges, src, isrequired)
188190 return isrequired, evalassign
189191end
190- @noinline minimal_evaluation!(@nospecialize(predicate), methodinfo, frame:: JuliaInterpreter. Frame , mode:: Symbol ) =
192+ @noinline minimal_evaluation!(@nospecialize(predicate), methodinfo, frame:: Frame , mode:: Symbol ) =
191193 minimal_evaluation!(predicate, methodinfo, moduleof(frame), frame. framecode. src, mode)
192194
193- function minimal_evaluation!(methodinfo, frame:: JuliaInterpreter. Frame , mode:: Symbol )
194- minimal_evaluation!(methodinfo, frame, mode) do @nospecialize(stmt), code
195+ function minimal_evaluation!(methodinfo, frame:: Frame , mode:: Symbol )
196+ minimal_evaluation!(methodinfo, frame, mode) do @nospecialize(stmt), code:: Vector{Any}
195197 ismeth, haseval, isinclude, isnamespace, istoplevel = categorize_stmt(stmt, code)
196198 isreq = ismeth | isinclude | istoplevel
197199 return mode === :sigs ? (isreq, haseval) : (isreq | isnamespace, haseval)
@@ -206,14 +208,14 @@ function methods_by_execution(mod::Module, ex::Expr; kwargs...)
206208end
207209
208210"""
209- methods_by_execution!(recurse =JuliaInterpreter.Compiled(), methodinfo, docexprs, mod::Module, ex::Expr;
211+ methods_by_execution!([interp::Interpreter =JuliaInterpreter.Compiled(),] methodinfo, docexprs::DocExprs , mod::Module, ex::Expr;
210212 mode=:eval, disablebp=true, skip_include=mode!==:eval, always_rethrow=false)
211213
212214Evaluate or analyze `ex` in the context of `mod`.
213215Depending on the setting of `mode` (see the Extended help), it supports full evaluation or just the minimal
214216evaluation needed to extract method signatures.
215- `recurse ` controls JuliaInterpreter's evaluation of any non-intercepted statement;
216- likely choices are `JuliaInterpreter.Compiled()` or `JuliaInterpreter.finish_and_return! `.
217+ `interp ` controls JuliaInterpreter's evaluation of any non-intercepted statement;
218+ likely choices are `JuliaInterpreter.Compiled()` or `JuliaInterpreter.RecursiveInterpreter() `.
217219`methodinfo` is a cache for storing information about any method definitions (see [`CodeTrackingMethodInfo`](@ref)).
218220`docexprs` is a cache for storing documentation expressions; obtain an empty one with `Revise.DocExprs()`.
219221
@@ -249,7 +251,7 @@ The other keyword arguments are more straightforward:
249251 If false, the error is logged with `@error`. `InterruptException`s are always rethrown.
250252 This is primarily useful for debugging.
251253"""
252- function methods_by_execution!(@nospecialize(recurse) , methodinfo, docexprs, mod:: Module , ex:: Expr ;
254+ function methods_by_execution!(interp :: Interpreter , methodinfo, docexprs:: DocExprs , mod:: Module , ex:: Expr ;
253255 mode:: Symbol = :eval, disablebp:: Bool = true , always_rethrow:: Bool = false , kwargs... )
254256 mode ∈ (:sigs, :eval, :evalmeth, :evalassign) || error(" unsupported mode " , mode)
255257 lwr = Meta. lower(mod, ex)
@@ -261,8 +263,8 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, mod
261263 mode === :sigs && return nothing , nothing
262264 return Core. eval(mod, lwr), nothing
263265 end
264- frame = JuliaInterpreter . Frame(mod, lwr. args[1 ]:: CodeInfo )
265- mode === :eval || LoweredCodeUtils. rename_framemethods!(recurse , frame)
266+ frame = Frame(mod, lwr. args[1 ]:: CodeInfo )
267+ mode === :eval || LoweredCodeUtils. rename_framemethods!(interp , frame)
266268 # Determine whether we need interpreted mode
267269 isrequired, evalassign = minimal_evaluation!(methodinfo, frame, mode)
268270 # LoweredCodeUtils.print_with_code(stdout, frame.framecode.src, isrequired)
@@ -293,7 +295,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, mod
293295 foreach(disable, active_bp_refs)
294296 end
295297 ret = try
296- methods_by_execution!(recurse , methodinfo, docexprs, frame, isrequired; mode = mode, kwargs... )
298+ methods_by_execution!(interp , methodinfo, docexprs, frame, isrequired; mode, kwargs... )
297299 catch err
298300 (always_rethrow || isa(err, InterruptException)) && (disablebp && foreach(enable, active_bp_refs); rethrow(err))
299301 loc = location_string(whereis(frame))
@@ -311,10 +313,11 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, mod
311313 end
312314 return ret, lwr
313315end
314- methods_by_execution!(methodinfo, docexprs, mod:: Module , ex:: Expr ; kwargs... ) =
315- methods_by_execution!(JuliaInterpreter . Compiled(), methodinfo, docexprs, mod, ex; kwargs... )
316+ methods_by_execution!(methodinfo, docexprs:: DocExprs , mod:: Module , ex:: Expr ; kwargs... ) =
317+ methods_by_execution!(Compiled(), methodinfo, docexprs, mod, ex; kwargs... )
316318
317- function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, frame:: Frame , isrequired:: AbstractVector{Bool} ; mode:: Symbol = :eval, skip_include:: Bool = true )
319+ function methods_by_execution!(interp:: Interpreter , methodinfo, docexprs:: DocExprs , frame:: Frame , isrequired:: AbstractVector{Bool} ;
320+ mode:: Symbol = :eval, skip_include:: Bool = true )
318321 isok(lnn:: LineTypes ) = ! iszero(lnn. line) || lnn. file != = :none # might fail either one, but accept anything
319322
320323 mod = moduleof(frame)
@@ -336,7 +339,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra
336339 local value
337340 for ex in stmt. args
338341 ex isa Expr || continue
339- value = methods_by_execution!(recurse , methodinfo, docexprs, mod, ex; mode= mode , disablebp= false , skip_include = skip_include)
342+ value = methods_by_execution!(interp , methodinfo, docexprs, mod, ex; mode, disablebp= false , skip_include)
340343 end
341344 isassign(frame, pc) && assign_this!(frame, value)
342345 pc = next_or_nothing!(frame)
@@ -348,10 +351,10 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra
348351 # # way to find them within the already-defined module.
349352 # # They may be needed to define later signatures.
350353 # # Note that named inner methods don't require special treatment.
351- # pc = step_expr!(recurse , frame, stmt, true)
354+ # pc = step_expr!(interp , frame, stmt, true)
352355 elseif head === :method
353356 empty!(signatures)
354- ret = methoddef!(recurse , signatures, frame, stmt, pc; define= mode!= = :sigs)
357+ ret = methoddef!(interp , signatures, frame, stmt, pc; define= mode!= = :sigs)
355358 if ret === nothing
356359 # This was just `function foo end` or similar.
357360 # However, it might have been followed by a thunk that defined a
@@ -367,22 +370,22 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra
367370 end
368371 end
369372 @assert length(stmt. args) == 1
370- pc = mode != = :sigs ? step_expr!(recurse , frame, stmt, true ) :
373+ pc = mode != = :sigs ? step_expr!(interp , frame, stmt, true ) :
371374 next_or_nothing!(frame)
372375 else
373376 pc, pc3 = ret
374377 # Get the line number from the body
375378 stmt3 = pc_expr(frame, pc3):: Expr
376379 lnn = nothing
377- sigcode = lookup(frame, stmt3. args[2 ]):: Core.SimpleVector
380+ sigcode = lookup(interp, frame, stmt3. args[2 ]):: Core.SimpleVector
378381 lnn = sigcode[end ]
379382 if ! isa(lnn, LineNumberNode)
380383 lnn = nothing
381384 end
382385 if lnn === nothing
383386 bodycode = stmt3. args[end ]
384387 if ! isa(bodycode, CodeInfo)
385- bodycode = lookup(frame, bodycode)
388+ bodycode = lookup(interp, frame, bodycode)
386389 end
387390 if isa(bodycode, CodeInfo)
388391 lnn = linetable(bodycode, 1 )
@@ -456,13 +459,13 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra
456459 # avoid redefining types unless we have to
457460 pc = next_or_nothing!(frame)
458461 else
459- pc = step_expr!(recurse , frame, stmt, true )
462+ pc = step_expr!(interp , frame, stmt, true )
460463 end
461464 elseif head === :call
462- f = lookup(frame, stmt. args[1 ])
465+ f = lookup(interp, frame, stmt. args[1 ])
463466 if isdefined(Core, :_defaultctors) && f === Core. _defaultctors && length(stmt. args) == 3
464- T = lookup(frame, stmt. args[2 ])
465- lnn = lookup(frame, stmt. args[3 ])
467+ T = lookup(interp, frame, stmt. args[2 ])
468+ lnn = lookup(interp, frame, stmt. args[3 ])
466469 if T isa Type && lnn isa LineNumberNode
467470 empty!(signatures)
468471 uT = Base. unwrap_unionall(T):: DataType
@@ -482,12 +485,12 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra
482485 if mode=== :sigs
483486 pc = next_or_nothing!(frame)
484487 else # also execute this call
485- pc = step_expr!(recurse , frame, stmt, true )
488+ pc = step_expr!(interp , frame, stmt, true )
486489 end
487490 elseif f === Core. eval
488491 # an @eval or eval block: this may contain method definitions, so intercept it.
489- evalmod = lookup(frame, stmt. args[2 ]):: Module
490- evalex = lookup(frame, stmt. args[3 ])
492+ evalmod = lookup(interp, frame, stmt. args[2 ]):: Module
493+ evalex = lookup(interp, frame, stmt. args[3 ])
491494 value = nothing
492495 for (newmod, newex) in ExprSplitter(evalmod, evalex)
493496 if is_doc_expr(newex)
@@ -496,7 +499,7 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra
496499 end
497500 newex = unwrap(newex)
498501 push_expr!(methodinfo, newmod, newex)
499- value = methods_by_execution!(recurse , methodinfo, docexprs, newmod, newex; mode= mode, skip_include = skip_include, disablebp= false )
502+ value = methods_by_execution!(interp , methodinfo, docexprs, newmod, newex; mode, skip_include, disablebp= false )
500503 pop_expr!(methodinfo)
501504 end
502505 assign_this!(frame, value)
@@ -505,29 +508,29 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra
505508 # include calls need to be managed carefully from several standpoints, including
506509 # path management and parsing new expressions
507510 if length(stmt. args) == 2
508- add_includes!(methodinfo, mod, lookup(frame, stmt. args[2 ]))
511+ add_includes!(methodinfo, mod, lookup(interp, frame, stmt. args[2 ]))
509512 elseif length(stmt. args) == 3
510- add_includes!(methodinfo, lookup(frame, stmt. args[2 ]), lookup(frame, stmt. args[3 ]))
513+ add_includes!(methodinfo, lookup(interp, frame, stmt. args[2 ]), lookup(interp, frame, stmt. args[3 ]))
511514 else
512515 error(" Bad call to Core.include" )
513516 end
514517 assign_this!(frame, nothing ) # FIXME : the file might return something different from `nothing`
515518 pc = next_or_nothing!(frame)
516519 elseif skip_include && f === Base. include
517520 if length(stmt. args) == 2
518- add_includes!(methodinfo, mod, lookup(frame, stmt. args[2 ]))
521+ add_includes!(methodinfo, mod, lookup(interp, frame, stmt. args[2 ]))
519522 else # either include(module, path) or include(mapexpr, path)
520- mod_or_mapexpr = lookup(frame, stmt. args[2 ])
523+ mod_or_mapexpr = lookup(interp, frame, stmt. args[2 ])
521524 if isa(mod_or_mapexpr, Module)
522- add_includes!(methodinfo, mod_or_mapexpr, lookup(frame, stmt. args[3 ]))
525+ add_includes!(methodinfo, mod_or_mapexpr, lookup(interp, frame, stmt. args[3 ]))
523526 else
524527 error(" include(mapexpr, path) is not supported" ) # TODO (issue #634)
525528 end
526529 end
527530 assign_this!(frame, nothing ) # FIXME : the file might return something different from `nothing`
528531 pc = next_or_nothing!(frame)
529532 elseif f === Base. Docs. doc! # && mode !== :eval
530- fargs = JuliaInterpreter. collect_args(recurse , frame, stmt)
533+ fargs = JuliaInterpreter. collect_args(interp , frame, stmt)
531534 popfirst!(fargs)
532535 length(fargs) == 3 && push!(fargs, Union{}) # add the default sig
533536 dmod:: Module , b:: Base.Docs.Binding , str:: Base.Docs.DocStr , sig = fargs
@@ -559,16 +562,16 @@ function methods_by_execution!(@nospecialize(recurse), methodinfo, docexprs, fra
559562 pc = next_or_nothing!(frame)
560563 else
561564 # A :call Expr we don't want to intercept
562- pc = step_expr!(recurse , frame, stmt, true )
565+ pc = step_expr!(interp , frame, stmt, true )
563566 end
564567 else
565568 # An Expr we don't want to intercept
566569 frame. pc = pc
567- pc = step_expr!(recurse , frame, stmt, true )
570+ pc = step_expr!(interp , frame, stmt, true )
568571 end
569572 else
570573 # A statement we don't want to intercept
571- pc = step_expr!(recurse , frame, stmt, true )
574+ pc = step_expr!(interp , frame, stmt, true )
572575 end
573576 pc === nothing && break
574577 end
0 commit comments