# Circuit Variables Management

`cirvariables.cpp` implements the small [`Circuit`](circuit.md) API around circuit variables - the netlist-level name/value bindings set by the `var` command, `.param`-style top-level assignments, and the command interpreter's `alter`/`elaborate`/`print`/`postprocess` machinery. Circuit variables are distinct from instance and model parameters: they live in a single flat namespace and are visible from every parameter expression in the hierarchy, rather than being scoped to one instance.

## Storage

Variables are held in `Circuit::variables`, a single [`Context`](context.md) (name to `Value` map). Two separate `RpnEvaluator`s reference it:

- `variableEvaluator_` has `variables` entered into its context stack once, in the `Circuit` constructor, and keeps it there for the evaluator's lifetime. This is the evaluator used wherever an expression is evaluated directly against circuit variables and constants - analysis parameters given by expressions, sweep parameters, option values given by expressions in the `options` command, the `postprocess` command line, the `var` command itself, `alter`, `elaborate` arguments, and names/expressions given to `print`.
- `paramEvaluator_` is the evaluator used for ordinary netlist parameter expressions (instance, model, and subcircuit parameters). Its context stack additionally holds the hierarchical instance contexts pushed and popped while propagating parameters down the hierarchy (see [Elaboration and Partial Elaboration](cirparams.md)), so `variables` cannot simply be entered once at construction time the way it is for `variableEvaluator_` - it must be re-installed as the base of the stack whenever it may have gone stale.

## `updateGlobalContext()`

Clears `paramEvaluator_`'s context stack and re-enters `variables` as its base (global) context. Called from the `Circuit` constructor (to make variables visible before anything else runs) and from `elaborateChanges()` whenever `Flags::VariablesChanged` is set (see [Elaboration and Partial Elaboration](cirparams.md)), which is the only time `paramEvaluator_`'s stack needs variables re-anchored.

## Variable API

- **`getVariable(name, s)`**: returns a pointer into `variables`, or sets `Status::NotFound`. Used by the parameter sweeper to bind to and snapshot a variable's value across sweep points.
- **`setVariable(name, value, s)`**: rejects redefinition of RPN constants (`ContextStack::isConstant()`, checked manually here since `Context::insertAndCheck()` itself does not distinguish constants from variables) with `Status::Redefinition`; otherwise inserts or updates the variable via `Context::insertAndCheck()`. Both insertion of a new variable and a change to an existing one's value set `Circuit::Flags::VariablesChanged`.
- **`clearVariables(s)`**: empties `variables` entirely and sets `VariablesChanged`.

## Downstream effect

`VariablesChanged` is the trigger `elaborateChanges()` checks to decide whether to rebuild the global parameter context, re-evaluate every options and analysis expression, and force parameter propagation across the whole hierarchy - see [Elaboration and Partial Elaboration](cirparams.md) for the full sequence.
