juliaのソースファイルを分析し、関数呼出しの木を作ろうとしたことがあったわけです。https://github.com/sazare/parsetools/blob/master/src/parsetool.jl
そんな中、ソースファイルでなく、メモリ上でincludeされた関数の定義はとってこれないのか、ずっと悩んでいたが、すこしわかったので書いておく。
完全にはわかっていない。(大変だということはわかった)
まず、このリポジトリにある関数parsefileが定義してあるとする。
julia> mm=methods(parsefile)
# 1 method for generic function "parsefile":
[1] parsefile(fname) in Main at
〜/parsetool.jl:58
julia> typeof(mm)
Base.MethodList
help?> Base.MethodList
No documentation found.
Summary
≡≡≡≡≡≡≡≡≡
mutable struct Base.MethodList <: Any
Fields
≡≡≡≡≡≡≡≡
ms :: Array{Method,1}
mt :: Core.MethodTable
このmsとmtをたどっていくと、mtのほうに定義が残っていた。
julia> mm.mt
# 1 method for generic function "parsefile":
[1] parsefile(fname) in Main at
〜/parsetool.jl:58
julia> typeof(mm.mt)
Core.MethodTable
help?> Core.MethodTable
No documentation found.
Summary
≡≡≡≡≡≡≡≡≡
mutable struct Core.MethodTable <: Any
Fields
≡≡≡≡≡≡≡≡
name :: Symbol
defs :: Any
cache :: Any
max_args :: Int64
kwsorter :: Any
module :: Module
backedges :: Array{Any,1}
:: Int64
:: Int64
offs :: UInt8
:: UInt8
この、defsには
mm.mt.defs
Core.TypeMapEntry(nothing, Tuple{typeof(parsefile),Any}, nothing, svec(), 0x000000000000688e, 0xffffffffffffffff, parsefile(fname) in Main at
〜/parsetool.jl:58, false, true, false)
となっていて、
julia> dump(mm.mt.defs)
Core.TypeMapEntry
next: Nothing nothing
sig: Tuple{typeof(parsefile),Any} <: Any
simplesig: Nothing nothing
guardsigs: empty SimpleVector
min_world: UInt64 0x000000000000688e
max_world: UInt64 0xffffffffffffffff
func: Method
name: Symbol parsefile
module: Module Main
file: Symbol 〜/parsetool.jl
line: Int32 58
primary_world: UInt64 0x000000000000688e
deleted_world: UInt64 0xffffffffffffffff
sig: Tuple{typeof(parsefile),Any} <: Any
ambig: Nothing nothing
resorted: Nothing nothing
specializations: Core.TypeMapEntry
以下略
ここから、関数定義を読み取るのは無理かなあ・・・
ちなみにmsのほうは
julia> typeof(mm.ms[1])
Method
こっちは
julia> mm.ms[1].file
Symbol("/Users/shin/Projects/github/parsetools/src/parsetool.jl")
julia> mm.ms[1].line
58
となっていて関数単位の行番号がわかるので、定義をファイルからとってくるのならこちらだろう・・・
julia実行中に関数のソースはいらないから、メモリ上にはないのだろう。
自分でソース読みにいくしかないのなら、ファイルパスから、parsefile()で呼び出す方法しかないかな。
その場合は、今のようなArrayでなくDictにして関数名からcalling treeを取り出せるようにするのか。
その場合、multiple dispatchのような構造がまた別に存在するわけで、すこし整理しないと・・・。