Orchestrates parallel fact extraction from BEAM modules.
The pipeline runs in stages:
modules → Disassemble → Emit (Layer 1) + Extractors (Layer 2) → write .factsArgus.Pipeline.Disassembleresolves module names to.beampaths and reads BEAM files into normalized module data.Argus.Pipeline.Emitproduces base bytecode facts from each module.- User-supplied extractors implementing
Argus.Extractorproduce domain-specific Layer 2 facts. run/3streams each module's facts to.factsfiles (one per relation, tab-separated) as extraction completes, so the program's fact set never exists in memory at once.extract/2returns the merged facts in memory.
Summary
Functions
Extracts facts from the given modules and returns them as a map without writing to disk.
Extracts facts from the given modules and writes .facts files to output_dir.
Writes extracted facts to .facts files in output_dir (one
tab-separated file per relation).
Types
@type extract_opts() :: [ concurrency: pos_integer(), extractors: [module()], timeout: timeout(), trace_imprecision: boolean(), format: :raw | :typed | :interned, symbols: Argus.Symbols.t() ]
@type run_opts() :: [ concurrency: pos_integer(), extractors: [module()], timeout: timeout(), trace_imprecision: boolean(), relations: :all | [atom()] ]
Functions
@spec extract(modules :: [Argus.Pipeline.Disassemble.module_input()], extract_opts()) :: {:ok, Argus.Pipeline.Emit.facts() | Argus.Facts.t()} | {:error, term()}
Extracts facts from the given modules and returns them as a map without writing to disk.
With format: :typed, rows are decoded against the schema via
Argus.Facts.decode/1 (field-name-keyed maps, integers, Argus.InstrId
structs) instead of the raw string lists that .facts files use. With
format: :interned, rows are tuples of Argus.Symbols ids interned in
the worker that extracted them against the symbols: table the caller
owns (Argus.Facts.interned/0); the caller keeps the table, and reads
the rows back through Argus.Facts.materialize/2 or decode/2.
@spec run( modules :: [Argus.Pipeline.Disassemble.module_input()], output_dir :: Path.t(), run_opts() ) :: {:ok, Path.t()} | {:error, term()}
Extracts facts from the given modules and writes .facts files to output_dir.
Modules can be atoms (resolved via :code.which/1), string paths to
.beam files, or raw beam data binaries. Returns {:ok, output_dir}
or {:error, reason}.
Every schema relation gets a file (Souffle fails on a missing .input
file), but relations: limits which ones receive rows: the rest stay
empty. Argus.Analysis.extract_facts/3 uses it to leave out the
relations that exist only for the in-process control-flow and dataflow
passes (Argus.Schema.in_process_only/0), which no Souffle program
reads and which are most of the fact volume.
@spec write_facts(Argus.Pipeline.Emit.facts(), Path.t()) :: :ok | {:error, term()}
Writes extracted facts to .facts files in output_dir (one
tab-separated file per relation).
Empty files are materialized for every schema relation so Souffle never
fails on a missing .input file. Callers that merge per-module fact
maps themselves (rather than going through run/3) can use this to
produce a Souffle-ready facts directory from in-memory facts.
Expects raw-format facts (string rows, as returned by extract/2 with
the default format: :raw). The directory must already exist.