Packages
croma
0.9.1
0.13.0
0.12.0
0.11.3
0.11.2
0.11.1
0.11.0
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.3
0.7.2
0.7.1
0.7.0
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.1
0.5.0
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Elixir macro utilities to make type-based programming easier
Current section
Files
Jump to
Current section
Files
lib/croma/validation.ex
defmodule Croma.Validation do
@moduledoc """
Module for code generation of argument validation (see `Croma.Defun.defun/2`).
This module is intended for internal use.
"""
def make(type_expr, v, caller) do
ast = validation_expr(type_expr, v, caller)
{name, _, _} = v
type_string = Macro.to_string(type_expr)
quote bind_quoted: [name: name, ast: ast, type_string: type_string] do
case ast do
true -> nil
false -> raise "validation error: #{Atom.to_string(name)} is not a valid #{type_string}"
end
end
end
defp validation_expr(type_expr, v, caller) do
case type_expr do
a when is_atom(a) -> validation_expr_equal(v, a)
l when is_list(l) -> validation_expr_module(v, Croma.List)
{_, _} -> validation_expr_module(v, Croma.Tuple)
{:t, _, _} -> validation_expr_module(v, caller.module)
{:|, _, [t1, t2]} -> validation_expr_union(v, t1, t2, caller)
{{:., _, [mod_alias, :t]}, _, _} -> validation_expr_module(v, replace_elixir_type_module(mod_alias, caller))
{first, _, _} -> validation_expr_module(v, module_for(first, type_expr))
_ -> error(type_expr)
end
end
defp module_for(first, type_expr) do
case first do
:integer -> Croma.Integer
:pos_integer -> Croma.PosInteger
:neg_integer -> Croma.NeInteger
:non_neg_integer -> Croma.NonNegInteger
:boolean -> Croma.Boolean
:byte -> Croma.Byte
:char -> Croma.Char
:float -> Croma.Float
:number -> Croma.Number
:binary -> Croma.Binary
:bitstring -> Croma.BitString
:module -> Croma.Atom
:atom -> Croma.Atom
:node -> Croma.Atom
:fun -> Croma.Function
:pid -> Croma.Pid
:port -> Croma.Port
:reference -> Croma.Reference
:char_list -> Croma.List
:list -> Croma.List
:map -> Croma.Map
:tuple -> Croma.Tuple
:%{} -> Croma.Map
:{} -> Croma.Tuple
:<<>> -> Croma.BitString
_ -> error(type_expr)
end
end
defp validation_expr_module(v, mod) do
quote bind_quoted: [v: v, mod: mod] do
mod.valid?(v)
end
end
defp validation_expr_equal(v, value) do
quote bind_quoted: [v: v, value: value] do
v == value
end
end
defp validation_expr_union(v, t1, t2, caller) do
q1 = validation_expr(t1, v, caller)
q2 = validation_expr(t2, v, caller)
quote do
unquote(q1) || unquote(q2)
end
end
defp replace_elixir_type_module(mod_alias, caller) do
mod = Macro.expand(mod_alias, caller)
case mod do
String -> Croma.String
_ -> mod
end
end
defp error(type_expr) do
raise "cannot generate validation code for the given type: #{Macro.to_string(type_expr)}"
end
end