plymio_codi v0.3.1 Plymio.Codi View Source

Plymio.Codi generates quoted forms for common code patterns.

The produce_codi/2 function produces the quoted forms for the patterns.

The reify_codi/2 macro calls produce_codi/2 and then compiles the forms.

Documentation Terms

In the documentation below these terms, usually in italics, are used to mean the same thing.

opts

opts is a Keyword list.

form and forms

A form is a quoted form (Macro.t). A forms is a list of zero, one or more forms.

vekil

The proxy patterns (see below) use a dictionary called the vekil: The proxy can be though of as the key while its value (called a from) “realises” to a form / forms.

The vekil implements the Plymio.Vekil protocol. If the vekil given to new/1 or update/2 is a Map or Keyword, it will be used to create a Plymio.Vekil.Form vekil.

The forom in the vekil must “realise” (Plymio.Vekil.Forom.realise/2) to forms.

It is more efficient to pre-create (ideally at compile time) the vekil; it can be edited later using e.g. :proxy_put.

Options (opts)

The first argument to both of these functions is an opts.

The canonical form of a pattern definition in the opts is the key :pattern with an opts value specific to the pattern e.g.

  [pattern: [pattern: :delegate, name: :fun_one, arity: 1, module: ModuleA]

The value is referred to as the cpo below, short for codi pattern opts.

All pattern definitions are normalised to this format.

However, for convenience, the key can be the pattern name (e.g. :delegate) and the value the (pre normalised) cpo:

  [delegate: [name: :fun_one, arity: 1, module: ModuleA]

This example shows the code produced for the above:

iex> {:ok, {forms, _}} = [
...>   delegate: [name: :fun_one, arity: 1, module: ModuleA],
...> ] |> produce_codi
...> forms |> harnais_helper_show_forms!
["@doc(\"Delegated to `ModuleA.fun_one/1`\")",
 "defdelegate(fun_one(var1), to: ModuleA)"]

Also, again for convenience, some patterns will normalise the value. For example the :doc pattern normalises this:

[doc: "This is a docstring"]

into this:

[pattern: [pattern: doc, doc: "This is a docstring"]

The keys in the cpo have aliases. Note the aliases are pattern-specific. For examples :args is both an alias for :spec_args and :fun_args. Each pattern below lists its keys’ aliases.

Common Codi Pattern Opts Keys

These are the keys that can appear in a cpo as well as the pattern-specific ones:

KeyAliasesRole
:patternthe name of the pattern
:forms_edit:form_edit, :edit_forms, :edit_formforms_edit/2 opts

there are other, internal use, keys that can appear as well.

Editing Pattern Forms

Most patterns produce forms. Individual pattern forms can be edited by giving a :forms_edit key in the cpo where the value is an opts understood by Plymio.Fontais.Form.forms_edit/2.

Alternatively the :forms_edit can be given in the opts to produce_codi/2 (or reify_codi/2) and will be applied to all produced forms.

Patterns

There are a number of patterns, some having aliases, described below:

PatternAliases
:form:forms, :ast, :asts
:typespec_spec:spec
:doc
:since
:delegate
:delegate_module
:bang
:bang_module
:query
:query_module
:proxy_fetch:proxy, :proxies, :proxies_fetch
:proxy_put:proxies_put
:proxy_delete:proxies_delete
:proxy_get:proxies_get
:struct_get
:struct_fetch
:struct_put
:struct_maybe_put
:struct_has?
:struct_update
:struct_set
:struct_export

Pattern: form

The form pattern is a convenience to embed arbitrary code.

See Plymio.Codi.Pattern.Other for details and examples.

Pattern: typespec_spec

The typespec_spec pattern builds a @spec module attribute form.

See Plymio.Codi.Pattern.Typespec for details and examples.

Pattern: doc

The doc pattern builds a @doc module attribute form.

See Plymio.Codi.Pattern.Doc for details and examples.

Pattern: since

The since pattern builds a @since module attribute form.

See Plymio.Codi.Pattern.Other for details and examples.

Pattern: deprecated

The deprecated pattern builds a @deprecated module attribute form.

See Plymio.Codi.Pattern.Other for details and examples.

Pattern: delegate and delegate_module

The delegate pattern builds a Kernel.defdelegate/2 call, together, optionally, with a @doc, @since, and/or @spec.

The delegate_module pattern builds a Kernel.defdelegate/2 call for one or more functions in a module. As with :delegate a @doc and/or @since can be generated at the same time.

See Plymio.Codi.Pattern.Delegate for details and examples.

Pattern: bang and bang_module

The bang pattern builds bang functions (e.g. myfun!(arg)) using existing base functions (e.g. myfun(arg)).

The bang_module pattern builds a bang function for one or more functions in a module. As with :bang a @doc or @since can be generated at the same time.

See Plymio.Codi.Pattern.Bang for details and examples.

Pattern: query and query_module

The query pattern works like bang but builds a query function (e.g. myfun?(arg)) using a base function (e.g. myfun(arg)).

The query_module pattern builds a query function for one or more functions in a module. As with :query a @doc or @since can be generated at the same time.

See Plymio.Codi.Pattern.Query for details and examples.

Pattern: proxy patterns

The proxy patterns manage the vekil..

See Plymio.Codi.Pattern.Proxy for details and examples.

Pattern: struct patterns

The struct patterns create a range of transform functions for a module’s struct.

See Plymio.Codi.Pattern.Struct for details and examples.

Link to this section Summary

Functions

new/1 creates a new instance of the module’s struct and, if the optional opts were given, calls update/2 with the instance and the opts, returning {:ok, instance}, else {:error, error}

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

update/2 takes an instance of the module’s struct and an optional opts

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.Codi{
  forms: term(),
  forms_edit: term(),
  module_doc_dict: term(),
  module_fva_dict: term(),
  pattern_dicts: term(),
  pattern_express_dispatch: term(),
  pattern_normalisers: term(),
  patterns: term(),
  snippets: term(),
  stage_dispatch: term(),
  vekil: term()
}

Link to this section Functions

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

new/1 creates a new instance of the module’s struct and, if the optional opts were given, calls update/2 with the instance and the opts, returning {:ok, instance}, else {:error, error}.

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 produce_codi(opts, codi_or_opts \\ []) View Source
produce_codi(any(), any()) :: {:ok, {forms(), t()}} | {:error, error()}
Link to this macro reify_codi(opts \\ [], other_opts \\ []) View Source (macro)
Link to this function update(t, opts \\ []) View Source
update(t(), opts()) :: {:ok, t()} | {:error, error()}

update/2 takes an instance of the module’s struct and an optional opts.

The opts are normalised by calling the module’s update_canonical_opts/1 and then reduced with update_field/2:

opts |> Enum.reduce(instance, fn {k,v}, s -> s |> update_field({k,v}) end)

{:ok, instance} is returned.

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.