Skip to content

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

NameDescription
ProgramViewУзлы программы после фильтров осей вызова и ленивые производные от них.

Functions

NameDescription
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 = 0

dependent_predicatesattributeinstance attribute#

dependent_predicates = dependent_predicates or set()

excluded_rulesattributeinstance attribute#

excluded_rules = excluded_rules

exclusion_reasonsattributeinstance attribute#

exclusion_reasons = exclusion_reasons

interpretation_requiredattributeinstance attribute#

interpretation_required = interpretation_required

keyattributeinstance attribute#

key = key

nodesattributeinstance attribute#

nodes = nodes

positions_dependentattributeinstance attribute#

positions_dependent = positions_dependent

replay_issuesattributeinstance attribute#

replay_issues = replay_issues

selected_interpsattributeinstance attribute#

selected_interps = selected_interps

tableattributeinstance attribute#

table = table

derivedmethod#

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.