Current section
Files
Jump to
Current section
Files
lib/understated.ex
defmodule Understated do
alias Understated.Transition
defmacro __using__(_options) do
quote do
import Understated.Machine
import Understated.State
import Understated.Transition
import Understated.Entry
Module.register_attribute(__MODULE__, :transitions, accumulate: true)
Module.register_attribute(__MODULE__, :states, accumulate: true)
Module.register_attribute(__MODULE__, :current_state, accumulate: false)
@current_state ""
@before_compile unquote(__MODULE__)
end
end
defmacro __before_compile__(%{module: module} = _env) do
transitions = Module.get_attribute(module, :transitions, [])
transitions_ast =
transitions
|> Enum.map(fn {state, to, _on} ->
quote do
unquote(Transition.__compile_transitions(state, to))
end
end)
handlers_ast =
transitions
|> Enum.map(fn {state, to, on} ->
quote do
unquote(Transition.__compile_event_handlers(state, to, on))
end
end)
events_ast =
transitions
|> Enum.uniq_by(fn {_state, _to, on} -> on end)
|> Enum.map(fn {_, _, on} ->
quote do
unquote(Transition.__compile_event(on))
end
end)
quote do
def valid_states() do
@states
|> Enum.reverse()
end
def valid_transitions() do
@transitions
end
unquote(transitions_ast)
unquote(handlers_ast)
unquote(events_ast)
def before_event(machine, _from, _to), do: machine
def after_event(machine, _from, _to), do: machine
def enter_state(machine, _from_state), do: machine
def trigger(%__MODULE{} = machine, _to_state) do
{:error, "Invalid event for current state", machine}
end
defp apply_state(%__MODULE__{} = machine, _state) do
{:error, "Invalid transition", machine}
end
end
end
end