Metastatic.Semantic.Patterns (Metastatic v0.10.4)

View Source

Language-aware pattern registry for semantic enrichment.

This module provides a pattern matching engine that maps function names to semantic operation kinds. Patterns are organized by language and domain, enabling precise detection of framework-specific operations.

Pattern Types

Three types of patterns are supported:

  1. Exact match - Full function name: "Repo.get"
  2. Prefix match - Module prefix with wildcard: "Repo.*"
  3. Suffix match - Method name at end: "*.findByPk"
  4. Regex match - Complex patterns: ~r/\.objects\.get/

Usage

alias Metastatic.Semantic.Patterns

# Match a function name against patterns for a language
case Patterns.match("Repo.get", :elixir, args) do
  {:ok, op_kind} -> # Found a match
  :no_match -> # No pattern matched
end

Pattern Registration

Patterns are defined in domain-specific modules (e.g., Domains.Database) and registered here. Each pattern specifies:

  • Language(s) it applies to
  • Function name pattern
  • Operation kind metadata
  • Optional: target extraction strategy

Summary

Types

Language identifier

Pattern specification

Functions

Clears all registered patterns (useful for testing).

Gets all registered patterns for a domain and language.

Matches a function name against registered patterns for a language.

Registers patterns for a domain and language.

Types

language()

@type language() ::
  :elixir | :python | :ruby | :javascript | :erlang | :haskell | atom()

Language identifier

pattern_spec()

@type pattern_spec() :: %{
  pattern: String.t() | Regex.t(),
  operation: Metastatic.Semantic.OpKind.operation(),
  framework: Metastatic.Semantic.OpKind.framework() | nil,
  extract_target: :first_arg | :receiver | :none | nil
}

Pattern specification

Functions

clear_all()

@spec clear_all() :: :ok

Clears all registered patterns (useful for testing).

get_patterns(domain, language)

@spec get_patterns(Metastatic.Semantic.OpKind.domain(), language()) :: [
  {String.t() | Regex.t(), pattern_spec()}
]

Gets all registered patterns for a domain and language.

match(func_name, language, args, receiver \\ nil)

@spec match(String.t(), language(), list(), term()) ::
  {:ok, Metastatic.Semantic.OpKind.t()} | :no_match

Matches a function name against registered patterns for a language.

Returns {:ok, op_kind} if a pattern matches, or :no_match otherwise.

Parameters

  • func_name - The function name to match (e.g., "Repo.get", "session.query")
  • language - The source language (e.g., :elixir, :python)
  • args - AST arguments for target extraction
  • receiver - Optional receiver AST for method calls

Examples

iex> Patterns.match("Repo.get", :elixir, [{:variable, [], "User"}, {:literal, [subtype: :integer], 1}])
{:ok, [domain: :db, operation: :retrieve, target: "User", async: false, framework: :ecto]}

iex> Patterns.match("unknown_function", :elixir, [])
:no_match

register(domain, language, patterns)

@spec register(Metastatic.Semantic.OpKind.domain(), language(), [
  {String.t() | Regex.t(), pattern_spec()}
]) :: :ok

Registers patterns for a domain and language.

This is called by domain modules (e.g., Domains.Database) during compilation.

Examples

Patterns.register(:db, :elixir, [
  {"Repo.get", %{operation: :retrieve, framework: :ecto, extract_target: :first_arg}},
  {"Repo.all", %{operation: :retrieve_all, framework: :ecto}}
])