lawref.evaluator.prepared
Подготовленная программа: анализы, зависящие только от IR, — один раз на объект.
Профиль 02.09.2026 (kz-income-tax, 18,8 МБ, 9790 узлов, ПУСТОЕ дело,
тёплый вызов): 2,94 с процессорного времени, из них ~90 % — величины,
которые не зависят ни от дела, ни от запроса и пересчитывались на КАЖДОМ
вызове evaluate: разыменование констант обходом всего IR (0,87 с),
классификация и страты строгих правил (0,7 с), анализ агрегатов (0,46 с),
установка замыканий §70 (0,54 с), хвосты proof-id (0,39 с), проверка хэшей
фрагментов §194 (0,5 с), таблицы символов календарного окружения (0,14 с).
Тот же класс, что закрыл DECISION-0054 для programHash: считалось не право,
а константа программы. Здесь константы программы получают один носитель.
Два уровня, по тому, от чего величина зависит:
- от IR целиком — хвосты proof-id (E-0097), issue §194 — живут в записи
program_derived(DECISION-0054) и делят с хэшем пин объекта, вытеснение и детектор мутации; - от «вида» программы — IR, срезанного осями вызова, которые его
фильтруют: дата права (§92.3, E-0095), выбор прочтений (§152–§156) и
константы дела (§168/§186; они же — таблица разыменования §54). Вид —
ProgramView: узлы после трёх проходов и ленивые производные от них (строгие правила с рангами §110, поражаемые правила с рангами и замыканием приоритетов §106, установка замыканий §70, таблицы TermEnv, индекс сигнатур). Виды живут в той же записи, что хэш, под ключом осей.
Байты выхода не меняются ни при каком порядке вызовов — по построению:
кэшируются ЧИСТЫЕ функции от (IR, оси), а issues, которые эти функции
порождали по ходу, записаны и воспроизводятся в том же порядке и тем же
числом раз, что и до кэша (см. strict_closure, defeasible_closure).
Проверка — differential: lawc этот кэш не знает, и байты обязаны сойтись.
Мутация. Раньше каждый вызов работал на свежих копиях (при непустой
таблице констант) либо на самом IR (при пустой); теперь узлы вида делятся
между вызовами всегда, как делился IR. Мутировать входные узлы движку
запрещено и до кэша (прецедент _conjuncts, DECISION-0054); детектор — та
же плановая сверка: на вызовах вида со счётчиком-степенью двойки вид
собирается заново и сравнивается структурно, расхождение — громкий
RuntimeError. Канарейка — engines/lawref/selftest.py.
Память. Разыменование §54 стало copy-on-write (constants._walk
возвращает ТОТ ЖЕ объект, если под ним ничего не изменилось), поэтому вид
держит в основном ссылки на узлы IR, а не копию программы; видов на
программу — не больше _VIEW_CAP, вытеснение LRU.
Classes
| Name | Description |
|---|---|
ProgramView | Узлы программы после фильтров осей вызова и ленивые производные от них. |
Functions
| Name | Description |
|---|---|
program_view | Вид программы для этого вызова: из кэша записи программы либо собранный. |
ProgramViewclass#
class ProgramView(key: tuple, nodes: list[dict], table: dict[str, dict], excluded_rules: list[dict], exclusion_reasons: dict[str, str], replay_issues: list[dict], selected_interps: list[str], interpretation_required: bool, dependent_predicates: set[str] | None = None, positions_dependent: bool = False)Узлы программы после фильтров осей вызова и ленивые производные от них.
callsattributeinstance attribute#
calls = 0dependent_predicatesattributeinstance attribute#
dependent_predicates = dependent_predicates or set()excluded_rulesattributeinstance attribute#
excluded_rules = excluded_rulesexclusion_reasonsattributeinstance attribute#
exclusion_reasons = exclusion_reasonsinterpretation_requiredattributeinstance attribute#
interpretation_required = interpretation_requiredkeyattributeinstance attribute#
key = keynodesattributeinstance attribute#
nodes = nodespositions_dependentattributeinstance attribute#
positions_dependent = positions_dependentreplay_issuesattributeinstance attribute#
replay_issues = replay_issuesselected_interpsattributeinstance attribute#
selected_interps = selected_interpstableattributeinstance attribute#
table = tablederivedmethod#
def derived(name: str, compute: Callable[[], Any]) -> AnyЛенивая чистая функция от узлов вида; считается один раз.
program_viewfunction#
def program_view(ir: dict, legal_time: str, options: dict, case: dict) -> ProgramViewВид программы для этого вызова: из кэша записи программы либо собранный.
Ключ — ровно те оси, от которых зависят три прохода: дата права, список выбранных прочтений КАК ПОДАН (порядок влияет на порядок issues о неизвестных прочтениях), константы дела в порядке подачи (порядок задаёт порядок эфемерных деклараций в узлах, §211) и предъявленный состав редакций §92 (E-0167): он решает, исполняется ли условие 3 вообще, — без него один и тот же IR на одной дате отдавал бы из кэша чужой вид.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.