Extracts function definitions and call edges from a single file using
the same in-process parsers as the chunkers (:epp for Erlang,
Code.string_to_quoted for Elixir) — not a second tree-sitter pass,
which is what the original call_extractor.py uses. This is Phase 0's
core untested hypothesis for the call graph: that a compiler-accurate
parse can drive it too, and — for Erlang specifically — one that sees
through macro expansion in a way tree-sitter structurally cannot, since
:epp fully expands macros as part of parsing while tree-sitter only
ever sees the raw ?MACRO(...) token.
Elixir macros are a different story: Code.string_to_quoted/2 parses
syntax only, it does not expand macros (that happens later, during
compilation) — so a call hidden behind an Elixir macro is just as
invisible here as it is to tree-sitter. The macro-transparency
advantage is Erlang-specific.
Returns {defs, edges}:
defs:[%{name:, module:, file_path:, start_line:, end_line:}]edges:[%{caller_module:, caller_name:, callee_module:, callee_name:, file_path:, line:}]
callee_module: "?" marks a call whose target module couldn't be
statically resolved (e.g. Mod:Fun() where Mod is a variable, or
Mod.fun() where Mod isn't a literal alias) — matching
call_extractor.py's convention so results stay comparable.