Skip to content

Language and Analysis Capabilities

Bifrost supports the same broad analysis categories across its languages, but language syntax and resolution rules affect what can be proved. This page is a suitability map, not a promise that every possible program construct resolves. Capability and execution diagnostics remain authoritative for a particular query and workspace.

Structural means query_code can match language-neutral parsed shapes such as declarations, calls, assignments, imports, literals, and containment. Exact graph means an indexed declaration identity can be connected to source references, semantic users, and resolved calls without resolving a display name by text. Proven means the analyzer established the target from structured language facts. Unproven is an explicit best-effort graph candidate used when a dynamic language leaves identity incomplete; it is never silently upgraded to proven.

Named arguments refer to call-site syntax represented by the normalized kwargs role. Import-file edges are direct, project-local file relationships used by imports_of and importers_of; matching an import node structurally is a separate, broader capability. Hierarchy means indexed direct supertypes and subtypes, not compiler-complete effective-member lookup. Bounded receiver provenance means the receiver_targets, points_to, and member_targets query steps return explicit analysis outcomes and bounded candidates; it is separate from ordinary call/reference receiver resolution.

Direct value-flow baseline means the production semantic adapter has a source-backed helper-flow case that agrees across the direct solver, JSON CodeQuery, and RQL. It proves the shared adapter contract for that fixture, not complete precision for every language construct.

LanguageStructuralExact references and callsCall and receiver precisionNamed argumentsDirect import-file edgesIndexed hierarchy
PythonYesYesResolved functions, methods, and properties; dynamic candidates may be unprovenYesYesYes
JavaYesYesReceiver identity, overloads, constructors, fields, and typesNoYesYes
JavaScriptYesYesModule and method identity; this references are separated by result surfaceNoYesYes
TypeScriptYesYesJavaScript forms plus typed declaration and module identityNoYesYes
GoYesYesPackage-scoped functions, methods, fields, and typesNoYesYes, including indexed type relationships
CYes, through the cpp query labelYesFunctions, fields, and types; method receivers and class inheritance do not applyNoYes, through structured includesNot applicable
C++Yes, through the cpp query labelYesFunctions, members, fields, types, includes, and structured receiver resolutionNoYes, through structured includesYes
RustYesYesFunctions, impl members, fields, types, and explicit self surface handlingNoYesYes
PHPYesYesNamespaces, functions, methods, fields, types, static receivers, and $this ownershipYesNo; unsupported traversal returns a diagnosticYes
ScalaYesYesReceiver and overload resolution across methods, fields, types, and inheritanceYesYesYes
C#YesYesReceiver and overload resolution across methods, constructors, fields, and typesYesYesYes
RubyYesYesResolved methods, fields, and constants; dynamic candidates may be unprovenYesYes, for conservative static importsYes
KotlinYesYesFunctions, methods, real constructors, properties, and types resolved through inheritance, companion objects, extensions, and receiver chainsYesYesYes

receiver_targets, points_to, and member_targets share one adapter-neutral result contract. When an input site exposes structured receiver facts, the steps return bounded values, allocation or factory provenance where represented, and exact owner-scoped members where the analyzer can prove them. Open dispatch, dynamic behavior, metaprogramming, unsupported syntax, and source forms without receiver semantics remain explicit through ambiguous, unknown, or unsupported outcomes.

Receiver availability is not defined by a static language allowlist. The selected adapter, exact source shape, workspace evidence, budgets, and cancellation state determine the result. Treat each receiver_analysis row and its diagnostics as authoritative for that input.

The executable language tutorials prove structural vocabulary against fixtures. Reference Traversal exercises inbound and outbound graph pipelines across every graph-backed adapter, Import Traversal records direct-edge support and the PHP diagnostic boundary, and Receiver Traversal locks the shared outcome and provenance contract.

Every language in the matrix has the direct value-flow baseline described above; C and C++ share the C-family semantic adapter. Advanced field, receiver, exceptional-flow, dynamic-dispatch, and external-model precision still varies by adapter and source shape.

The public query vocabulary exposes procedure-local CFG inspection plus host-registered value-flow, typestate, and retained taint projections. .rqlp taint policies use the production compiler, set-oriented batch planner, solver, retained report, and human/JSON/SARIF projection. Typestate policies execute finite-state protocols over the bounded semantic graph. See Data Flow, Taint, and Typestate for the execution and registration boundaries.

Structural matching is syntax-precise: Bifrost matches normalized Tree-sitter nodes and roles rather than regex or substring approximations. It does not make a structural call match equivalent to a resolved callee identity. Use reference and call traversal when identity matters.

Graph results preserve a proof tier. Filter to proven when an answer must contain only analyzer-established identities. Include unproven when a dynamic-language best effort is useful, and describe those candidates as possible rather than exact. A proven edge is precise evidence for that returned edge; it is not by itself proof that all possible runtime edges were found.

A zero-result is conclusive only within the reported capability, workspace, filters, and budgets. Before claiming “no matches” or “all callers,” check truncated, capability and execution diagnostics, proof tiers, and provenance_truncated. Agent Result Safety gives the complete decision rule; the JSON reference sections on diagnostics and limits define the underlying contract.

Import traversal follows resolved direct edges between project files. It can identify candidate importer files, but an importer edge is not proof that a file calls or references a particular member. Compose an exact reference step when the symbol use itself must be proved.

Hierarchy traversal returns indexed direct type relationships. Repeating a bounded step can walk farther, but Bifrost does not currently compute a language’s complete effective-member surface with override selection, hiding, access control, or every compiler rule. Member and owner steps navigate exact indexed declaration ownership.

External package imports can be matched structurally, and source references to library code may be visible. External declarations appear as query targets only when their source is genuinely inside the indexed workspace and has a renderable declaration range. Bifrost does not synthesize external declarations from import names, installed package metadata, or runtime objects.

Bifrost does not currently claim:

  • SMT-backed or otherwise path-sensitive feasibility;
  • whole-program points-to or complete allocation-site analysis (the receiver-query implementations are bounded and demand-driven);
  • general alias sets or receiver provenance beyond the structured facts published by each bounded adapter;
  • an arbitrary unregistered data-flow query assembled from structural matches, or an unbounded public ICFG traversal;
  • compiler-complete external dependency indexing.

call_input can project the expression written at a resolved call site, and the selected adapter’s points_to step can analyze that exact expression under a bounded receiver budget. Neither operation by itself invokes the data-flow engine. Structural inside and has constraints prove syntax-tree containment, not runtime control or data flow. Use a registered value-flow plan, a taint policy, or a typestate protocol when the required claim is supported by those bounded analyses; choose another analysis engine when it depends on one of the remaining boundaries above.