plymio_vekil v0.1.0 Plymio.Vekil.Forom.Form View Source

The module implements the Plymio.Vekil.Forom protocol and produces quoted forms.

See Plymio.Vekil.Forom for the definitions of the protocol functions.

See Plymio.Vekil for an explanation of the test environment.

The default :produce_default is an empty list.

The default :realise_default is the unset value (Plymio.Fontais.the_unset_value/0).

Module State

See Plymio.Vekil.Forom for the common fields.

The module’s state is held in a struct with the following field(s):

FieldAliasesPurpose
:foromholds the quoted form

Link to this section Summary

Functions

new/1 takes an optional opts and creates a new forom returning {:ok, forom}

new!/1 calls new/1 and, if the result is {:ok, instance} returns the instance

normalise/1 creates a new forom from its argument unless the argument is already one

produce/2 takes a forom and an optional opts, calls update/2 with the vekil and the opts if any, and returns {:ok, {product, forom}}

realise/2 takes a forom and an optional opts, calls produce/2 and then gets (Keyword.get_values/2) the :forom key values from the product

update!/2 calls update/2 and, if the result is {:ok, instance} returns the instance

Link to this section Types

Link to this type t() View Source
t() :: %Plymio.Vekil.Forom.Form{
  forom: term(),
  produce_default: term(),
  protocol_impl: term(),
  protocol_name: term(),
  realise_default: term()
}

Link to this section Functions

Link to this function new(opts \\ []) View Source
new(any()) :: {:ok, t()} | {:error, error()}

new/1 takes an optional opts and creates a new forom returning {:ok, forom}.

Examples

iex> {:ok, forom} = new()
...> match?(%FOROMFORM{}, forom)
true

Plymio.Vekil.Utility.forom?/1 returns true if the value implements Plymio.Vekil.Forom

iex> {:ok, forom} = new()
...> forom |> Plymio.Vekil.Utility.forom?
true

The form is passed using the :forom key:

iex> {:ok, forom} = new(forom: quote(do: x = x + 1))
...> forom |> Plymio.Vekil.Utility.forom?
true

iex> {:ok, forom} = new(
...>    forom: quote(do: x = x + 1), proxy: :x_add_1)
...> forom |> Plymio.Vekil.Utility.forom?
true

Same example but here the realise function is used to access the form in the :forom field:

iex> {:ok, forom} = new(
...>    forom: quote(do: x = x + 1), proxy: :x_add_1)
...> {:ok, {form, _}} = forom |> FOROMPROT.realise
...> form |> harnais_helper_test_forms!(binding: [x: 7])
{8, ["x = x + 1"]}

The form is validated:

iex> {:error, error} = new(forom: %{a: 1})
...> error |> Exception.message
"form invalid, got: %{a: 1}"
Link to this function new!(opts \\ []) View Source
new!(any()) :: t() | no_return()

new!/1 calls new/1 and, if the result is {:ok, instance} returns the instance.

Link to this function normalise(value) View Source
normalise(any()) :: {:ok, struct()} | {:error, error()}

normalise/1 creates a new forom from its argument unless the argument is already one.

Examples

iex> {:ok, forom} = quote(do: x = x + 1) |> normalise
...> {:ok, {form, _}} = forom |> FOROMPROT.realise
...> form |> harnais_helper_test_forms!(binding: [x: 3])
{4, ["x = x + 1"]}

iex> {:ok, forom} = normalise(
...>   forom: quote(do: x = x + 1), proxy: :add_1)
...> {:ok, {form, _}} = forom |> FOROMPROT.realise
...> form |> harnais_helper_test_forms!(binding: [x: 3])
{4, ["x = x + 1"]}

Multiples forms can be stored:

iex> {:ok, forom} = [
...>    quote(do: x = x + 1),
...>    quote(do: x = x * x),
...>    quote(do: x = x - 1)
...> ] |> normalise
...> {:ok, {forms, _}} = forom |> FOROMPROT.realise
...> forms |> harnais_helper_test_forms!(binding: [x: 3])
{15, ["x = x + 1", "x = x * x", "x = x - 1"]}

An invalid form returns an error result:

iex> {:error, error} = %{a: 1} |> normalise
...> error |> Exception.message
"form invalid, got: %{a: 1}"

An existing forom (of any implementation) is returned unchanged:

iex> {:ok, forom} = quote(do: x = x + 1) |> normalise
...> {:ok, forom} = forom |> normalise
...> {:ok, {form, _}} = forom |> FOROMPROT.realise
...> form |> harnais_helper_test_forms!(binding: [x: 8])
{9, ["x = x + 1"]}
Link to this function produce(forom, opts \\ []) View Source
produce(t(), opts()) :: {:ok, {product(), t()}} | {:error, error()}

produce/2 takes a forom and an optional opts, calls update/2 with the vekil and the opts if any, and returns {:ok, {product, forom}}.

The product will be Keyword with one or more :forom keys where the values are the forms.

Examples

iex> {:ok, forom} = quote(do: x = x + 1) |> normalise
...> {:ok, {product, %FOROMFORM{}}} = forom |> FOROMPROT.produce
...> [:forom] = product |> Keyword.keys |> Enum.uniq
...> product |> Keyword.get_values(:forom)
...> |> harnais_helper_test_forms!(binding: [x: 41])
{42, ["x = x + 1"]}

iex> {:ok, forom} = [
...>    quote(do: x = x + 1),
...>    quote(do: x = x * x),
...>    quote(do: x = x - 1)
...> ] |> normalise
...> {:ok, {product, _}} = forom |> FOROMPROT.produce
...> product |> Keyword.get_values(:forom)
...> |> harnais_helper_test_forms!(binding: [x: 3])
{15, ["[x = x + 1, x = x * x, x = x - 1]"]}

If opts are given, update/2 is called before producing the forom:

iex> {:ok, forom} = new()
...> {:ok, forom} = forom |> update(forom: quote(do: x = x + 1))
...> {:ok, {product, %FOROMFORM{}}} = forom |> FOROMPROT.produce
...> [:forom] = product |> Keyword.keys |> Enum.uniq
...> product |> Keyword.get_values(:forom)
...> |> harnais_helper_test_forms!(binding: [x: 41])
{42, ["x = x + 1"]}

An empty forom does not produce any :forom keys:

iex> {:ok, forom} = new()
...> {:ok, {product, _}} = forom |> FOROMPROT.produce
...> product |> Keyword.get_values(:forom)
...> |> harnais_helper_test_forms!(binding: [x: 41])
{nil, []}
Link to this function realise(forom, opts \\ []) View Source
realise(t(), opts()) :: {:ok, {any(), t()}} | {:error, error()}

realise/2 takes a forom and an optional opts, calls produce/2 and then gets (Keyword.get_values/2) the :forom key values from the product.

The forms are then normalised (Plymio.Fontais.Form.forms_normalise/1) and {:ok, {forms, forom}} returned.

Examples

iex> {:ok, forom} = quote(do: x = x + 1) |> normalise
...> {:ok, {forms, _}} = forom |> FOROMPROT.realise
...> forms |> harnais_helper_test_forms!(binding: [x: 41])
{42, ["x = x + 1"]}

iex> {:ok, forom} = [
...>    quote(do: x = x + 1),
...>    quote(do: x = x * x),
...>    quote(do: x = x - 1)
...> ] |> normalise
...> {:ok, {forms, %FOROMFORM{}}} = forom |> FOROMPROT.realise
...> forms |> harnais_helper_test_forms!(binding: [x: 3])
{15, ["x = x + 1", "x = x * x", "x = x - 1"]}

If opts are given, update/2 is called before realising the forom:

iex> {:ok, forom} = new()
...> {:ok, {forms, %FOROMFORM{}}} = forom
...>    |> FOROMPROT.realise(forom: quote(do: x = x + 1))
...> forms |> harnais_helper_test_forms!(binding: [x: 41])
{42, ["x = x + 1"]}

An empty forom does not produce any :forom keys so the :realise_default is returned:

iex> {:ok, forom} = new()
...> {:ok, {value, _forom}} = forom |> FOROMPROT.realise
...> value |> Plymio.Fontais.Guard.is_value_unset
true
Link to this function update(t, opts \\ []) View Source
update(t(), opts()) :: {:ok, t()} | {:error, error()}

update/2 implements Plymio.Vekil.Forom.update/2.

Examples

iex> {:ok, forom} = new(
...>    forom: quote(do: x = x + 1), proxy: :x_add_1)
...> {:ok, forom} = forom |> update(forom: quote(do: x = x * x))
...> {:ok, {form, _}} = forom |> FOROMPROT.realise
...> form |> harnais_helper_test_forms!(binding: [x: 7])
{49, ["x = x * x"]}
Link to this function update!(t, opts \\ []) View Source
update!(t(), any()) :: t() | no_return()

update!/2 calls update/2 and, if the result is {:ok, instance} returns the instance.