# `Otera.Scope`
[🔗](https://github.com/georgeguimaraes/otera/blob/v0.2.0/lib/otera/scope.ex#L1)

The static scopes of Jinja2, from its `idtracking` module.

Jinja2 compiles each scope of a template to the local variables of a Python function: the root of the template, a block, a macro, a `caller`, the body of a loop, a with block and others. At the start of a scope, each name that the scope sets before it reads it starts as missing, also when the render has a variable with that name. A loop that reads `x` before a later top-level `{% set x = 1 %}` sees `x` as undefined. At the end of a scope that is not a function, such as a loop, its names become missing again, which a macro that the scope defined can see.

`annotate/1` analyzes the scopes of a syntax tree like Jinja2, and gives each node that opens a scope its `t:t/0`. The evaluator applies them.

# `t`

```elixir
@type t() :: %{
  unset: [String.t()],
  exit: %{required(String.t()) =&gt; :missing | :unset},
  self: boolean(),
  super: boolean(),
  captured: boolean()
}
```

`unset` lists the names that are missing at the start of the scope. `exit` gives the value of each name of the scope after the scope ends: `:missing` for a parameter, such as the target of a loop, which prints as `missing`, and `:unset` for the others, which are undefined.

`self` is true when the root of a template or a block reads `self`, and `super` when a block reads `super`, which Jinja2 then sets at the start of the scope. `captured` is true when the scope defines a macro or a call block, which can read the scope after it ends.

# `annotate`

```elixir
@spec annotate(list()) :: {list(), t()}
```

Returns the syntax tree with the scope of each node that opens one, and the scope of the root.

---

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