# `Feel.Extensions`
[🔗](https://github.com/FeeJai/BDM/blob/feel-v0.1.0/apps/feel/lib/feel/extensions.ex#L1)

The extensions that are on for an expression, resolved (D-81).

`Feel.prepare/2` turns its `:extensions` option into this once, and every stage that has to decide
something asks it: the parser which words are a function name, the analyzer which functions there are and
which signatures they have, and a run which function to call. It is part of the prepared expression and of
its executable, and a run cannot change it, as with the dialect (D-49).

`new/1` checks what is given:

  * a name is one of `Feel.Extension.registry/0`; anything else that is an atom is a module that
    implements `Feel.Extension`;
  * a function of `c:Feel.Extension.functions/0` has a name that DMN 1.6 does not, and that no other
    extension defines;
  * an overload of `c:Feel.Extension.overloads/0` has the name of a function of DMN 1.6.

It raises `ArgumentError` otherwise: a wrong extension is a mistake of the caller, found when the expression
is prepared and not when it runs.

The signatures of everything an extension adds carry `extension: true`. The analyzer reads it to mark a
call that an extension may answer in its metadata (`Feel.IR`): the analyzer and the optimizer fold such a call with
the extensions of the expression, and `Feel.Analysis.Analyzer` does not fold it as one of DMN 1.6, which it would
take for an error (D-45).

    iex> Feel.Extensions.none() == Feel.Extensions.new([])
    true

# `t`

```elixir
@type t() :: %Feel.Extensions{
  data_only: boolean(),
  functions: %{optional(Feel.Name.t()) =&gt; Feel.Builtin.Function.t()},
  modules: [module()],
  overloads: %{optional(Feel.Name.t()) =&gt; [Feel.Builtin.Function.t()]},
  temporal: [module()]
}
```

# `data_only?`

```elixir
@spec data_only?(t() | [atom()]) :: boolean()
```

Returns `true` when every extension in the set says it adds data only (`c:Feel.Extension.data_only?/0`); so does an empty
set. For a resolved set this reads what `new/1` recorded and runs no extension code, so a host may ask it where nothing of
the extension may run (a caller that has not started its worker yet). For a list of names and modules, as `new/1` takes it,
the callbacks are called here, so ask where `new/1` could be called; something that is no extension is not data only.

# `function`

```elixir
@spec function(t(), Feel.Name.t()) :: {:ok, Feel.Builtin.Function.t()} | :error
```

Finds a function that an extension adds, by its name. A function of DMN 1.6 is never found here: its
overloads are `overloads/2`.

# `function?`

```elixir
@spec function?(t(), Feel.Name.t()) :: boolean()
```

Returns `true` when an extension adds a function of this name.

# `function_names`

```elixir
@spec function_names(t()) :: [Feel.Name.t()]
```

The names of the functions that the extensions add, which the parser needs to read a name of several
words as one.

# `lenient_temporal`

```elixir
@spec lenient_temporal(t(), String.t(), Feel.Value.Temporal.Spellings.parser()) ::
  {:ok, Feel.Value.Temporal.t(), String.t()} | :error
```

Reads the text of a time or a date and time as an extension spells it (`c:Feel.Extension.temporal_text/1`): the
first other spelling of `text`, in the order of the extensions, that `parse` reads. Returns the value and the text
that was read, and `:error` if no extension has a spelling that `parse` reads.

The caller has tried `parse` on `text`, and says what it read with `spelling_diagnostic/2`.

# `modules`

```elixir
@spec modules(t()) :: [module()]
```

The extensions, as modules, in the order they were given.

# `new`

```elixir
@spec new(t() | [atom()]) :: t()
```

Resolves a list of extension names and modules. An already resolved set is returned as it is, so every
function that takes the option can be given either.

# `none`

```elixir
@spec none() :: t()
```

No extension: DMN 1.6 and nothing else.

# `none?`

```elixir
@spec none?(t()) :: boolean()
```

Returns `true` when no extension is on.

# `overloads`

```elixir
@spec overloads(t(), Feel.Name.t()) :: [Feel.Builtin.Function.t()]
```

The overloads that the extensions add to the function of DMN 1.6 of this name, in the order of the extensions.

# `spelling_diagnostic`

```elixir
@spec spelling_diagnostic(String.t(), String.t()) :: Feel.Diagnostic.t()
```

The `:info` for a text that was read as another spelling (D-81), with the code `:temporal_spelling`. Its span is
the one of the operation that read it.

# `spells?`

```elixir
@spec spells?(t(), Feel.Name.t()) :: boolean()
```

Returns `true` when the function reads a text that an extension that is on may spell another way (D-81): a call of it
may give a value where DMN 1.6 gives `null`, so the analyzer marks the call (`Feel.IR`, `meta.extension`) and folds it
with the extensions, and not as a call of DMN 1.6 (D-45). `range` is one: the endpoints of its text are such texts.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
