plymio_ast v1.0.0 Plymio.Ast.Form View Source
Utility Functions for Manipulating Asts (Quoted Forms)
Many functions return either {:ok, value} or {:error, error} where error with be usually an ArgumentError
Link to this section Summary
Functions
maybe_ast_escape/1 escapes (Macro.escape/1) any value other than a module attribute or an existing ast (i.e. Macro.validate/1 returns :ok)
Takes a maybe quoted value and returns the realised value
Takes a maybe quoted value, realises it and, if a function, returns
{:ok, function}. Anything else returns :error
Takes a maybe quoted value, realises it using
maybe_ast_realise_function/1, and, if {:ok, function}, returns the
function, else raises a BadFunctionError exception
Takes a maybe quoted value, realises it and, if a Map, returns
{:ok, map}
Takes a maybe quoted value, realises it using
maybe_ast_realise_map/1, and if the result is {:ok, map}, returns the map,
else raises a BadMapError exception
Takes a maybe quoted value, realises it and, if a compiled module, returns {:ok, module}
Takes a maybe quoted value, realises it using
maybe_ast_realise_module/1, and, if {:ok, module}, returns the
module, else raises a ArgumentError exception
Takes a maybe quoted value, realises it and, if a tuple, returns {:ok, tuple}
Takes a maybe quoted value, realises it using
maybe_ast_realise_tuple/1, and if the result is {:ok, tuple}, returns the tuple,
else raises an ArgumentError exception
Takes a maybe quoted value and returns the realised value as {:ok, value}
Takes a maybe quoted value, realises it and, if a function, returns
{:ok, function}
Takes a maybe quoted value, realises it using
maybe_form_realise_function/1, and, if {:ok, function}, returns the
function, else raises error in {:error, error}
Takes a maybe quoted value, realises it and, if a Map, returns
{:ok, map}. Otherwise {:error, error} where error will be a BadMapError
Takes a maybe quoted value, realises it using
maybe_form_realise_map/1, and if the result is {:ok, map}, returns the map,
else raises error in {:error, error}
Takes a maybe quoted value, realises it and, if a compiled module, returns {:ok, module}
Takes a maybe quoted value, realises it using
maybe_form_realise_module/1, and, if {:ok, module}, returns the
module, else raises error in {:error, error}
Takes a maybe quoted value, realises it and, if a tuple, returns {:ok, tuple}
Takes a maybe quoted value, realises it using
maybe_form_realise_tuple/1, and if the result is {:ok, tuple}, returns the tuple,
else raises an ArgumentError exception
Link to this section Types
error() :: %ArgumentError{__exception__: term(), message: term()}
Link to this section Functions
maybe_ast_escape/1 escapes (Macro.escape/1) any value other than a module attribute or an existing ast (i.e. Macro.validate/1 returns :ok)
Examples
iex> 42 |> maybe_ast_escape
42
iex> :two |> maybe_ast_escape
:two
iex> %{a: 1} |> maybe_ast_escape
{:%{}, [], [a: 1]}
iex> %{a: 1} |> Macro.escape |> maybe_ast_escape
{:%{}, [], [a: 1]}
iex> [1, %{b: 2}, {:c, 2, :tre}] |> maybe_ast_escape
[1, {:%{}, [], [b: 2]}, {:{}, [], [:c, 2, :tre]}]
iex> [1, %{b: 2}, {:c, 2, :tre}] |> Macro.escape |> maybe_ast_escape
[1, {:%{}, [], [b: 2]}, {:{}, [], [:c, 2, :tre]}]
Takes a maybe quoted value and returns the realised value.
Realisation in this context means extracting the underlying (“unquoted”) value.
Examples
iex> 1 |> maybe_ast_realise
1
iex> :atom |> maybe_ast_realise
:atom
iex> "string" |> maybe_ast_realise
"string"
iex> [1, :atom, "string"] |> maybe_ast_realise
[1, :atom, "string"]
iex> {:x, 42} |> maybe_ast_realise
{:x, 42}
iex> ast = {:x, 42} |> Macro.escape
...> ast |> maybe_ast_realise
{:x, 42}
iex> %{a: 1, b: 2, c: 3} |> maybe_ast_realise
%{a: 1, b: 2, c: 3}
iex> ast = %{a: 1, b: 2, c: 3} |> Macro.escape
...> ast |> maybe_ast_realise
%{a: 1, b: 2, c: 3}
iex> fun = fn x -> x + 5 end
...> fun = fun |> maybe_ast_realise
...> 42 |> fun.()
47
iex> ast = "fn x -> x + 5 end" |> Code.string_to_quoted!
...> fun = ast |> maybe_ast_realise
...> 42 |> fun.()
47
A map’s keys and values are recursively realised:
iex> ast = %{a: %{a1: 1}, b: %{b21: 21, b22: 22}, c: 3} |> Macro.escape
iex> ast |> maybe_ast_realise
%{a: %{a1: 1}, b: %{b21: 21, b22: 22}, c: 3}
The elements of a tuple are recursively realised:
iex> ast = [{:x, 2, [1,2,3], %{a: %{a1: 1}, b: %{b21: 21, b22: 22}, c: 3}}] |> Macro.escape
iex> ast |> maybe_ast_realise
[{:x, 2, [1,2,3], %{a: %{a1: 1}, b: %{b21: 21, b22: 22}, c: 3}}]
The elements of a list are recursively realised:
iex> ast = [{:x,:y,:z}, [1,2,3], %{a: %{a1: 1}, b: %{b21: 21, b22: 22}, c: 3}] |> Macro.escape
iex> ast |> maybe_ast_realise
[{:x,:y,:z}, [1,2,3], %{a: %{a1: 1}, b: %{b21: 21, b22: 22}, c: 3}]
maybe_ast_realise_function(any()) :: {:ok, (... -> any())} | :error
Takes a maybe quoted value, realises it and, if a function, returns
{:ok, function}. Anything else returns :error.
iex> fun = fn x -> x end
...> result = fun |> maybe_ast_realise_function
...> match?({:ok, ^fun}, result)
true
iex> quoted_fun = quote(do: fn x -> x end)
...> {:ok, fun} = quoted_fun |> maybe_ast_realise_function
...> is_function(fun, 1)
true
iex> 42 |> maybe_ast_realise_function
:error
iex> {:x, 42} |> Macro.escape
...> |> maybe_ast_realise_function
:error
maybe_ast_realise_function!(any()) :: (... -> any()) | no_return()
Takes a maybe quoted value, realises it using
maybe_ast_realise_function/1, and, if {:ok, function}, returns the
function, else raises a BadFunctionError exception.
iex> fun = fn x -> x end
...> result = fun |> maybe_ast_realise_function!
...> match?(^fun, result)
true
iex> quoted_fun = quote(do: fn x -> x end)
...> fun = quoted_fun |> maybe_ast_realise_function!
...> is_function(fun, 1)
true
iex> 42 |> maybe_ast_realise_function!
** (BadFunctionError) expected a function, got: :error
iex> {:x, 42}
...> |> Macro.escape
...> |> maybe_ast_realise_function!
** (BadFunctionError) expected a function, got: :error
maybe_ast_realise_map(any()) :: {:ok, map()} | :error
Takes a maybe quoted value, realises it and, if a Map, returns
{:ok, map}.
If the realised value is a Keyword, its is converted to a map and
{:ok, map} returned.
Anything else returns :error.
The keys and values are recursively realised.
iex> %{a: 1, b: %{b21: 21, b22: 22}, c: 3} |> maybe_ast_realise_map
{:ok, %{a: 1, b: %{b21: 21, b22: 22}, c: 3}}
iex> ast = %{a: 1, b: %{b21: 21, b22: 22}, c: 3} |> Macro.escape
iex> ast |> maybe_ast_realise_map
{:ok, %{a: 1, b: %{b21: 21, b22: 22}, c: 3}}
iex> 42 |> maybe_ast_realise_map
:error
iex> ast = {:x, 42} |> Macro.escape
iex> ast |> maybe_ast_realise_map
:error
maybe_ast_realise_map!(any()) :: map() | no_return()
Takes a maybe quoted value, realises it using
maybe_ast_realise_map/1, and if the result is {:ok, map}, returns the map,
else raises a BadMapError exception.
iex> %{a: 1, b: %{b21: 21, b22: 22}, c: 3} |> maybe_ast_realise_map!
%{a: 1, b: %{b21: 21, b22: 22}, c: 3}
iex> ast = %{a: 1, b: %{b21: 21, b22: 22}, c: 3} |> Macro.escape
iex> ast |> maybe_ast_realise_map!
%{a: 1, b: %{b21: 21, b22: 22}, c: 3}
iex> 42 |> maybe_ast_realise_map!
** (BadMapError) expected a map, got: :error
iex> ast = {:x, 42} |> Macro.escape
iex> ast |> maybe_ast_realise_map!
** (BadMapError) expected a map, got: :error
maybe_ast_realise_module(any()) :: {:ok, atom()} | :error
Takes a maybe quoted value, realises it and, if a compiled module, returns {:ok, module}.
Tests whether the module’s __info__ function works to confirm an actual module.
Anything else returns :error.
iex> mod = (defmodule XYZ1, do: nil) |> elem(1)
...> result = mod |> maybe_ast_realise_module
...> match?({:ok, ^mod}, result)
true
iex> mod = (defmodule XYZ2, do: nil) |> elem(1)
...> quoted_mod = mod |> Macro.escape
...> result = quoted_mod |> maybe_ast_realise_module
...> match?({:ok, ^mod}, result)
true
iex> 42 |> maybe_ast_realise_module
:error
iex> {:x, 42}
...> |> Macro.escape
...> |> maybe_ast_realise_module
:error
maybe_ast_realise_module!(any()) :: atom() | no_return()
Takes a maybe quoted value, realises it using
maybe_ast_realise_module/1, and, if {:ok, module}, returns the
module, else raises a ArgumentError exception.
iex> mod = (defmodule XYZ3, do: nil) |> elem(1)
...> result = mod |> maybe_ast_realise_module!
...> match?(^mod, result)
true
iex> mod = (defmodule XYZ4, do: nil) |> elem(1)
...> quoted_mod = mod |> Macro.escape
...> result = quoted_mod |> maybe_ast_realise_module!
...> match?(^mod, result)
true
iex> :an_atom_but_not_a_module |> maybe_ast_realise_module!
** (ArgumentError) expected a module, got: :error
iex> 42 |> maybe_ast_realise_module!
** (ArgumentError) expected a module, got: :error
iex> {:x, 42}
...> |> Macro.escape
...> |> maybe_ast_realise_module!
** (ArgumentError) expected a module, got: :error
maybe_ast_realise_tuple(any()) :: {:ok, tuple()} | :error
Takes a maybe quoted value, realises it and, if a tuple, returns {:ok, tuple}.
Anything else returns :error.
iex> {:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3} |> maybe_ast_realise_tuple
{:ok, {:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3}}
iex> {:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3}
...> |> Macro.escape
...> |> maybe_ast_realise_tuple
{:ok, {:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3}}
iex> 42 |> maybe_ast_realise_tuple
:error
iex> %{x: 42}
...> |> Macro.escape
...> |> maybe_ast_realise_tuple
:error
maybe_ast_realise_tuple!(any()) :: tuple() | no_return()
Takes a maybe quoted value, realises it using
maybe_ast_realise_tuple/1, and if the result is {:ok, tuple}, returns the tuple,
else raises an ArgumentError exception.
iex> {:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3} |> maybe_ast_realise_tuple!
{:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3}
iex> {:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3}
...> |> Macro.escape
...> |> maybe_ast_realise_tuple!
{:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3}
iex> 42 |> maybe_ast_realise_tuple!
** (ArgumentError) expected a tuple, got: :error
iex> %{x: 42}
...> |> Macro.escape
...> |> maybe_ast_realise_tuple!
** (ArgumentError) expected a tuple, got: :error
maybe_form_realise(any()) :: {:ok, any()} | {:error, error()}
Takes a maybe quoted value and returns the realised value as {:ok, value}.
Otherwise {:error, error} is returned.
Realisation in this context means extracting the underlying (“unquoted”) value.
Examples
iex> 1 |> maybe_form_realise
{:ok, 1}
iex> :atom |> maybe_form_realise
{:ok, :atom}
iex> "string" |> maybe_form_realise
{:ok, "string"}
iex> [1, :atom, "string"] |> maybe_form_realise
{:ok, [1, :atom, "string"]}
iex> {:x, 42} |> maybe_form_realise
{:ok, {:x, 42}}
iex> ast = {:x, 42} |> Macro.escape
...> ast |> maybe_form_realise
{:ok, {:x, 42}}
iex> %{a: 1, b: 2, c: 3} |> maybe_form_realise
{:ok, %{a: 1, b: 2, c: 3}}
iex> ast = %{a: 1, b: 2, c: 3} |> Macro.escape
...> ast |> maybe_form_realise
{:ok, %{a: 1, b: 2, c: 3}}
iex> fun = fn x -> x + 5 end
...> {:ok, fun} = fun |> maybe_form_realise
...> 42 |> fun.()
47
iex> ast = "fn x -> x + 5 end" |> Code.string_to_quoted!
...> {:ok, fun} = ast |> maybe_form_realise
...> 42 |> fun.()
47
A map’s keys and values are recursively realised:
iex> ast = %{a: %{a1: 1}, b: %{b21: 21, b22: 22}, c: 3} |> Macro.escape
iex> ast |> maybe_form_realise
{:ok, %{a: %{a1: 1}, b: %{b21: 21, b22: 22}, c: 3}}
The elements of a tuple are recursively realised:
iex> ast = [{:x, 2, [1,2,3], %{a: %{a1: 1}, b: %{b21: 21, b22: 22}, c: 3}}] |> Macro.escape
iex> ast |> maybe_form_realise
{:ok, [{:x, 2, [1,2,3], %{a: %{a1: 1}, b: %{b21: 21, b22: 22}, c: 3}}]}
The elements of a list are recursively realised:
iex> ast = [{:x,:y,:z}, [1,2,3], %{a: %{a1: 1}, b: %{b21: 21, b22: 22}, c: 3}] |> Macro.escape
iex> ast |> maybe_form_realise
{:ok, [{:x,:y,:z}, [1,2,3], %{a: %{a1: 1}, b: %{b21: 21, b22: 22}, c: 3}]}
maybe_form_realise_function(any()) ::
{:ok, (... -> any())} |
{:error, error()} |
{:error, %BadFunctionError{__exception__: term(), term: term()}}
Takes a maybe quoted value, realises it and, if a function, returns
{:ok, function}.
Anything else returns {:error, error} where error is a BadFunctionError.
iex> fun = fn x -> x end
...> result = fun |> maybe_form_realise_function
...> match?({:ok, ^fun}, result)
true
iex> quoted_fun = quote(do: fn x -> x end)
...> {:ok, fun} = quoted_fun |> maybe_form_realise_function
...> is_function(fun, 1)
true
iex> {:error, error} = 42 |> maybe_form_realise_function
...> match?(%BadFunctionError{term: 42}, error)
true
iex> {:error, error} = {:x, 42} |> Macro.escape
...> |> maybe_form_realise_function
...> match?(%BadFunctionError{term: {:x, 42}}, error)
true
maybe_form_realise_function!(any()) :: (... -> any()) | no_return()
Takes a maybe quoted value, realises it using
maybe_form_realise_function/1, and, if {:ok, function}, returns the
function, else raises error in {:error, error}.
iex> fun = fn x -> x end
...> result = fun |> maybe_form_realise_function!
...> match?(^fun, result)
true
iex> quoted_fun = quote(do: fn x -> x end)
...> fun = quoted_fun |> maybe_form_realise_function!
...> is_function(fun, 1)
true
iex> 42 |> maybe_form_realise_function!
** (BadFunctionError) expected a function, got: 42
iex> {:x, 42}
...> |> Macro.escape
...> |> maybe_form_realise_function!
** (BadFunctionError) expected a function, got: {:x, 42}
maybe_form_realise_map(any()) ::
{:ok, map()} |
{:error, error()} |
{:error, %BadMapError{__exception__: term(), term: term()}}
Takes a maybe quoted value, realises it and, if a Map, returns
{:ok, map}. Otherwise {:error, error} where error will be a BadMapError.
If the realised value is a Keyword, its is converted to a map and
{:ok, map} returned.
The keys and values are recursively realised.
iex> %{a: 1, b: %{b21: 21, b22: 22}, c: 3} |> maybe_form_realise_map
{:ok, %{a: 1, b: %{b21: 21, b22: 22}, c: 3}}
iex> ast = %{a: 1, b: %{b21: 21, b22: 22}, c: 3} |> Macro.escape
iex> ast |> maybe_form_realise_map
{:ok, %{a: 1, b: %{b21: 21, b22: 22}, c: 3}}
iex> 42 |> maybe_form_realise_map
{:error, %BadMapError{term: 42}}
iex> {:x, 42} |> Macro.escape |> maybe_form_realise_map
{:error, %BadMapError{term: Macro.escape({:x, 42})}}
maybe_form_realise_map!(any()) :: map() | no_return()
Takes a maybe quoted value, realises it using
maybe_form_realise_map/1, and if the result is {:ok, map}, returns the map,
else raises error in {:error, error}.
iex> %{a: 1, b: %{b21: 21, b22: 22}, c: 3} |> maybe_form_realise_map!
%{a: 1, b: %{b21: 21, b22: 22}, c: 3}
iex> ast = %{a: 1, b: %{b21: 21, b22: 22}, c: 3} |> Macro.escape
iex> ast |> maybe_form_realise_map!
%{a: 1, b: %{b21: 21, b22: 22}, c: 3}
iex> 42 |> maybe_form_realise_map!
** (BadMapError) expected a map, got: 42
iex> ast = {:x, 42} |> Macro.escape
iex> ast |> maybe_form_realise_map!
** (BadMapError) expected a map, got: {:x, 42}
maybe_form_realise_module(any()) :: {:ok, atom()} | {:error, error()}
Takes a maybe quoted value, realises it and, if a compiled module, returns {:ok, module}.
Tests whether the module’s __info__ function works to confirm an actual module.
Anything else returns {:error, error}.
iex> mod = (defmodule ABC1, do: nil) |> elem(1)
...> result = mod |> maybe_form_realise_module
...> match?({:ok, ^mod}, result)
true
iex> mod = (defmodule ABC2, do: nil) |> elem(1)
...> quoted_mod = mod |> Macro.escape
...> result = quoted_mod |> maybe_form_realise_module
...> match?({:ok, ^mod}, result)
true
iex> {:error, error} = 42 |> maybe_form_realise_module
...> match?(%ArgumentError{message: "expected a module; got: 42"}, error)
true
iex> {:error, error} = {:x, 42}
...> |> Macro.escape
...> |> maybe_form_realise_module
...> match?(%ArgumentError{message: "expected a module; got: {:x, 42}"}, error)
true
maybe_form_realise_module!(any()) :: atom() | no_return()
Takes a maybe quoted value, realises it using
maybe_form_realise_module/1, and, if {:ok, module}, returns the
module, else raises error in {:error, error}.
iex> mod = (defmodule ABC3, do: nil) |> elem(1)
...> result = mod |> maybe_form_realise_module!
...> match?(^mod, result)
true
iex> mod = (defmodule ABC, do: nil) |> elem(1)
...> quoted_mod = mod |> Macro.escape
...> result = quoted_mod |> maybe_form_realise_module!
...> match?(^mod, result)
true
iex> :an_atom_but_not_a_module |> maybe_form_realise_module!
** (ArgumentError) expected a module; got: :an_atom_but_not_a_module
iex> 42 |> maybe_form_realise_module!
** (ArgumentError) expected a module; got: 42
iex> {:x, 42}
...> |> Macro.escape
...> |> maybe_form_realise_module!
** (ArgumentError) expected a module; got: {:x, 42}
maybe_form_realise_tuple(any()) :: {:ok, tuple()} | {:error, error()}
Takes a maybe quoted value, realises it and, if a tuple, returns {:ok, tuple}.
Anything else returns {:error, error}.
iex> {:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3} |> maybe_form_realise_tuple
{:ok, {:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3}}
iex> {:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3}
...> |> Macro.escape
...> |> maybe_form_realise_tuple
{:ok, {:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3}}
iex> {:error, error} = 42 |> maybe_form_realise_tuple
...> match?(%ArgumentError{message: "expected a tuple; got: 42"}, error)
true
iex> {:error, error} = %{x: 42}
...> |> Macro.escape
...> |> maybe_form_realise_tuple
...> match?(%ArgumentError{message: "expected a tuple; got: %{x: 42}"}, error)
true
maybe_form_realise_tuple!(any()) :: tuple() | no_return()
Takes a maybe quoted value, realises it using
maybe_form_realise_tuple/1, and if the result is {:ok, tuple}, returns the tuple,
else raises an ArgumentError exception.
iex> {:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3} |> maybe_form_realise_tuple!
{:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3}
iex> {:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3}
...> |> Macro.escape
...> |> maybe_form_realise_tuple!
{:one, 1, %{"two1" => 21, :two2 => 22}, "tre", 3}
iex> 42 |> maybe_form_realise_tuple!
** (ArgumentError) expected a tuple; got: 42
iex> %{x: 42}
...> |> Macro.escape
...> |> maybe_form_realise_tuple!
** (ArgumentError) expected a tuple; got: %{x: 42}