View Source Matcha.Context behaviour (Matcha v0.1.6)

Different types of match spec are intended to be used for different purposes, and support different instructions in their bodies for different use-cases.

The modules implementing the Matcha.Context behaviour define the different types of Matcha.Spec, provide documentation for what specialized instructions that type supports, and are used during Elixir-to-match spec conversion as a concrete function definition to use when expanding instructions (since most of these specialized instructions do not exist anywhere as an actual functions, this lets the Elixir compiler complain about invalid instructions as UndefinedFunctionErrors).

predefined-contexts

Predefined contexts

Currently there are three applications of match specs supported:

  • :filter_map:

    Matchspecs intended to be used to filter/map over an in-memory list in an optimized fashion. These types of match spec reference the Matcha.Context.FilterMap module.

  • :match:

    Matchspecs intended to be used to match over an in-memory list in an optimized fashion. These types of match spec reference the Matcha.Context.Match module.

  • :table:

    Matchspecs intended to be used to efficiently select data from BEAM VM "table" tools, such as :ets, :dets, and :mnesia, and massage the values returned. These types of match spec reference the Matcha.Context.Table module.

  • :trace:

    Matchspecs intended to be used to instruct tracing utilities such as :dbg and :recon_trace exactly what function calls with what arguments to trace, and allows invoking special trace command instructions in response. These types of match spec reference the Matcha.Context.Trace module.

custom-contexts

Custom contexts

The context mechanism is technically extensible: any module can implement the Matcha.Context behaviour, define the callbacks, and list public no-op functions to allow their usage in specs compiled with that context (via Matcha.spec(CustomContext) do...).

In practice there is little point in defining a custom context: the supported use-cases for match specs are tightly coupled to the erlang language, and Matcha covers all of them with its provided contexts, which should be sufficient for any application. The module+behaviour+callback implementation used in Matcha is less about offering extensibility, but instead used to simplify special-casing in Matcha.Spec function implementations, raise Elixir-flavored errors when an invalid instruction is used in the different types of spec, and provide a place to document what they do when invoked.

Link to this section Summary

Callbacks

A default value to use when executing match specs in this context.

Which primitive erlang context this context module wraps.

Describes an issue with a test target.

Allows this context module to modify match specs before their execution.

A validator that runs before executing a match spec against a target in this context.

Functions

Resolves shortcut references to the core Matcha context modules.

Determines whether or not specs in this context can be compiled.

Determines whether or not specs in this context can used in tracing.

Link to this section Types

Link to this section Callbacks

Link to this callback

__default_match_target__()

View Source
@callback __default_match_target__() :: any()

A default value to use when executing match specs in this context.

This function is used to provide Matcha.Source.test/3 with a target value to test against, in situations where it is being used to simply validate the match spec itself, but we do not acutally care if the input matches the spec.

This value, when passed to this context's Matcha.Context.__valid_match_target__/1 callback, must produce a true value.

Link to this callback

__emit_erl_test_result__(result)

View Source
@callback __emit_erl_test_result__(result :: any()) ::
  {:emit, new_result :: any()} | :no_emit
@callback __erl_spec_type__() :: Matcha.Source.type()

Which primitive erlang context this context module wraps.

Link to this callback

__invalid_match_target_error_message__(match_target)

View Source
@callback __invalid_match_target_error_message__(match_target :: any()) :: String.t()

Describes an issue with a test target.

Invoked to generate a t:Matcha.Error.message when Matcha.Context.__valid_match_target__/1 fails.

Link to this callback

__prepare_source__(source)

View Source
@callback __prepare_source__(source :: Matcha.Source.uncompiled()) ::
  {:ok, new_source :: Matcha.Source.uncompiled()}
  | {:error, Matcha.Error.problems()}

Allows this context module to modify match specs before their execution.

This hook is the main entrypoint for creating custom contexts, allowing them to augment the match spec with new behaviour when executed in this context.

Care must be taken to handle the results of the modified match spec after execution correctly, before they are returned to the caller. This should be implemented in the callbacks:

  • c:__transform_erl_run_results__/1
  • c:__transform_erl_test_result__/1
  • c:__emit_erl_test_result__/1
Link to this callback

__transform_erl_run_results__(results)

View Source
@callback __transform_erl_run_results__(results :: [any()]) ::
  {:ok, results :: [any()]} | {:error, Matcha.Error.problems()}
Link to this callback

__transform_erl_test_result__(result)

View Source
@callback __transform_erl_test_result__(result :: any()) ::
  {:ok, result :: any()} | {:error, Matcha.Error.problems()}
Link to this callback

__valid_match_target__(match_target)

View Source
@callback __valid_match_target__(match_target :: any()) :: boolean()

A validator that runs before executing a match spec against a target in this context.

This validator is run before any match specs are executed on inputs to Matcha.Source.test/3, and all elements of the enumerable input to Matcha.Source.run/2.

If this function returns false, the match spec will not be executed, instead returning a t:Matcha.Error.error_problem with a t:Matcha.Error.message generated by the Matcha.Context.__invalid_match_target_error_message__/1 callback.

Link to this section Functions

@spec resolve(atom() | t()) :: t() | no_return()

Resolves shortcut references to the core Matcha context modules.

@spec run(Matcha.Spec.t(), Enumerable.t()) ::
  {:ok, [any()]} | {:error, Matcha.Error.problems()}
Link to this function

stream(spec, enumerable)

View Source
@spec stream(Matcha.Spec.t(), Enumerable.t()) ::
  {:ok, Enumerable.t()} | {:error, Matcha.Error.problems()}
Link to this function

supports_compilation?(context)

View Source
@spec supports_compilation?(t()) :: boolean()

Determines whether or not specs in this context can be compiled.

Link to this function

supports_tracing?(context)

View Source
@spec supports_tracing?(t()) :: boolean()

Determines whether or not specs in this context can used in tracing.

@spec test(Matcha.Spec.t()) :: {:ok, any()} | {:error, Matcha.Error.problems()}
Link to this function

test(spec, match_target)

View Source
@spec test(Matcha.Spec.t(), Matcha.Source.match_target()) ::
  {:ok, any()} | {:error, Matcha.Error.problems()}