Current section
Files
Jump to
Current section
Files
src/metamon@transform.erl
-module(metamon@transform).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/metamon/transform.gleam").
-export([new/2, identity/0, constant/2, then/2, repeat/2, rename/2]).
-export_type([transform/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Named, deterministic input transformations. The `name` is surfaced\n"
" in failure messages so a metamorphic relation always reports which\n"
" transformation produced the follow-up input.\n"
).
-type transform(GUX) :: {transform, binary(), fun((GUX) -> GUX)}.
-file("src/metamon/transform.gleam", 16).
?DOC(" Construct a transform from a name and a function.\n").
-spec new(binary(), fun((GUY) -> GUY)) -> transform(GUY).
new(Name, Apply) ->
{transform, Name, Apply}.
-file("src/metamon/transform.gleam", 21).
?DOC(" The transform that returns its input unchanged.\n").
-spec identity() -> transform(any()).
identity() ->
{transform, <<"identity"/utf8>>, fun(Value) -> Value end}.
-file("src/metamon/transform.gleam", 28).
?DOC(
" A transform that ignores its input and always returns `value`.\n"
" Use sparingly — most metamorphic relations want a real\n"
" transformation rather than a constant.\n"
).
-spec constant(binary(), GVC) -> transform(GVC).
constant(Name, Value) ->
{transform, Name, fun(_) -> Value end}.
-file("src/metamon/transform.gleam", 34).
?DOC(
" Sequential composition: `then(t1, t2).apply(x) == t2.apply(t1.apply(x))`.\n"
" The composite name is `\"<t1.name> |> <t2.name>\"`.\n"
).
-spec then(transform(GVE), transform(GVE)) -> transform(GVE).
then(T1, T2) ->
{transform,
<<<<(erlang:element(2, T1))/binary, " |> "/utf8>>/binary,
(erlang:element(2, T2))/binary>>,
fun(Value) ->
(erlang:element(3, T2))((erlang:element(3, T1))(Value))
end}.
-file("src/metamon/transform.gleam", 57).
-spec repeat_step(fun((GVM) -> GVM), integer(), GVM) -> GVM.
repeat_step(F, Remaining, Value) ->
case Remaining =< 0 of
true ->
Value;
false ->
repeat_step(F, Remaining - 1, F(Value))
end.
-file("src/metamon/transform.gleam", 53).
-spec repeat_apply(fun((GVL) -> GVL), integer()) -> fun((GVL) -> GVL).
repeat_apply(F, Times) ->
fun(Value) -> repeat_step(F, Times, Value) end.
-file("src/metamon/transform.gleam", 42).
?DOC(
" Apply `t` exactly `n` times. `repeat(t, 0)` is `identity`. Negative\n"
" counts are treated as `0`.\n"
).
-spec repeat(transform(GVI), integer()) -> transform(GVI).
repeat(T, N) ->
case N =< 0 of
true ->
identity();
false ->
{transform,
<<<<(erlang:element(2, T))/binary, " × "/utf8>>/binary,
(erlang:integer_to_binary(N))/binary>>,
repeat_apply(erlang:element(3, T), N)}
end.
-file("src/metamon/transform.gleam", 66).
?DOC(
" Override the name of a transform. The behaviour of `apply` is not\n"
" changed — only the label that appears in failure reports.\n"
).
-spec rename(transform(GVN), binary()) -> transform(GVN).
rename(T, Name) ->
{transform, Name, erlang:element(3, T)}.