View Source Matcha.Context behaviour (Matcha v0.1.10)
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 UndefinedFunctionError
s).
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 theMatcha.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 theMatcha.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.
Decides if the result of a spec match should be part of the result set.
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.
Transforms the result of a spec match just after calling :ets.match_spec_run/2
.
Transforms the result of a spec match just after calling :erlang.match_spec_test/3
.
A validator that runs before executing a match spec against a target
in this context.
Functions
Maps the shortcut references to the core Matcha context modules.
Resolves shortcut references to the core Matcha context modules.
Runs a spec
against an enumerable
.
Creates a lazy Stream
that yields the results of running the spec
against the provided enumberable
.
Determines whether or not specs in this context can be compiled.
Determines whether or not specs in this context can used in tracing.
Tests that the provided spec
in its Matcha.Context
is valid.
Tests that the provided spec
in its Matcha.Context
correctly matches a provided match_target
.
Link to this section Types
@type t() :: module()
Link to this section Callbacks
@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.
Decides if the result of a spec match should be part of the result set.
This callback runs just after calls to __transform_erl_test_result__/1
or __transform_erl_test_result__/1
.
Must return {:emit, result}
to include the transformed result of a spec match, when executing it
against in-memory data (as opposed to tracing or :ets) for validation or debugging purposes.
Otherwise, returning :no_emit
will hide the result.
@callback __erl_spec_type__() :: Matcha.Source.type()
Which primitive Erlang context this context module wraps.
Describes an issue with a test target.
Invoked to generate a t:Matcha.Error.message
when Matcha.Context.__valid_match_target__/1
fails.
@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:
@callback __transform_erl_run_results__(results :: [any()]) :: {:ok, results :: [any()]} | {:error, Matcha.Error.problems()}
Transforms the result of a spec match just after calling :ets.match_spec_run/2
.
You can think of this as an opportunity to "undo" any modifications to the user's
provided matchspec made in __prepare_source__/1
.
Must return {:ok, result}
to indicate that the returned value is valid; otherwise
return {:error, problems}
to raise an exception.
@callback __transform_erl_test_result__(result :: any()) :: {:ok, result :: any()} | {:error, Matcha.Error.problems()}
Transforms the result of a spec match just after calling :erlang.match_spec_test/3
.
You can think of this as an opportunity to "undo" any modifications to the user's
provided matchspec made in __prepare_source__/1
.
Must return {:ok, result}
to indicate that the returned value is valid; otherwise
return {:error, problems}
to raise an exception.
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 __core_context_aliases__() :: Keyword.t()
Maps the shortcut references to the core Matcha context modules.
This describes which shortcuts users may write, for example in Matcha.spec(:some_shortcut)
instead of
the fully qualified module Matcha.spec(Matcha.Context.SomeContext)
.
Resolves shortcut references to the core Matcha context modules.
This allows users to write, for example, Matcha.spec(:trace)
instead of
the fully qualified module Matcha.spec(Matcha.Context.Trace)
.
@spec run(Matcha.Spec.t(), Enumerable.t()) :: {:ok, [any()]} | {:error, Matcha.Error.problems()}
Runs a spec
against an enumerable
.
This is a key function that ensures the input spec
and results
are passed through the callbacks of a Matcha.Context
.
Returns either {:ok, results}
or {:error, problems}
(that other !
APIs may use to raise an exception).
@spec stream(Matcha.Spec.t(), Enumerable.t()) :: {:ok, Enumerable.t()} | {:error, Matcha.Error.problems()}
Creates a lazy Stream
that yields the results of running the spec
against the provided enumberable
.
This is a key function that ensures the input spec
and results
are passed through the callbacks of a Matcha.Context
.
Returns either {:ok, stream}
or {:error, problems}
(that other !
APIs may use to raise an exception).
Determines whether or not specs in this context can be compiled.
Determines whether or not specs in this context can used in tracing.
@spec test(Matcha.Spec.t()) :: {:ok, any()} | {:error, Matcha.Error.problems()}
Tests that the provided spec
in its Matcha.Context
is valid.
Invokes __default_match_target__/0
and passes it into :erlang.match_spec_test/3
.
Returns either {:ok, stream}
or {:error, problems}
(that other !
APIs may use to raise an exception).
@spec test(Matcha.Spec.t(), Matcha.Source.match_target()) :: {:ok, any()} | {:error, Matcha.Error.problems()}
Tests that the provided spec
in its Matcha.Context
correctly matches a provided match_target
.
Passes the provided match_target
into :erlang.match_spec_test/3
.
Returns either {:ok, stream}
or {:error, problems}
(that other !
APIs may use to raise an exception).