Skip to content

lawref.canon

Канонический JSON-emitter (WP-04; SPEC §208 + errata E-0002).

Правила v1 (кросс-языковой контракт с engines/lawc/law-canon — байтовая идентичность проверяется в CI):

  • UTF-8, без незначащего whitespace;
  • все строки (ключи и значения) ОБЯЗАНЫ быть в NFC — иначе CanonError: NFC- нормализация — обязанность normalizer-а, emitter только проверяет. Исключений нет: исходные байты official text block (SPEC §13), отличные от NFC, несёт base64-поле texts[].exactBytes (§28, errata E-0248), а не строка text;
  • ключи объектов сортируются по code points (== порядок байтов UTF-8 — одинаково в Python и Rust); коллизия ключей после NFC — ошибка;
  • JSON-числа допускаются только целые в диапазоне i64 (SPEC §18: binary float запрещён; Decimal/Rational сериализуются строками в canonical form §208 — форму строки обеспечивает normalizer);
  • массивы сохраняют порядок; для document-режима top-level “nodes” сортируется по stable ID (§208: unordered node sets — по stable ID); сортировка semantic sets по element hash и commutative operands по semantic hash — обязанность normalizer-а (§207.1), сюда документы приходят уже нормализованными;
  • экранирование строк зафиксировано явно (совпадает в обеих реализациях): " -> ", \ -> \, управляющие < U+0020 — \b \t \n \f \r либо \u00xx (строчные hex); остальное — сырой UTF-8.

Classes

NameDescription
CanonErrorНарушение канонических правил §208.

Functions

NameDescription
canonical_bytesКанонические байты (§208). document=True сортирует top-level nodes по ID.
canonical_decimalКаноническая форма Decimal §208 (errata E-0052).
canonical_rationalКаноническая форма Rational §208/§35 (errata E-0213).

CanonErrorclass#

class CanonError(ValueError)

Bases: ValueError

Нарушение канонических правил §208.

canonical_bytesfunction#

def canonical_bytes(value: Any, *, document: bool = True) -> bytes

Канонические байты (§208). document=True сортирует top-level nodes по ID.

Нормализация записи значения (errata E-0052, E-0213) применяется ВСЕГДА, а не только к документу: канонические байты обязаны быть каноническими независимо от производителя, а CLIR приходит и не от компилятора.

canonical_decimalfunction#

def canonical_decimal(text: str) -> str | None

Каноническая форма Decimal §208 (errata E-0052).

«canonical non-exponent string: 0, -12, 0.125, -3.5; без leading zeros, trailing fractional zeros и negative zero», и там же нормативный пример: «source 12.50, 1.25e3 normalizes соответственно в 12.5, 1250». Зеркало law_canon::canonical_decimal; кросс-языковой контракт G-M1a держит их байтово равными.

None — вход не десятичное число: значение чужого вида (Text, Date, Rational) обязано пройти невредимым, а не быть испорченным нормализацией.

Считается СТРОКОЙ, а не Decimal/float: float запрещён §18, а перенос точки цифр не меняет.

canonical_rationalfunction#

def canonical_rational(text: str) -> str | None

Каноническая форма Rational §208/§35 (errata E-0213).

§35: «в canonical serialization представляется несократимой дробью». Знак стоит у ЧИСЛИТЕЛЯ, знаменатель строго положителен — той же записью, какую §168.1 уже требует от ground-позиции утверждения. 15/100 → 3/20, 1/-2 → -1/2, -3/-6 → 1/2, 0/7 → 0/1. 5/1 остаётся дробью: вид значения не зависит от значения (§58), и целое здесь не появляется.

None — вход не дробь §208 (чужой вид, незаконная лексика E-0203) либо знаменатель нулевой: такая запись обязана пройти каноном невредимой, чтобы её отверг читатель литерала своей диагностикой (§48, E-0152), а не канон.

Зеркало law_canon::canonical_rational; кросс-языковой контракт G-M1a держит их байтово равными. Носитель — целые Python (§35, E-0159: разрядность Rational не ограничена), делитель — math.gcd над int.

Documentation for Arxo. Writings — blog.arxo.io.

Anonymous visit counts on stats.arxo.io, no cookies.