# lawref.evaluator.constants

*module*

[§54](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/09-part-ix-values-terms-expressions.ru.md#54-const): разыменование ссылок на константы пакета перед исполнением.

Константа объявляется декларацией (`const KZ: Jurisdiction = …`) и живёт в
CLIR узлом `symbol_decl` вида `constant`; терм, который её называет, остаётся
ссылкой `const_ref` ([§53](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/09-part-ix-values-terms-expressions.ru.md#53-термы)). Программа — это ссылка, исполнение — значение, и
здесь проходит граница между ними.

**Почему один предпроход, а не разыменование по месту.** Ссылка встречается в
двух ролях сразу: в позиции ТЕРМА (гард `r <= MAX_RATE`, арифметика [§58](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/09-part-ix-values-terms-expressions.ru.md#58-arithmetic)) и в
позиции АРГУМЕНТА литерала (`member_of(p, StateDuma)`). Первую разрешает
вычислитель термов, вторую — сопоставление с фактами по ключу атома
(`literal_key`). Разыменуй мы только первую — правило и факт об одном и том же
индивиде получили бы РАЗНЫЕ ключи и молча перестали совпадать; это ровно тот
класс отказа, ради которого заведён E-0040. Разыменование обеих по отдельности
требует, чтобы две ветки давали побайтово одну форму терма, и расхождение
между ними было бы невидимо. Предпроход снимает вопрос: ниже него ссылок на
константы не существует вовсе.

**Следствие, названное прямо:** в evaluation-документе (атомы, proof-граф,
вербализация) стоит ЗНАЧЕНИЕ константы, а не её имя. Имя остаётся в CLIR — в
узле `symbol_decl` и в исходнике. Обратный выбор — публиковать ссылку —
означал бы, что форма опубликованного атома зависит от того, какая сторона
попала в store первой (`SupportStore.atoms` хранит первую), то есть от порядка
узлов; [§211](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/29-part-xxviii-compiler-pipeline.ru.md#211-determinism) такого не допускает.

**Быстрый выход обязателен, а не является оптимизацией.** Пакет без единой
константы обязан пройти этот модуль, не изменив ни одного байта: только так
differential остаётся байтовым на всех замороженных голденах, ни один из
которых констант не несёт.

## lawref.evaluator.constants.ConstantError

*class*

```python
class ConstantError(Exception)
```

Bases: `Exception`

Ошибка разыменования константы; code — машинный код для issue.

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/evaluator/constants.py#L36-L42)

### lawref.evaluator.constants.ConstantError.code

*attribute* · *instance attribute*

```python
code = code
```

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/evaluator/constants.py#L41-L41)

### lawref.evaluator.constants.ConstantError.message

*attribute* · *instance attribute*

```python
message = message
```

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/evaluator/constants.py#L42-L42)

## lawref.evaluator.constants.resolve

*function*

```python
def resolve(*node_lists: list[dict]) -> tuple[list[dict], ...]
```

Разыменовать константы во всех переданных списках узлов.

Списки обрабатываются вместе и таблица строится по их объединению: факты
дела ссылаются на константы ПРОГРАММЫ, и раздельный проход дал бы стороне
дела нетронутую ссылку — то самое расхождение ключей, ради которого
предпроход и существует.

Возвращает списки в том же порядке. Если констант нет — те же объекты,
без единой копии.

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/evaluator/constants.py#L118-L134)

## lawref.evaluator.constants.resolved_table

*function*

```python
def resolved_table(nodes: list[dict]) -> dict[str, dict]
```

Таблица [§54](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/09-part-ix-values-terms-expressions.ru.md#54-const), чьи значения САМИ прошли разыменование (константа через
константу), — форма, в которой константу видит программа НИЖЕ предпрохода.

Нужна свёртке [§161.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1611-свёртка-истории-decision-0156): она публикует состояния и переходы профиля [§164.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1641-носитель-у-трёх-предикатов-decision-0156) и
обязана давать ту же форму терма, что предпроход даёт вопросу и фактам, —
иначе вывод и вопрос об одном состоянии получают разные ключи атома
(E-0148, сверка №4 п. 3). Цикла здесь быть уже не может: предпроход прошёл
раньше и на цикле отказал.

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/evaluator/constants.py#L99-L110)

## lawref.evaluator.constants.table

*function*

```python
def table(nodes: list[dict]) -> dict[str, dict]
```

Таблица [§54](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/09-part-ix-values-terms-expressions.ru.md#54-const) по списку узлов — для вида программы (`prepared`).

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/evaluator/constants.py#L94-L96)

## lawref.evaluator.constants.walk

*function*

```python
def walk(nodes: Any, table: dict[str, dict]) -> Any
```

Разыменовать по готовой таблице; пустая таблица — те же объекты.

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/evaluator/constants.py#L113-L115)
