@@ -6,7 +6,7 @@ using JuliaInterpreter
6
6
using JuliaInterpreter: @lookup , moduleof, pc_expr, step_expr!, is_global_ref, whichtt,
7
7
next_until!, finish_and_return!, nstatements, codelocation
8
8
9
- export signature, methoddef!, methoddefs!
9
+ export signature, methoddef!, methoddefs!, bodymethod
10
10
11
11
"""
12
12
iscallto(stmt, name)
@@ -441,6 +441,68 @@ function _methoddefs!(@nospecialize(recurse), signatures, frame::Frame, pc; defi
441
441
return pc
442
442
end
443
443
444
+ """
445
+ mbody = bodymethod(m::Method)
446
+
447
+ Return the "body method" for a method `m`. `mbody` contains the code of the function body
448
+ when `m` was defined.
449
+ """
450
+ function bodymethod (mkw:: Method )
451
+ function is_self_call (stmt, slotnames, argno= 1 )
452
+ if isa (stmt, Expr)
453
+ if stmt. head == :call
454
+ a = stmt. args[argno]
455
+ if isa (a, Core. SlotNumber)
456
+ if slotnames[a. id] == Symbol (" #self#" )
457
+ return true
458
+ end
459
+ end
460
+ end
461
+ end
462
+ return false
463
+ end
464
+ m = mkw
465
+ local src
466
+ while true
467
+ framecode = JuliaInterpreter. get_framecode (m)
468
+ fakeargs = Any[nothing for i = 1 : length (framecode. scope. nargs)]
469
+ frame = JuliaInterpreter. prepare_frame (framecode, fakeargs, isa (m. sig, UnionAll) ? sparam_ub (m) : Core. svec ())
470
+ src = framecode. src
471
+ (length (src. code) > 1 && is_self_call (src. code[end - 1 ], src. slotnames)) || break
472
+ # Build the optional arg, so we can get its type
473
+ pc = frame. pc
474
+ while pc < length (src. code) - 1
475
+ pc = step_expr! (frame)
476
+ end
477
+ val = pc > 1 ? frame. framedata. ssavalues[pc- 1 ] : src. code[1 ]. args[end ]
478
+ sig = Tuple{Base. unwrap_unionall (m. sig). parameters... , typeof (val)}
479
+ m = whichtt (sig)
480
+ end
481
+ length (src. code) > 1 || return m
482
+ stmt = src. code[end - 1 ]
483
+ if isexpr (stmt, :call ) && (f = stmt. args[1 ]; isa (f, QuoteNode))
484
+ # Check that it has a #self# call
485
+ hasself = any (i-> is_self_call (stmt, src. slotnames, i), 1 : length (stmt. args))
486
+ hasself || return m
487
+ f = f. value
488
+ mths = methods (f)
489
+ if length (mths) == 1
490
+ return first (mths)
491
+ end
492
+ end
493
+ return m
494
+ end
495
+
496
+ function sparam_ub (meth:: Method )
497
+ typs = []
498
+ sig = meth. sig
499
+ while sig isa UnionAll
500
+ push! (typs, Symbol (sig. var. ub))
501
+ sig = sig. body
502
+ end
503
+ return Core. svec (typs... )
504
+ end
505
+
444
506
# precompilation
445
507
446
508
if ccall (:jl_generating_output , Cint, ()) == 1
0 commit comments