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

The conversion of bound values to the types that were declared for them (D-138).

A `Feel.Scope` says what type each name has. When a run starts, `Feel.Analysis.Analyzer`'s
`:conform_bindings` node has each value that is bound to a name the expression reads
converted to its declared type by the implicit conversions of DMN 1.6, section 10.3.2.9.4, and
verified to conform to it, as the result is (`Feel.Runtime.ResultType`, D-138). A backend calls
`conform_bindings/3`. It is a function of the runtime, and not a part of a backend, because
generated code may call only `Feel.Runtime` and both backends have to give the same result.

  * `null` conforms to every type, and is the value as it is. So does a name that is not bound,
    which is left for its read to report. A type marked `!` (D-48) is the exception: `null`
    does not conform to `number!`, and neither does a name that has no value. In the mode
    `:enforce` that ends the run with an error of kind `:input`, in either mode of the run, because
    the type says that the value is there and the expression was analyzed on it. In the mode
    `{:report, severity}` it is reported with that severity and the value stays.
  * A value that conforms is the value. One that does after a conversion is converted
    (`Feel.Type.Conversion.convert/3`: conformance first, then a singleton list is unwrapped, a
    value is wrapped in a list, a date becomes a date and time), and the conversion is reported
    as an `:info` (`:implicit_conversion`, D-46), which does not end a strict run.
  * A value that cannot be made to conform is `null`, with an error (`:type_mismatch`) that ends
    a run in strict mode. For a type marked `!` it cannot be `null` either, so it ends the run
    with an error of kind `:input`, as a `null` does.

This is what lets the type of a name be relied on: every read sees a value of its type, or
`null`. That is the mode `:enforce`. In the mode `{:report, severity}` (D-138) nothing is
converted and nothing becomes `null`: a value that does not conform as it is gets a
`:type_mismatch` diagnostic with that severity, and stays. The type is then an assertion of the
caller's, and the report says when it does not hold.

# `mode`

```elixir
@type mode() :: :enforce | {:report, :error | :warning}
```

What is done with a value that does not conform: `:enforce` converts it or makes it `null`, and
`{:report, severity}` leaves it and reports it with that severity (D-138).

# `conform_bindings`

```elixir
@spec conform_bindings(
  Feel.Runtime.Env.t(),
  Feel.bindings(),
  [{Feel.Name.t(), Feel.Diagnostic.span(), Feel.Type.t()}],
  mode()
) :: {Feel.bindings(), Feel.Runtime.Env.t()}
```

Converts the bound values of the names in `conforms` to their types.

Each entry is the canonical name, the span of its first read in the expression, which goes on the
error, and the declared type, with the names of types resolved. Returns the bindings that the
expression is to run with, and the environment. `mode` is `:enforce`, the default, or
`{:report, severity}`.

    iex> env = Feel.Runtime.Env.new()
    iex> conforms = [{"age", {0, 3}, :number}, {"tags", {4, 8}, {:list, :string}}]
    iex> bindings = %{"age" => [Decimal.new(30)], "tags" => "a", "id" => 7}
    iex> {converted, converted_env} = Feel.Runtime.BindingTypes.conform_bindings(env, bindings, conforms)
    iex> converted
    %{"age" => Decimal.new(30), "tags" => ["a"], "id" => 7}
    iex> for d <- Feel.Runtime.Env.diagnostics(converted_env), do: {d.severity, d.code, d.span}
    [{:info, :implicit_conversion, {0, 3}}, {:info, :implicit_conversion, {4, 8}}]
    iex> {converted, env} = Feel.Runtime.BindingTypes.conform_bindings(env, %{"age" => "x"}, conforms)
    iex> converted
    %{"age" => nil}
    iex> [diagnostic] = Feel.Runtime.Env.diagnostics(env)
    iex> {diagnostic.code, diagnostic.span, diagnostic.message}
    {:type_mismatch, {0, 3}, "the value of \"age\" is a string, which cannot be converted to the declared type number"}

---

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