# `Dmn.Compiled`
[🔗](https://github.com/FeeJai/BDM/blob/dmn-v0.1.0/apps/dmn/lib/dmn/compiled.ex#L1)

A compiled model: what `Dmn.compile/2` makes of a `Dmn.Model`, and what `Dmn.evaluate/4` runs.

It holds a **unit** for each DRG element (`Dmn.Compiler.Unit`): the prepared FEEL expression of a decision, or of a business knowledge model,
with its scope, source map and dependency metadata. The ordered plan is computed per request,
not stored on the reusable model. Sandbox preflight can pass its successful plan to execution
with the matching compact model; trusted calls and conservative fallbacks plan during execution.
Evaluating a decision runs each required unit once, without reanalyzing its prepared logic.
`Dmn.invoke/4` separately prepares a small call wrapper for the supplied arguments.

| Field | Is |
| ----- | -- |
| `model` | the `Dmn.Model` it was made from |
| `sources` | internal extra diagnostic origins for compact worker views with opaque callbacks; `nil` in ordinary models |
| `units` | the units by key |
| `names` | the canonical names of the decisions, business knowledge models and decision services, to their keys |
| `ambiguous` | the canonical names that more than one element of the model has, to the keys of those elements: they are not in `names`, and a call by one is an error (`:ambiguous_name`) |
| `imports` | which document each imported model is, by namespace: `%{location: where it was asked for, sha256: the hash of its bytes}` (`Dmn.Imports`) |
| `groups` | the recursion groups, by the key that names each (`Dmn.Compiler.Unit.group`), to the keys of their members: none unless `Dmn.compile/2` was told `recursion: true` |
| `diagnostics` | what the compiler found without data, `Dmn.Diagnostic`s |
| `feel_extensions` | the extensions of FEEL that the expressions were prepared with (`c:Dmn.Extension.feel_extensions/0`), which a call of a knowledge model from outside (`Dmn.invoke/4`) is prepared with too: a function resolves what it calls in the extensions of the expression that calls it |
| `feel_data_only` | whether every one of those extensions declared that it adds data only (the `data_only?` callback of `Feel.Extension`), asked once at compilation, where the extensions are protected, so that a call in a worker does not run extension code before its worker starts |
| `feel_limits` | the `Feel.Limits` the expressions were prepared within (`:feel_limits` of `Dmn.compile/2`), which a run keeps to unless it is given `:limits` of its own |

# `key`

```elixir
@type key() :: {Dmn.Compiler.Unit.kind(), String.t()}
```

# `t`

```elixir
@type t() :: %Dmn.Compiled{
  ambiguous: %{optional(String.t()) =&gt; [key()]},
  diagnostics: [Dmn.Diagnostic.t()],
  feel_data_only: boolean(),
  feel_extensions: [atom()],
  feel_limits: Feel.Limits.t(),
  groups: %{optional(key()) =&gt; [key(), ...]},
  imports: %{optional(String.t()) =&gt; Dmn.Imports.identity()},
  model: Dmn.Model.t() | nil,
  names: %{optional(String.t()) =&gt; key()},
  sources:
    %{optional(key()) =&gt; {Dmn.Compiler.Source.finished(), String.t()}} | nil,
  units: %{optional(key()) =&gt; Dmn.Compiler.Unit.t()}
}
```

# `errors`

```elixir
@spec errors(t()) :: [Dmn.Diagnostic.t()]
```

The diagnostics of the compile that are errors: what is wrong with the model whatever the data. A model with none can still have
warnings and infos; `Dmn.validate/1` is the gate that asks.

# `plan`

```elixir
@spec plan(t(), key()) :: [key()]
```

The keys of the units that running the element `key` needs, in the order to run them, it last.

A unit needs the units it reads. The requirements of a model are acyclic, which the compiler checked: a unit in a cycle has
no expression and reads nothing, so the walk ends. The exception is a **recursion group**, units of knowledge that read each
other (`Dmn.compile/2` with `recursion: true`): they are run together, after every unit that any of them reads outside the
group, since each is run with links to the others and not with their values (`Feel.Recursion`).

# `plan_all`

```elixir
@spec plan_all(t(), [key()]) :: [key()]
```

The combined dependency plan of several targets, visiting shared dependencies once.

# `validation_errors`

```elixir
@spec validation_errors(t()) :: [Dmn.Diagnostic.t()]
```

Errors that prevent admitting a model. Unresolved names are errors at this boundary,
even though lenient evaluation retains FEEL's warning-and-null behavior.

---

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