# `EEVM.Interpreter`
[🔗](https://github.com/mw2000/eevm/blob/main/lib/eevm/interpreter.ex#L1)

The EVM interpreter — fetches, decodes, and dispatches opcodes in a loop.

This is the core opcode-execution engine. It is invoked by `EEVM.Handler`
(the transaction-level pipeline) and by system contracts that need to
evaluate bytecode against an existing world state.

Execution ends when a terminating opcode is reached (STOP, RETURN, REVERT,
INVALID), the program counter advances past the end of the bytecode
(implicit STOP), or gas runs out before the opcode can execute. INVALID
(0xFE) is special-cased: its "base" gas cost is set to the entire
remaining gas, draining it completely before the opcode runs.

Opcode dispatch is data-driven via
`EEVM.Interpreter.Instructions.Registry`; opcode modules own their
semantics, and the interpreter only orchestrates.

# `run`

```elixir
@spec run(
  binary(),
  keyword()
) :: EEVM.Interpreter.MachineState.t()
```

Creates a `MachineState` from bytecode and options, then runs the execution loop.

## Options

- `:gas` — initial gas limit (default: 1_000_000)
- `:value` — ETH value sent with the call, in wei
- `:code` — contract bytecode (usually the same as the first argument)
- `:calldata` — ABI-encoded input data for the call
- `:caller` — address of the account initiating this call
- `:origin` — address of the original transaction signer
- `:authorization_refund` — EIP-7702 refund earned before execution; it is
  added to the refund counter even when execution fails

Returns the final `MachineState` after execution completes.

# `run_loop`

```elixir
@spec run_loop(EEVM.Interpreter.MachineState.t()) :: EEVM.Interpreter.MachineState.t()
```

The main execution loop. Runs until execution terminates.

Three clauses handle the three possible states:

1. `status: :running` — fetch the current opcode, deduct static gas, delegate
   to `execute_opcode/2`, and recurse.
2. Any non-running status (`:stopped`, `:returned`, `:reverted`, `:invalid`,
   `{:error, reason}`) — the machine has halted; return as-is.
3. Out-of-gas during static cost deduction — the halted state is returned
   directly from `MachineState.consume_gas/2`.

This function is public because it is called recursively by itself. It is
the internal execution engine and not part of the public API — use `run/2`.

---

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