What event types a gen_statem callback discriminates on, and whether it has a catch-all.
A state function state(EventType, Content, Data) and the
handle_event(EventType, Content, State, Data) callback both receive
the event type first, in {x, 0}. The clause heads are what the
runtime's messages are matched against, so two questions about them are
worth answering from the bytecode:
- which event types does this callback have a clause for at all? A
{:timeout, ms, content}action arms an event of type:timeout; a module that arms one and has no clause with:timeoutfirst has a timer that fires into a crash. Postgrex's SimpleConnection wrote the handler ashandle_event(:info, :timeout, ...)and pinged nothing. - does it accept an
:infoevent with any content? A gen_statem instate_functionsmode is only as robust as its least defensive state, and a state without an:infocatch-all dies on the first stray message it sees while in that state.
Reading the dispatch
Clause selection compiles to tests whose failure branch is either the
next clause's label or the function's own func_info label (raise
FunctionClauseError). A catch-all for some register set is a path from
the dispatch to a body that passes the success branch only of tests on
those registers, and takes failure branches freely — a failed test on
the content is just "not this clause", and the clause we are looking
for is the one after it.
So: for the :info catch-all, start where a test has just established
{x, 0} == :info and allow success on {x, 0} only; for the total
catch-all, start at the entry and allow success on nothing. Guards fall
out correctly, since a guarded clause tests a register and its failure
goes to func_info.
Answers
analyse/1 returns the event types some clause head compares the first
argument to (tagged tuples as "{call}", "{timeout}"), whether some
clause accepts :info with any content, and whether some clause accepts
any event at all. Argus.Extractors.GenStatem emits them as
statem_event_clause, statem_info_catchall and statem_event_catchall.
Summary
Functions
Reads one callback's clause heads. The caller turns the answer into facts; this module only walks bytecode, over the function's graph. Without a graph nothing is a catch-all.
Types
Functions
@spec analyse(Argus.Cfg.Function.t() | nil, [tuple()]) :: t()
Reads one callback's clause heads. The caller turns the answer into facts; this module only walks bytecode, over the function's graph. Without a graph nothing is a catch-all.