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

What the analyzer knows of a decision table that does not need the analyzer: whether the node is a table at all, and the type of
its result (DMN 1.6, clause 8, 10.3.2.10; the node is described in `Feel.AST`).

## The shape

A table has a hit policy, an aggregation for `:collect` only, and one to many outputs; an output has a name if there are
several. Every rule has one entry for each input (`nil` for `-`) and one output entry for each output. A table that is not so is
not one that a run could make sense of, and it is an error of the analysis, `:invalid_decision_table`, whoever built it.

## The type of the result

A table is `null` when no rule counts and there is no default output, and when its hit policy is broken (the unique policy with
several rules, the any policy with different outputs, an output that is not among the output values), so `null` is always
in the type. The rest follows from the outputs, which are the types of the output entries of all the rules and the default:

| Policy | Type |
| ------ | ---- |
| `:unique`, `:first`, `:any`, `:priority` | the output |
| `:output_order`, `:rule_order`, `:collect` | a list of the output, or the default (which is not in a list) |
| `:collect` with `:count` | a number |
| `:collect` with `:sum` | a number if all the outputs are, else anything |
| `:collect` with `:min`, `:max` | the output |

The output of a table of several outputs is a context of them, closed, with the type of each output for the entry of its name.

# `result_type`

```elixir
@spec result_type(atom(), atom() | nil, [String.t() | nil], [[Feel.Type.Union.t()]], [
  Feel.Type.Union.t() | nil
]) :: Feel.Type.Union.t()
```

The type of the result of a table.

`rule_outputs` are the types of the output entries of each rule (one union for each output), `defaults` the type of the default
output entry of each output, or `nil`.

# `validate`

```elixir
@spec validate(Feel.Diagnostic.span(), atom(), atom() | nil, list(), list(), list()) ::
  :ok | {:error, [Feel.Diagnostic.t(), ...]}
```

Checks the shape of a table: the policy and the aggregation, and the numbers of entries and outputs.

Returns `:ok` or the diagnostics, all with the code `:invalid_decision_table`, at the span of the node.

---

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