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

A prepared FEEL expression.

`Feel.prepare/2` returns one. It holds everything that does not depend on the
data: the syntax tree, the resolved form that `Feel.run/3` executes, the names
the expression reads, its inferred type, and the diagnostics found while
preparing it. Preparing once and running many times avoids repeating that work
on every call.

Preparation options are retained internally so `Feel.Recursion` can prepare members with evidence about the
single-signature links it constructs, while keeping the caller's analysis, declaration and optimization settings.

Treat the struct as opaque and read it through the functions of this module.

# `dialect`

```elixir
@type dialect() :: Feel.Dialect.t()
```

# `entry`

```elixir
@type entry() :: :expression | :unary_tests
```

# `t`

```elixir
@type t() :: %Feel.Expression{
  ast: Feel.AST.t() | nil,
  backend: atom() | nil,
  diagnostics: [Feel.Diagnostic.t()],
  dialect: dialect(),
  entry: entry(),
  executable: term(),
  extensions: Feel.Extensions.t(),
  free_names: MapSet.t(Feel.Name.t()),
  ir: Feel.IR.t() | nil,
  linked_peers: [Feel.Name.t()],
  preparation: keyword() | nil,
  source: String.t(),
  type: Feel.Type.t(),
  unoptimized_ir: Feel.IR.t() | nil
}
```

# `ast`

```elixir
@spec ast(t()) :: Feel.AST.t() | nil
```

Returns the syntax tree.

# `diagnostics`

```elixir
@spec diagnostics(t()) :: [Feel.Diagnostic.t()]
```

Returns the diagnostics found while preparing the expression.

# `dialect`

```elixir
@spec dialect(t()) :: dialect()
```

Returns the FEEL dialect the expression was prepared with.

# `entry`

```elixir
@spec entry(t()) :: entry()
```

Returns the grammar entry point the expression was prepared with.

# `extensions`

```elixir
@spec extensions(t()) :: [module()]
```

Returns the extensions the expression was prepared with (`Feel.Extension`, D-81), as the modules that
implement them. Every run of the expression has them.

# `free_names`

```elixir
@spec free_names(t()) :: MapSet.t(Feel.Name.t())
```

Returns the names the expression reads from its bindings.

# `source`

```elixir
@spec source(t()) :: String.t()
```

Returns the source text the expression was prepared from.

# `type`

```elixir
@spec type(t()) :: Feel.Type.t()
```

Returns the inferred result type, or `:any` when it cannot be determined statically.

# `unoptimized_ir`

```elixir
@spec unoptimized_ir(t()) :: Feel.IR.t() | nil
```

Returns the IR as the analyzer made it, before `Feel.Optimizer`: the `:ir` field is the one the
backend compiled, and is the same when the expression was prepared with `optimize: false`.

---

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