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

Three-valued logic: conjunction, disjunction, and negation (DMN 1.6, section
10.3.2.4 and Tables 51 and 52).

The operations are total. An operand is `true`, `false`, or "otherwise", which
means any other value, `null` included:

| a         | b         | a and b | a or b |
| --------- | --------- | ------- | ------ |
| true      | true      | true    | true   |
| true      | false     | false   | true   |
| true      | otherwise | null    | true   |
| false     | true      | false   | true   |
| false     | false     | false   | false  |
| false     | otherwise | false   | null   |
| otherwise | true      | null    | true   |
| otherwise | false     | false   | null   |
| otherwise | otherwise | null    | null   |

`not` is `true` for `false`, `false` for `true`, and `null` otherwise. The result
does not depend on the order of the operands, so a chain `a and b and c` has one
value however it is grouped. A `false` decides a conjunction and a `true` decides
a disjunction whatever the other operand is, an error included.

A result of `null` is not an error of `and` and `or`: the tables give `null` for an operand that is
neither a boolean nor `null` too, as in `true and "x"`, and the TCK flags none of the cases of
`0064` and `0065` (D-103). It is one of `not` for a value that is neither a boolean nor `null`, which is a
call of a function with an argument out of its domain (`0066#003_b` to `#003_d`).

The functions are named after the tables because `and`, `or`, and `not` are
Elixir operators.

# `conjunction`

```elixir
@spec conjunction(Feel.Value.t(), Feel.Value.t()) :: Feel.Runtime.Env.outcome()
```

Returns the conjunction of two values.

    iex> Feel.Runtime.Logic.conjunction(true, false)
    {:ok, false}
    iex> Feel.Runtime.Logic.conjunction(false, nil)
    {:ok, false}
    iex> Feel.Runtime.Logic.conjunction(true, nil)
    :missing

# `disjunction`

```elixir
@spec disjunction(Feel.Value.t(), Feel.Value.t()) :: Feel.Runtime.Env.outcome()
```

Returns the disjunction of two values.

    iex> Feel.Runtime.Logic.disjunction(nil, true)
    {:ok, true}
    iex> Feel.Runtime.Logic.disjunction(false, false)
    {:ok, false}
    iex> Feel.Runtime.Logic.disjunction(false, "x")
    :missing

# `negation`

```elixir
@spec negation(Feel.Value.t()) :: Feel.Runtime.Env.outcome()
```

Returns the negation of a value.

    iex> Feel.Runtime.Logic.negation(true)
    {:ok, false}
    iex> Feel.Runtime.Logic.negation(nil)
    :missing

---

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