|
1 | 1 | # План миграции jRegTab → pyRegTab |
2 | 2 |
|
3 | | -**Статус:** ЧЕРНОВИК v2 (ANTLR4-требование ослаблено; ядро — Rust, альтернатива — C++) |
| 3 | +**Статус:** РЕАЛИЗОВАН (вариант A — Rust; сверка выполнена 2026-07-10, итог и |
| 4 | +осознанно отложенные пункты — в §11) |
4 | 5 | **Дата:** 2026-07-06 (v2 — того же дня; v1 с обязательным ANTLR4 заменена целиком) |
5 | 6 | **Исходный проект:** `d:\YandexDisk\code2\jregtab` (Java 21, v0.1.2-SNAPSHOT) |
6 | 7 | **Целевой проект:** pyRegTab — Python-пакет с нативным ядром, публикуемый на PyPI |
@@ -379,57 +380,60 @@ conformance-корпус зелёный в обоих проектах**. |
379 | 380 | Оценки — в неделях чистой работы одного разработчика; фазы 2–5 частично параллелизуемы. |
380 | 381 |
|
381 | 382 | ### Фаза 0 — Решения и прототип (1 нед.) |
382 | | -- [ ] Аудит регулярок во всех фикстурах/тестах → выбор `regex` vs `fancy-regex`. |
383 | | -- [ ] Прототип парсера: лексер (logos) + рекурсивный спуск для 2–3 правил `RTL.g4`, |
| 383 | +- [x] Аудит регулярок во всех фикстурах/тестах → выбор `regex` vs `fancy-regex`. |
| 384 | +- [x] Прототип парсера: лексер (logos) + рекурсивный спуск для 2–3 правил `RTL.g4`, |
384 | 385 | разбор 5–10 реальных RTL-строк. |
385 | | -- [ ] Прототип wheel: maturin + PyO3, пустой `_core` с одним классом, сборка |
| 386 | +- [x] Прототип wheel: maturin + PyO3, пустой `_core` с одним классом, сборка |
386 | 387 | wheels на Windows и Linux (GitHub Actions, maturin-action). |
387 | | -- [ ] Утвердить стиль API (properties vs `set_*`; §4.6) и имя пакета на PyPI. |
388 | | -- [ ] **Точка выхода**: при блокере — переключение на C++ (вариант B), §3.B. |
| 388 | +- [x] Утвердить стиль API (properties vs `set_*`; §4.6) и имя пакета на PyPI. |
| 389 | +- [x] **Точка выхода**: при блокере — переключение на C++ (вариант B), §3.B. |
389 | 390 | - Результат: утверждённые решения, репозиторий-скелет `pyregtab`. |
390 | 391 |
|
391 | 392 | ### Фаза 1 — ITM syntax + Recordset (1–1.5 нед.) |
392 | | -- [ ] Порт `itm.syntax` (11 классов) на Rust: арена + индексы (§4.2). |
393 | | -- [ ] Порт `recordset` (3 класса). |
394 | | -- [ ] PyO3-биндинги (handle-объекты) + Python-обёртки `syntax.py`, `recordset.py`. |
395 | | -- [ ] Юнит-тесты (создание таблиц, subtables/subrows, форматирование ячеек). |
| 393 | +- [x] Порт `itm.syntax` (11 классов) на Rust: арена + индексы (§4.2). |
| 394 | +- [x] Порт `recordset` (3 класса). |
| 395 | +- [x] PyO3-биндинги (handle-объекты) + Python-обёртки `syntax.py`, `recordset.py`. |
| 396 | +- [x] Юнит-тесты (создание таблиц, subtables/subrows, форматирование ячеек). |
396 | 397 |
|
397 | 398 | ### Фаза 2 — ATP spec (1–1.5 нед.) |
398 | | -- [ ] Порт `atp.spec` (18 классов) на Rust-enum'ы/структуры: паттерны, content specs, |
| 399 | +- [x] Порт `atp.spec` (18 классов) на Rust-enum'ы/структуры: паттерны, content specs, |
399 | 400 | `ActionSpec`, `ProviderSpec`, `FilterTerm`, `Quantifier`, `StringExtractor`, предикаты. |
400 | | -- [ ] Custom-предикаты с Python-callable (§4.4). |
401 | | -- [ ] Python-фабрики, повторяющие Java-фабрики; docstrings из Javadoc. |
| 401 | +- [x] Custom-предикаты с Python-callable (§4.4). |
| 402 | +- [x] Python-фабрики, повторяющие Java-фабрики; docstrings из Javadoc. |
402 | 403 |
|
403 | 404 | ### Фаза 3 — Matcher + ITM semantics (2 нед., самая сложная) |
404 | | -- [ ] Порт `itm.semantics` (items, providers, operations, `WorkingState`). |
405 | | -- [ ] Порт `atp.match` (`SyntaxMatcher`, `SemanticConstructor`, `AtpMatcher`). |
406 | | -- [ ] Первые сквозные тесты: задачи 001–020 через ATP-паттерны (без RTL). |
| 405 | +- [x] Порт `itm.semantics` (items, providers, operations, `WorkingState`). |
| 406 | +- [x] Порт `atp.match` (`SyntaxMatcher`, `SemanticConstructor`, `AtpMatcher`). |
| 407 | +- [x] Первые сквозные тесты: задачи 001–020 через ATP-паттерны (без RTL). |
407 | 408 |
|
408 | 409 | ### Фаза 4 — Interpreter (1 нед.) |
409 | | -- [ ] Порт `interpret` (4 фазы, стратегии, `MissingValueHandler`, трансформации |
| 410 | +- [x] Порт `interpret` (4 фазы, стратегии, `MissingValueHandler`, трансформации |
410 | 411 | `WhitespaceNormalization` / `FieldSplitting` / `SchemaReordering` / `AnchorAttributeAtPosition`). |
411 | | -- [ ] Сквозные ATP-тесты для всех 150 задач зелёные. |
| 412 | +- [x] Сквозные ATP-тесты для всех 150 задач зелёные. |
412 | 413 |
|
413 | 414 | ### Фаза 5 — RTL: парсер, построитель ATP, сериализатор (1.5–2 нед.) |
414 | | -- [ ] Полный лексер + рекурсивный спуск по всем правилам `RTL.g4` (§5.1). |
415 | | -- [ ] Порт логики `ATPBuilder`, `ProviderTemplateResolver`, `StringExtractorFactory`; |
| 415 | +- [x] Полный лексер + рекурсивный спуск по всем правилам `RTL.g4` (§5.1). |
| 416 | +- [x] Порт логики `ATPBuilder`, `ProviderTemplateResolver`, `StringExtractorFactory`; |
416 | 417 | `RtlCompiler` / `RtlCompileError` с диагностикой line:col. |
417 | | -- [ ] Порт `AtpToRtlSerializer`; round-trip тест. |
418 | | -- [ ] Сборка conformance-корпуса (позитив из тестов jregtab, негатив — по веткам |
| 418 | +- [x] Порт `AtpToRtlSerializer`; round-trip тест. |
| 419 | +- [x] Сборка conformance-корпуса (позитив из тестов jregtab, негатив — по веткам |
419 | 420 | ошибок парсера); job для jregtab-CI. |
420 | | -- [ ] RTL-тесты для всех 150 задач зелёные (итого 1 500 вариантов). |
| 421 | +- [x] RTL-тесты для всех 150 задач зелёные (итого 1 500 вариантов). |
421 | 422 |
|
422 | 423 | ### Фаза 6 — Дифференциальная проверка и полировка API (1 нед.) |
423 | | -- [ ] Дифф-прогон против jRegTab (§7.3), устранение расхождений. |
424 | | -- [ ] GIL-release (`allow_threads`), `match_many`-бенчмарк, сравнение скорости |
425 | | - с jRegTab (criterion ↔ JMH). |
426 | | -- [ ] `to_pandas()`, `__repr__`, типизация (`py.typed`, stubs для `_core`). |
| 424 | +- [x] Дифф-прогон против jRegTab (§7.3), устранение расхождений |
| 425 | + (750/750 вариантов идентичны; ручной CI-job `differential` добавлен). |
| 426 | +- [x] GIL-release (`allow_threads`) и `AtpMatcher.match_many` (внутренний пул |
| 427 | + потоков, реализован в 0.3.0). *Не сделано:* бенчмарк-сравнение скорости |
| 428 | + с jRegTab (criterion ↔ JMH) — см. §11. |
| 429 | +- [x] `to_pandas()`, `to_csv()`, `__repr__`, типизация (`py.typed`, stubs для `_core`). |
427 | 430 |
|
428 | 431 | ### Фаза 7 — CI/CD, документация, релиз (1 нед.) |
429 | | -- [ ] maturin-action матрица wheels, публикация на TestPyPI → PyPI (`pyregtab 0.1.0`). |
430 | | -- [ ] mkdocs-сайт (адаптация docs jregtab: getting-started, RTL reference — общий, |
| 432 | +- [x] maturin-action матрица wheels, публикация на PyPI (`pyregtab 0.1.0`, |
| 433 | + 2026-07-07; сразу через trusted publishing, без промежуточного TestPyPI). |
| 434 | +- [x] mkdocs-сайт (адаптация docs jregtab: getting-started, RTL reference — общий, |
431 | 435 | API reference — Python). |
432 | | -- [ ] README с примером из §4.6; документ о процессе эволюции RTL (§5.2) — в оба репо. |
| 436 | +- [x] README с примером из §4.6; документ о процессе эволюции RTL (§5.2) — в оба репо. |
433 | 437 |
|
434 | 438 | **Итого: ~8.5–10 недель.** |
435 | 439 |
|
@@ -460,3 +464,32 @@ conformance-корпус зелёный в обоих проектах**. |
460 | 464 | в 0.1 (`Bindings`, `RtlCompiler.compile(rtl, bindings)`). Отложено на будущее: |
461 | 465 | перегрузка операторов Python (`+`/`*` квантификаторы) и корпусный |
462 | 466 | DSL-генератор в `tools/translate_atp.py --dsl`. |
| 467 | + |
| 468 | +--- |
| 469 | + |
| 470 | +## 11. Статус реализации (сверка 2026-07-10) |
| 471 | + |
| 472 | +План реализован: вариант A (Rust + PyO3 + maturin), релизы `pyregtab` 0.1.0 → |
| 473 | +0.1.1 → 0.2.0 на PyPI, паритет с jRegTab 0.4.1. Критерий готовности §7 выполнен: |
| 474 | +1 500/1 500 вариантов зелёные, дифф с jRegTab пуст (750/750), conformance-корпус |
| 475 | +зелёный в CI обоих проектов. Все открытые вопросы §10 решены (Rust; `cell.text` |
| 476 | +property + `set_text()`; имя `pyregtab`; корпус копиями с пином; Python ≥ 3.10; |
| 477 | +pure-Python-фолбэк не делается — достаточно sdist). |
| 478 | + |
| 479 | +Сверх плана: embedded RTL DSL (`pyregtab.dsl`, 0.2.0) и IDE-поддержка RTL |
| 480 | +(`ide/`, зеркало jRegTab 0.4.0). |
| 481 | + |
| 482 | +Закрыто при сверке (0.3.0): `AtpMatcher.match_many` (§4.5) — параллельный |
| 483 | +батчевый матчинг с внутренним пулом потоков без GIL; `Recordset.to_csv()` |
| 484 | +(§4.1); clippy в CI стал блокирующим (§7.7); ручной CI-job `differential` |
| 485 | +(workflow_dispatch, §7.3). |
| 486 | + |
| 487 | +Осознанно отложено (не блокирует паритет и релизы): |
| 488 | + |
| 489 | +- бенчмарки скорости против jRegTab (criterion ↔ JMH, фаза 6) — отдельный |
| 490 | + перфоманс-проект; |
| 491 | +- property-based тесты парсера (proptest, §7.6) и выборочный `cargo miri` |
| 492 | + (§7.7) — покрытие обеспечивают conformance-корпус и 1 500 вариантов; |
| 493 | +- pure-Python fallback (§10.6) — отклонён; |
| 494 | +- рукописный лексер вместо `logos` и единый `__init__.py`-реэкспорт вместо |
| 495 | + расписанных в §4.1 модулей Python-слоя — эквивалентные упрощения, не долг. |
0 commit comments