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

Inspection for trusted fixtures; execution and monitoring run in the caller.
Use the ordinary `Feel` APIs for default containment of untrusted input.

The paranoid run (D-159): the proof that the analysis made of an expression, checked on the values of one run.

The analysis gives every node of the IR a type, and the optimizer takes out checks that those types make unneeded. A mistake in
a type is a wrong answer and not a missed warning, and the sweeps (`scripts/sweep/`) only look at the type of the root of an
expression. `run/3` runs the **IR as the analyzer made it** (`Feel.Expression.unoptimized_ir/1`, with nothing taken out) on the
interpreter, and for **every node** checks that the value it made is in its type with the exact `Feel.Type.Union.contains?/2`. It
also runs the expression as it is prepared (optimized, on its own backend) and checks that the value and the diagnostics are the same.

It returns the result and the violations: a node whose value is not in its type (`:type`), or an optimized run that gave another
result (`:optimizer`). A violation is a bug of the analysis or the optimizer. An empty list is no proof, and a run that has none
has shown that this input is not a counterexample.

It runs at the speed of the interpreter and of a check at each node, so it is for tests and for finding out why an answer is
wrong. Nothing else reads the monitor: it is told by `Feel.Backend.Interpreter.Monitored`, a walk of the nodes of its own, so a run
without one (`Feel.Backend.Interpreter.Plain`) pays nothing for it (D-159).

    iex> {:ok, expression} = Feel.prepare("for x in [1, 2, 3] return x * 2")
    iex> {{:ok, _value, []}, []} = Feel.Paranoid.run(expression)

# `violation`

```elixir
@type violation() ::
  %{
    kind: :type,
    node: atom(),
    span: Feel.Diagnostic.span() | nil,
    type: Feel.Type.Union.t(),
    value: term()
  }
  | %{
      kind: :grain,
      node: atom(),
      span: Feel.Diagnostic.span() | nil,
      grain: integer(),
      value: Decimal.t()
    }
  | %{kind: :optimizer, optimized: term(), unoptimized: term()}
```

A node whose value is not in its type, or is not a multiple of the grain the node says it has (D-161), or an optimized run
that disagrees with the one without the optimizer.

# `run`

```elixir
@spec run(Feel.Expression.t(), Feel.bindings(), [Feel.run_option()]) ::
  {Feel.result(Feel.Value.t()), [violation()]}
```

Runs a prepared expression as the interpreter runs the IR the analyzer made, and returns the result with the violations.

Takes the bindings and the run options of `Feel.run/3`.

# `same?`

```elixir
@spec same?(Feel.result(Feel.Value.t()), Feel.result(Feel.Value.t())) :: boolean()
```

Whether two results of `Feel.run/3` are the same: the same value (a number at any scale is the same number, a function of FEEL is
the same when its parameters and its result type are) and matching diagnostics, or the same error.
Diagnostic fields are compared recursively, using value equality for embedded numbers and functions.
Function comparison checks signature metadata, not behavior; test returned functions by calling them.
The optimized run and the run of the IR as the analyzer made it are held to this; so is any other pair of runs of one expression.

    iex> Feel.Paranoid.same?({:ok, Decimal.new("4.0"), []}, {:ok, Decimal.new("4"), []})
    true
    iex> Feel.Paranoid.same?({:ok, Decimal.new("4"), []}, {:ok, nil, []})
    false

---

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