Packages
bond
1.5.0
1.13.0
1.12.0
1.11.0
1.10.1
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.3.0-rc.1
1.2.1
1.2.0
1.1.0
1.0.0
1.0.0-rc.4
1.0.0-rc.3
1.0.0-rc.2
1.0.0-rc.1
0.18.0
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.2
0.16.1
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.1
0.9.0
0.8.3
0.8.2
0.8.1
0.1.0
Design by Contract (DbC) for Elixir
Current section
Files
Jump to
Current section
Files
lib/bond/compiler/function_definition.ex
defmodule Bond.Compiler.FunctionDefinition do
@moduledoc internal: true
@moduledoc """
Struct containing information about a function definition at compile time.
This struct represents a single `def` or `defp` at compile time, so there will be separate
instances of the struct for each clause of a multi-clause function.
"""
defstruct env: nil,
kind: nil,
module: nil,
fun: nil,
arity: nil,
params: nil,
guards: nil,
body: nil,
warn_skipped_invariants_override: nil,
external_override?: false
@type doc_attribute_value :: String.t() | Keyword.t()
@type doc_attribute :: {meta :: Keyword.t(), value :: doc_attribute_value()}
@type kind :: :def | :defp
@type function_parameters :: list()
@type function_guards :: list()
@type function_body :: list() | nil
@type clause :: {Macro.Env.t(), function_parameters(), function_guards(), function_body()}
@type t :: %__MODULE__{
env: Macro.Env.t(),
kind: kind(),
module: module(),
fun: atom(),
params: list(),
guards: list(),
body: list() | nil,
warn_skipped_invariants_override: nil | boolean(),
external_override?: boolean()
}
@spec new(
env :: Macro.Env.t(),
kind :: kind(),
fun :: atom(),
params :: list(),
guards :: list(),
body :: list() | nil
) :: t()
def new(%Macro.Env{} = env, kind, fun, params, guards, body) when kind in [:def, :defp] do
%__MODULE__{
env: env,
kind: kind,
module: env.module,
fun: fun,
arity: length(params),
params: params,
guards: guards,
body: body
}
end
def mfa(%__MODULE__{module: module, fun: function, params: params}) do
{module, function, length(params)}
end
def mfa(_), do: nil
@doc """
Records the per-function `@bond_warn_skipped_invariants` override captured at
`__on_definition__` time. `nil` means no override was set; `true`/`false`
overrides the module/global config for this single function.
"""
@spec put_warn_skipped_invariants_override(t(), nil | boolean()) :: t()
def put_warn_skipped_invariants_override(%__MODULE__{} = fd, override)
when override == nil or is_boolean(override) do
%{fd | warn_skipped_invariants_override: override}
end
@doc """
Records whether this clause was an externally-generated override at `__on_definition__`
time — i.e. the function was `defoverridable` and is now being redefined by another library
(Norm's `@contract`, the `decorator` library, etc.). Such clauses are wrappers, not user
contract sites; the FSM ignores them when they re-appear for an already-tracked function.
See `Bond.Compiler.__on_definition__/6` for how this is detected (`Module.overridable?/2`).
"""
@spec put_external_override(t(), boolean()) :: t()
def put_external_override(%__MODULE__{} = fd, external_override?)
when is_boolean(external_override?) do
%{fd | external_override?: external_override?}
end
@doc "Returns whether this clause was an externally-generated override (see `put_external_override/2`)."
@spec external_override?(t()) :: boolean()
def external_override?(%__MODULE__{external_override?: value}), do: value
end