plymio_ast v0.2.0 Plymio.Ast.Signature
Utility Functions for Creating Quoted Function Signatures (a list of Asts).
The Signature DSL
signature_create/2
implements a trivially simple dsl for creating unquotable signatures.
It always returns a list of unquotable values (asts) expected to be used with
Kernel.SpecialForms.unquote_splicing/1
.
The signature
passed to signature_create/2
must be one or more signature items
.
Each signature item
results in one unquotable argument
and can have one of a number of forms:
Signature Item - item (Atom
)
When the item is an atom, and the item is a key in the unquotables
(see the signature options), the value is returned,
else the argument will be the the result of Macro.var(item, nil)
.
iex> :arg0 |> helper_signature_create_to_string
"(arg0)"
iex> [:arg0, :arg1, :arg2] |> helper_signature_create_to_string
"(arg0, arg1, arg2)"
iex> unquotables = %{arg1: Macro.var(:arg111, nil), arg3: Macro.var(:arg3, nil)}
...> [:arg0, :arg1, :arg2]
...> |> helper_signature_create_to_string(unquotables: unquotables)
"(arg0, arg111, arg2)"
Signature Item - ast (3tuple)
If the item is already a valid ast, it will be used directly.
iex> Macro.var(:arg42, nil) |> helper_signature_create_to_string
"(arg42)"
iex> unquotables = %{arg1: Macro.var(:arg111, nil), arg3: Macro.var(:arg3, nil)}
...> [Macro.var(:arg42, nil), :arg1, :arg2]
...> |> helper_signature_create_to_string(unquotables: unquotables)
"(arg42, arg111, arg2)"
Signature Item - {value, default}
When the item is a 2tuple, the first element is resolved as before.
The second element is taken as the default value and is broadly resolved in the same way as the first element:
When the default is an atom it is first looked up in the :unquotables
(if supplied) or escaped (if necessary).
iex> {:arg0, 42} |> helper_signature_create_to_string
"(arg0 \\\\ 42)"
iex> {:arg0, :arg0_default} |> helper_signature_create_to_string
"(arg0 \\\\ :arg0_default)"
iex> {:arg0, %{a: 1}} |> helper_signature_create_to_string
"(arg0 \\\\ %{a: 1})"
iex> unquotables = %{
...> arg1: Macro.var(:arg111, nil), arg3: Macro.var(:arg3, nil),
...> default_x1: :x1, default_y2: %{a: 1}, default_z3: {1, :two, "tre"}}
...> [{:arg0, :default_z3}, :arg1, {:arg2, :default_x1}]
...> |> helper_signature_create_to_string(unquotables: unquotables)
"(arg0 \\\\ {1, :two, \"tre\"}, arg111, arg2 \\\\ :x1)"
When the default is already an ast it is used directly:
iex> default_ast = %{a: 1} |> Macro.escape
...> {:arg0, default_ast} |> helper_signature_create_to_string
"(arg0 \\\\ %{a: 1})"
There are a few special (Atom
) defaults for convenience
iex> {:arg0, :empty_map} |> helper_signature_create_to_string
"(arg0 \\\\ %{})"
iex> {:arg0, :empty_list} |> helper_signature_create_to_string
"(arg0 \\\\ [])"
iex> {:arg0, :empty_tuple} |> helper_signature_create_to_string
"(arg0 \\\\ {})"
true
, false
and nil
work as expected
iex> {:arg0, nil} |> helper_signature_create_to_string
"(arg0 \\\\ nil)"
iex> {:arg0, true} |> helper_signature_create_to_string
"(arg0 \\\\ true)"
iex> {:arg0, false} |> helper_signature_create_to_string
"(arg0 \\\\ false)"
The Signature Options
The options that can be given to signature_create/2
are:
Signature Options - :unquotables
If given, the :unquotables
option must be a map where the keys are atoms and the values an ast.
The map is used as a dictionary to look up signature item
that are atoms.
Note, for convenience, any non valid ast values are escaped (
Macro.escape/1
)
Summary
Functions
See above for the explanation of the arguments to signature_create/2
and more examples
Types
signature_default :: nil | false | true | :empty_map | :empty_list | :empty_tuple | unquotables_map_key | unquotable
Functions
signature_create(signature, signature_options) :: signature_ast
See above for the explanation of the arguments to signature_create/2
and more examples.
The example below repeat some of the above but show both the returned signature ast list and then the result of calling Macro.to_string/1
.
Note
signature_create/2
ensures the the returned signature is a valid ast, its does not attempt to validate its syntax: that is left to the compiler.
Examples
In these examples, an explicit default (e.g. arg0 \\ 42
) for the argument is provided:
iex> unquotables = %{arg0: Macro.var(:arg0, nil), arg1: Macro.var(:arg1, nil)}
...> {:arg1, 42}
...> |> helper_signature_create(unquotables: unquotables)
[{:\\, [], [{:arg1, [], nil}, 42]}]
iex> unquotables = %{arg0: Macro.var(:arg0, nil), arg1: Macro.var(:arg1, nil)}
...> {:arg1, 42}
...> |> helper_signature_create_to_string(unquotables: unquotables)
"(arg1 \\\\ 42)"
iex> unquotables = %{arg0: Macro.var(:arg0, nil), arg1: Macro.var(:arg1, nil)}
...> [:arg0, {:arg1, nil}]
...> |> helper_signature_create(unquotables: unquotables)
[{:arg0, [], nil}, {:\\, [], [{:arg1, [], nil}, nil]}]
iex> unquotables = %{arg0: Macro.var(:arg0, nil), arg1: Macro.var(:arg1, nil)}
...> [:arg0, {:arg1, nil}]
...> |> helper_signature_create_to_string(unquotables: unquotables)
"(arg0, arg1 \\\\ nil)"
iex> unquotables = %{arg0: Macro.var(:arg0, nil), arg1: Macro.var(:arg1, nil)}
...> [{:arg0, %{a: 1}}, {:arg1, true}]
...> |> helper_signature_create(unquotables: unquotables)
[{:\\, [], [{:arg0, [], nil}, {:%{}, [], [a: 1]}]}, {:\\, [], [{:arg1, [], nil}, true]}]
iex> unquotables = %{arg0: Macro.var(:arg0, nil), arg1: Macro.var(:arg1, nil)}
...> [{:arg0, %{a: 1}}, {:arg1, true}]
...> |> helper_signature_create_to_string(unquotables: unquotables)
"(arg0 \\\\ %{a: 1}, arg1 \\\\ true)"
In these examples, the default is a key in the quotables map
iex> unquotables = %{arg1: Macro.var(:arg1, nil), default: 42}
...> {:arg1, :default}
...> |> helper_signature_create(unquotables: unquotables)
[{:\\, [], [{:arg1, [], nil}, 42]}]
iex> unquotables = %{arg1: Macro.var(:arg1, nil), default: 42}
...> {:arg1, :default}
...> |> helper_signature_create_to_string(unquotables: unquotables)
"(arg1 \\\\ 42)"
iex> unquotables = %{
...> arg1: Macro.var(:arg1, nil),
...> def42: 42,
...> defmap1: Macro.escape(%{x: 99})}
...> [{Macro.var(:arg2, nil), :def42}, {:arg1, :defmap1}]
...> |> helper_signature_create(unquotables: unquotables)
[{:\\, [], [{:arg2, [], nil}, 42]}, {:\\, [], [{:arg1, [], nil}, {:%{}, [], [x: 99]}]}]
iex> unquotables = %{
...> arg1: Macro.var(:arg1, nil),
...> def42: 42,
...> defmap1: Macro.escape(%{x: 99})}
...> [{Macro.var(:arg2, nil), :def42}, {:arg1, :defmap1}]
...> |> helper_signature_create_to_string(unquotables: unquotables)
"(arg2 \\\\ 42, arg1 \\\\ %{x: 99})"
In these examples, a pre-existing ast is supplied
iex> Macro.var(:arg2, nil) |> helper_signature_create
[{:arg2, [], nil}]
iex> {Macro.var(:arg2, nil), 42} |> helper_signature_create
[{:\\, [], [{:arg2, [], nil}, 42]}]
In these examples, a range of signature values are used
iex> unquotables = %{arg0: Macro.var(:arg0, nil), arg1: Macro.var(:arg1, nil), def42: 42}
...> [{:arg0, %{a: 1}}, :arg1, {Macro.var(:arg2, nil), :def42}]
...> |> helper_signature_create_to_string(unquotables: unquotables)
"(arg0 \\\\ %{a: 1}, arg1, arg2 \\\\ 42)"
In these examples some of the “convenience” values for the signature are used for defaults
iex> unquotables = %{arg0: Macro.var(:arg0, nil), arg1: Macro.var(:arg1, nil)}
...> {:arg1, :empty_list} |> helper_signature_create(unquotables: unquotables)
[{:\\, [], [{:arg1, [], nil}, []]}]
iex> unquotables = %{arg0: Macro.var(:arg0, nil), arg1: Macro.var(:arg1, nil)}
...> {:arg1, :empty_list} |> helper_signature_create_to_string(unquotables: unquotables)
"(arg1 \\\\ [])"
iex> unquotables = %{arg0: Macro.var(:arg0, nil), arg1: Macro.var(:arg1, nil)}
...> {:arg1, :empty_map}
...> |> helper_signature_create(unquotables: unquotables)
[{:\\, [], [{:arg1, [], nil}, {:%{}, [], []}]}]
iex> unquotables = %{arg0: Macro.var(:arg0, nil), arg1: Macro.var(:arg1, nil)}
...> {:arg1, :empty_map}
...> |> helper_signature_create_to_string(unquotables: unquotables)
"(arg1 \\\\ %{})"
iex> unquotables = %{arg0: Macro.var(:arg0, nil), arg1: Macro.var(:arg1, nil)}
...> {:arg1, :empty_tuple}
...> |> helper_signature_create(unquotables: unquotables)
[{:\\, [], [{:arg1, [], nil}, {:{}, [], []}]}]
iex> unquotables = %{arg0: Macro.var(:arg0, nil), arg1: Macro.var(:arg1, nil)}
...> {:arg1, :empty_tuple}
...> |> helper_signature_create_to_string(unquotables: unquotables)
"(arg1 \\\\ {})"