Skip to content

Releases: FQingLars/Qlisp-Project

QLISP v2.8.3 — rc-контракт стабильных ячеек, отложенная смерть, live-глобалы

Choose a tag to compare

@FQingLars FQingLars released this 05 Oct 09:54

QLISP 2.8.3 — Release Notes

Тег: v2.8.3 · Платформы: Linux x86_64, Windows x86_64
Бинарники — сборка CI, коммит 1e79234 ветки main (зелёный прогон 37269734007). Состав: qlisp (REPL/интерпретатор + JIT), qlisp-lsp, qvalent.

Файл Платформа Состав
qlisp-linux-x86_64 Linux x86_64 REPL/интерпретатор + JIT
qlisp-lsp-linux-x86_64 Linux x86_64 Language Server
qvalent-linux-x86_64 Linux x86_64 пакетный менеджер
qlisp-windows-x86_64.zip Windows x86_64 qlisp.exe, qlisp-lsp.exe, qvalent.exe

SHA256SUMS — контрольные суммы всех файлов.

Что нового

1. rc-контракт стабильных ячеек (главное изменение)

Стабильная ячейка несёт refs_ (бит стабильности + счётчик, rc=1 при создании). Каждое место разделения берёт ссылку: захваты замыканий, O(1)-append списков, adopt_world, plist-таблица, fusion-реестры, слоты инстансов, back-refs декодера образов, примитивы-эмбеды. Смерть последнего владельца — итеративный worklist-каскад stable_release: строковые байты возвращаются в malloc, программы освобождают W^X-страницу и удаляются, тензоры снимаются с трекинга. nil бессмертен.

Вместе с этим удалены якоря-владельцы и аудитор контрактов смерти: QLISP_AUDIT больше не читается, реестр якорей и audit_death_contracts вычищены, CI-шаг leak_watch (QLISP_AUDIT=1) заменён на ASan-sweep с detect_leaks=0.

QA-хук: QLISP_RC_POISON=1 заполняет освобождённые ячейки и падает на use-after-release / double-release — контракт ссылок проверяется без ASan.

2. Доктрина отложенной смерти

Любая ЗАМЕНА стабильного значения посреди формы (adopt_world старого мира, swap setq, перепись put, переопределение defun/слота/макроса) больше не каскадит сразу: корень паркуется в defer_stable_release с меткой эпохи и умирает либо на следующем restore скраша (правило эпох), либо на границе формы (flush_form_end). Причина (доказано ASan): под live-резолвингом у исполняемого замыкания rc=1 — оно держит только пару спайна, и каскад посреди формы убивал ТЕЛО исполняемой функции (use-after-free в adopt_world). Явная смерть по запросу — (clear sym ...), (drop-model m), перепись биндинга — остаётся синхронной: пользователь попросил умереть сейчас. Парк константный (очередь хронологическая, слив с конца), иначе restore в горячем цикле сканировал бы всю очередь.

3. Live-резолвинг глобалов

«Острова циклов захвата» устранены: замыкание больше не захватывает глобальный кадр, глобалы резолвятся в момент вызова (семантика Common Lisp — переопределение defun видно живым замыканием). Захватываются только локальные кадры (let/let*/циклы), каждый со своей ссылкой. Разобраны три зависимости: образы — через отложенные каскады, import_from — через модульные лексические кадры, JIT — тест переписан на живой контракт. Контракт закрыт сюитом tests/live_globals.qlsp.

⚠️ Следствие: лисп-обёртка с именем примитива затеняет сам примитив (символы регистронезависимы) — (defun sample (logits) (SAMPLE logits)) вызовет сам себя и уйдёт в бесконечный хвостовой цикл. В stdlib такие обёртки убраны (SLEEP → WAIT-MS, STRING-CONTAINS → STRING-INDEX).

4. Свип утечек

ASan + detect_leaks=1 по всему корпусу: было 55/87 файлов без утечек, стало 85/87. Закрыто две ошибки владения: кэш раскрытий макросов ронял свои root-клон'ы (кэш не может быть владельцем памяти, которую читатель берёт без ссылки — либо парк, либо клон-на-хит) и clone_to инстанса добавлял ссылку поверх счётчика создания слота.

5. Фикс &optional со значением по умолчанию

Регрессия 2.8.2 закрыта: (defun f (&optional (k 0) (s 1)) ...) больше не теряет default-формулы — новая clean_param_list нормализует сырой список параметров напрямую, &OPTIONAL/&REST и формы (имя default) проходят насквозь.

(defun addup (&optional (k 0) (s 1)) (print (list k s)))
(addup)      ;; → (0 1)   — в 2.8.2 было (nil 1)
(addup 5)    ;; → (5 1)

6. Телдаун мира

~Interpreter разбирает все владеющие реестры; добавлены ~MacroExpander (дренирует макро-таблицы и кэш раскрытия) и деструктор ClassRegistry. run-tests освобождает реестр *tests* в конце — цикл «пара ↔ захваты тест-замыканий» разорван до телдауна, LSan-чистый выход.

7. Починка Windows-сборки

Удалены мёртвые #include <execinfo.h> и <unistd.h> из src/eval/interpreter.cpp — glibc-заголовок в MinGW-w64 ломал сборку (вызовов backtrace в коде нет).

Изменение (mem-report)

Ключ rooted удалён: бессмертие теперь выражается ссылками. Добавлены счётчики смерти — stable-cells, stable-cells-released, buffers-released, progs-released. Реальный вывод на этом бинаре:

(print (mem-report))
;; → (("names" . 0) ("payloads" . 0) ("progs" . 0) ("tensors" . 0)
;;     ("shared" . 0) ("stable-bytes" . 123664) ("scratch-bytes" . 3832)
;;     ("scratch-cells" . 25249) ("stable-cells" . 25711)
;;     ("stable-cells-released" . 22235) ("buffers-released" . 0)
;;     ("progs-released" . 0))

Известные ограничения

  • Острова циклов через set_cdr не собираются — доктрина no-GC: остров, удерживающий сам себя, неразрешим без GC.
  • Две остаточные утечки (обе стабильны, не растут с повторами): tests/symbolic_neuro.qlsp (66 Б) и tests/tablet.qlsp (67 Б) — стабильный клон строки, последняя ссылка не снимается.
  • MSan неприменим для текущего GCC-тулчейна (нужен clang + инструментированная libc++).
  • Класс C — многократный setq одного тензора: ранее +12 МБ на 20k setq; под rc-контрактом не перезамерялось.
  • run-tests освобождает реестр в конце, поэтому повторный вызов в том же скрипте даст 0/0 passed — контракт фреймворка, не регресс.

Тесты: корпус зелёный, новые сюиты rc_contract.qlsp (9 сценариев) и live_globals.qlsp (9 deftest), tail_call.qlsp расширен &optional-тестами, plist_anchor.qlsp переведён на rc-метрики; ASan-свип 85/87 файлов без утечек.

QLISP v2.8.2 — кэш раскрытия макросов, DEBUG-TRACE, tail-call optimization

Choose a tag to compare

@FQingLars FQingLars released this 04 Oct 22:21

QLISP 2.8.2 — Release Notes

Тег: v2.8.2 · Платформы: Linux x86_64, Windows x86_64
Бинарники — сборка CI (Linux: GCC/Ninja/OpenBLAS/OpenMP; Windows: MSYS2 MinGW64), коммит d716a6a ветки main компиляторного репозитория (CI run 37146790204, зелёный). Состав: qlisp (REPL/интерпретатор + JIT), qlisp-lsp, qvalent.

Файл Платформа Состав
qlisp-linux-x86_64 Linux x86_64 REPL/интерпретатор + JIT
qlisp-lsp-linux-x86_64 Linux x86_64 Language Server
qvalent-linux-x86_64 Linux x86_64 пакетный менеджер
qlisp-windows-x86_64.zip Windows x86_64 qlisp.exe, qlisp-lsp.exe, qvalent.exe

SHA256SUMS — контрольные суммы всех файлов.

Что нового

Кэш раскрытия макросов (FIXED)

Класс-A утечки scratch: let* или любой макрос в цикле давал ~1 КБ на оценку, линейно (дифференциал: 22 МБ у let против 217 МБ у let* на 200k итераций). Причина: eval_cons звал macroexpand_1 на каждой оценке, а expand() чеканил всё дерево раскрытия заново в root-арене. Кэш в MacroExpander: одно раскрытие на уникальную форму-источник, hit по контенту (у EVAL адреса scratch-форм перерабатываются), запись держит root-клон источника, инвалидация на defmacro*/SLOT-SET, macolet-протяжения вне кэша. После фикса: let* 22.7 МБ против let 22.6 МБ — дифференциал схлопнулся.

DEBUG-TRACE — хронология событий владения

Четыре новых примитива и модуль src/core/trace.{hpp,cpp}: ограниченное кольцо на 4096 записей (сам трейс не течёт; выключенный — один relaxed load), категории scope/clone/anchor/expand/macro.

(DEBUG-TRACE)                              ;; → nil   (выключен по умолчанию)
(DEBUG-TRACE t)                           ;; → T     (все категории)
(DEBUG-TRACE '(scope clone anchor))       ;; → T     (только указанные)
(TRACE-STATS)
;; → (("recorded" . 9) ("dropped" . 0) ("stored" . 9) ("capacity" . 4096)
;;     ("scope" . 5) ("clone" . 2) ("anchor" . 2) ("expand" . 0) ("macro" . 0))
(TRACE-DUMP)                              ;; список строк "<tick> <cat> <text>", oldest-first
(TRACE-CLEAR)                             ;; → nil

Включение также через QLISP_TRACE=scope,clone,anchor,expand,macro. Точки эмиссии: reset_scratch (границы форм), clone_to (мост disposable→stable), take/release якорей, кэш раскрытия, defmacro/defcompiler-macro. Счётчики вынесены в TRACE-STATS, а не в mem-report — форма mem-report зашита в существующие тесты.

Tail-call optimization для self-хвостовых вызовов

Хвостовой вызов пере-биндит кадр вместо того, чтобы класть новый (параметры копируются в heap-стор, итерация освобождается через restore). Гейт: при живых tape-узлах TCO для итерации выключается; let/let* разворачиваются в транполине до 8 уровней, глубже — честный фоллбэк.

Замер (RSS, рекурсивный train-эпох): было 34.8/51.2/67.5 МБ на N=100/300/500 против плоского while ~25 МБ → стало 27.4/27.4/27.4 МБ. Хвостовая рекурсия на 200 000: (tc-sum 200000 0) → 20000100000, без роста стека.

Вне среза: взаимные хвостовые вызовы, нативная рекурсия JIT, хвосты глубже let/if/progn (cond, when).

Известная проблема этой версии

&optional со значением по умолчанию теряет его: (defun f (&optional (k 0)) ...) биндит k в nil ((+ k 1) → «argument is not a number»). Причина — нормализация списка параметров в defun/defuse отбрасывала default-форму. Исправлено в 2.8.3.

Тесты: 78 сюитов в tests/ (+9 в test/); новые expansion_cache.qlsp (7), debug_trace.qlsp (7), tail_call.qlsp (18). Корпус и аудитор зелёные; ASan/LSan чисто на затронутых сценариях.

QLISP v2.8.1 — якорение plist, enc-спайн, production-тесты

Choose a tag to compare

@FQingLars FQingLars released this 02 Oct 06:03

QLISP 2.8.1 — Release Notes

Тег: v2.8.1 · Платформы: Linux x86_64, Windows x86_64
Бинарники — сборка CI, коммит 3fe9148 ветки main компиляторного репозитория (CI run 36874257672, зелёный). Состав: qlisp, qlisp-lsp, qvalent.

Файл Платформа Состав
qlisp-linux-x86_64 Linux x86_64 REPL/интерпретатор + JIT
qlisp-lsp-linux-x86_64 Linux x86_64 Language Server
qvalent-linux-x86_64 Linux x86_64 пакетный менеджер
qlisp-windows-x86_64.zip Windows x86_64 qlisp.exe, qlisp-lsp.exe, qvalent.exe

SHA256SUMS — контрольные суммы всех файлов.

Что нового — якорение plist + enc-спайн + production-тесты

enc-спайн сериализатора (закрыт предсказанный UB). RuntimeEnc::enc больше не рекурсирует по cdr-спайну: спайн проходится итеративно, каждый узел регистрируется в memo (паритет с декодером), общий/циклический хвост — tag-12 back-ref. Байт-формат не менялся. Зеркальная половина: RuntimeDec::dec (dec_spine_cell) — спайн итеративно, ячейки сшиваются снизу вверх, порядок memo-регистрации побайтно совпадает с энкодером. image.qlsp под -O2+ASan: exit 0 (не проходил с 2.8.0). Добавлен энкодерный детектор циклов через non-cons контейнеры (closure/jitprog/hloprog) — падает сразу с kind'ом объекта.

Якорение plist (щель put закрыта). Слоты property lists — stable-слоты леса: (put sym prop v) переписывает ключ plist:<sym>:<prop> по порядку take → anchor нового клона → release старого; (remprop sym prop) — досрочная смерть по явной просьбе; plists_install при LOAD-IMAGE сперва выпускает старые якоря, потом ставит образ-значения. Скалярный fast-path put (fixnum/flonum/symbol) — без якорей.

Тесты. tests/plist_anchor.qlsp (8): overwrite 7×512×512 держит RSS в 1024 КБ, remprop освобождает долю слота при живом имени, registry-drain, plist переживает SAVE/LOAD-IMAGE. tests/production_mem.qlsp — реальные задачи: тренировка 120 эпох (45.6 → 0.014) с per-epoch чекпоинтами, наклон 8 КБ; своп моделей через plist; image-циклы; compile-churn с возвратом реестра к базлайну. Корпус 81/81 по exit-code.

QLISP v2.8.0 — лесное правило бессмертной зоны, аудитор, интерактив

Choose a tag to compare

@FQingLars FQingLars released this 02 Oct 06:03

QLISP 2.8.0 — Release Notes

Тег: v2.8.0 · Платформы: Linux x86_64, Windows x86_64
Бинарники — сборка CI, коммит 7c9ec55 ветки main компиляторного репозитория (CI run 36871109705, зелёный). Состав: qlisp, qlisp-lsp, qvalent.

Файл Платформа Состав
qlisp-linux-x86_64 Linux x86_64 REPL/интерпретатор + JIT
qlisp-lsp-linux-x86_64 Linux x86_64 Language Server
qvalent-linux-x86_64 Linux x86_64 пакетный менеджер
qlisp-windows-x86_64.zip Windows x86_64 qlisp.exe, qlisp-lsp.exe, qvalent.exe

SHA256SUMS — контрольные суммы всех файлов.

Что нового — якоря-владельцы, аудитор, интерактив (FIXED)

Лесное правило бессмертной зоны: бессмертная зона — несвязный лес, каждое имя якорит своё поддерево; перепись имени (defvar/setq глобала/defun/defclass) выпускает старое поддерево. Критичный порядок rebind (выведен ASan): take_anchors (снапшот) → anchor_subtree → release_anchors (снапшота) → release_shadowed_pairs → prepend; нарушение = UAF.

  • Release-on-rebind работает для тензоров (буфер в пул) и HLO-программ (cache-erase → page_free → delete graph/storage/prog). Тензоры леса несвязны (deep copy), HLOPROG-программы шарят payload ⇒ «якорное множество»: release, когда множество пусто. Tape-held тензоры: release откладывается до опустошения ленты (расписание, не отмена).
  • Аудитор контрактов смерти (Interpreter::audit_death_contracts, флаг QLISP_AUDIT=1, вызов на границе формы после seal ленты): фатальны «второе бессмертие» (rooted payload без якоря) и сирота реестра (якорь без живого биндинга). Корпус 82 скрипта под аудитом: 0 падений. CI: шаг leak_watch гоняет весь корпус под QLISP_AUDIT=1.
  • Интерактив: (clear sym...) / (drop-model m) — специальные формы (имена не вычисляются), отвязывают имена и выпускают payload'ы; (mem-report) — alist якорного реестра + rooted count + байты арен.
  • LOAD-IMAGE по лесному правилу: adopt_world_bindings применяет take → anchor → release к каждому image-биндингу (иначе якорь IMG-T-ONE оставался сиротой); part-time drop образ-программы отменяется на обеих аренах.

Замеры (RSS, наклон): rebind тензоров 512×512 ×20 → 0 КБ; rebind программ ×8 → 0 КБ; bind/clear циклы → 1024 КБ разогрева, наклон 0.

QLISP v2.7.7 — part-time HLO: программа владеет своими артефактами

Choose a tag to compare

@FQingLars FQingLars released this 02 Oct 06:03

QLISP 2.7.7 — Release Notes

Тег: v2.7.7 · Платформы: Linux x86_64, Windows x86_64
Бинарники — сборка CI, коммит 3ae37e1 ветки main компиляторного репозитория (CI run 36772578415, зелёный). Состав: qlisp, qlisp-lsp, qvalent.

Файл Платформа Состав
qlisp-linux-x86_64 Linux x86_64 REPL/интерпретатор + JIT
qlisp-lsp-linux-x86_64 Linux x86_64 Language Server
qvalent-linux-x86_64 Linux x86_64 пакетный менеджер
qlisp-windows-x86_64.zip Windows x86_64 qlisp.exe, qlisp-lsp.exe, qvalent.exe

SHA256SUMS — контрольные суммы всех файлов.

Что нового — part-time HLO: программа владеет своими артефактами (FIXED)

Тестер (долгие компилирующие сессии): «утечка за вызов» — каждый HLO-COMPILE клонировал константы графа в бессмертный stable (даже при cache-hit), оставлял introspection-клон без владельца и никогда не освобождал W^X-страницу (ASan: 1120/752/1872 Б на тест, все из HloGraph::clone_into).

Причина: одноразовые артефакты компиляции жили в stable без владельца и без события смерти.

  • HloProgram владеет артефактами: storage-scope с sealed-константами (seal_graph_constants), introspection-клон графа, W^X-страница (page_free).
  • Якорь смерти = track_dtor в scratch на эпохе компиляции: программа умирает на первом restore, пересекающем эпоху (итерация объемлющего while или граница формы) — как любой scratch-объект.
  • Явное сохранение = привязка имени: clone_to в stable (defvar/setq через promote) помечает payload rooted — программа бессмертна до переписи. Спец-паттерн (setq *x* (HLO-COMPILE ...)) и defvar — явная просьба о бессмертии, всё прочее умирает само.
  • Кэш стенсила — non-owning дедупликация: drop стирает запись перед освобождением, мёртвая программа не возвращается из кэша; rooted-программы дедуплицируются между собой.
  • GRAPH-FROM-DATA: константы загруженного графа тоже seal-ятся в storage программы — закрыт кросс-форменный UAF.

Production-check (RSS): discard-loop ×20: 22548 → 3088 КБ (остаток — разовая high-water, наклон нулевой). distinct-loop ×20: 20632 → 20 КБ (идеально плоско). Корпус зелёный; ASan: утечки clone_into исчезли (memory_soak/arena_stress: 0).

QLISP v2.7.6 — lifetime loop store = граница формы

Choose a tag to compare

@FQingLars FQingLars released this 02 Oct 06:03

QLISP 2.7.6 — Release Notes

Тег: v2.7.6 · Платформы: Linux x86_64, Windows x86_64
Бинарники — сборка CI, коммит 405632a ветки main компиляторного репозитория (CI run 36746210696, зелёный). Состав: qlisp, qlisp-lsp, qvalent.

Файл Платформа Состав
qlisp-linux-x86_64 Linux x86_64 REPL/интерпретатор + JIT
qlisp-lsp-linux-x86_64 Linux x86_64 Language Server
qvalent-linux-x86_64 Linux x86_64 пакетный менеджер
qlisp-windows-x86_64.zip Windows x86_64 qlisp.exe, qlisp-lsp.exe, qvalent.exe

SHA256SUMS — контрольные суммы всех файлов.

Что нового — lifetime loop store = граница формы (FIXED)

Тестер (churn tensor classifier, рекурсивный лес): RSS-пик рос как O((деревья × глубина)²) — 4 дерева d=6 → +2.9 ГБ. Виновник — промоут выживших while-биндингов в бессмертный root при каждом выходе, даже когда биндинг никому не нужен.

  • Контракт владения вместо новой сущности: loop store и res-скоупы while — heap Scope с track_dtor в scratch-арене (эпоха = момент регистрации); умирают на первом restore, пересекающем эпоху (итерация объемлющего цикла или граница формы). Промоут в root при выходе удалён — побег обслуживают существующие мосты.
  • finish_loop_bindings удалён: записи живут в LoopStoreDrop своего store, teardown освобождает выжившие цепочки сразу перед смертью store.
  • Rehome по стеку store'ов (внутренний → внешний); append/suffix продлевают цепочку в домашнем store — цепочка никогда не тянется через два store (класс SIGSEGV из v2.7.4 закрыт структурно).
  • Zero-copy adoption: биндинг, чья пара переживает убийствующий restore, адоптируется в самый внешний store, умирающий вместе с парой — переезд wholesale, ноль копий. Scope::adopt сливает dying store в enclosing.
  • Новый сьют tests/loop_lifetime.qlsp (12 deftests: семантика чтения после while, вложенный общий аккумулятор, re-entrant, suffix, throw-recovery, тензор-ребайнд).

Production-check (RSS): выбрасывающий build ×20: 745 МБ → 4 КБ (плоско). Лес 10 деревьев: 34.5 МБ ≈ линейно (было умножение копий по уровням). 10 discard make-big(20000): 13248 КБ → 484 КБ. ASan: UAF/overflow нет.

QLISP v2.7.5 — O(1) spine-append для setq-накопителей

Choose a tag to compare

@FQingLars FQingLars released this 02 Oct 06:03

QLISP 2.7.5 — Release Notes

Тег: v2.7.5 · Платформы: Linux x86_64, Windows x86_64
Бинарники — сборка CI (Linux: GCC/Ninja/OpenBLAS/OpenMP; Windows: MSYS2 MinGW64), коммит d431c57 ветки main компиляторного репозитория (CI run 36707065329, зелёный). Состав: qlisp (REPL/интерпретатор + JIT), qlisp-lsp, qvalent.

Файл Платформа Состав
qlisp-linux-x86_64 Linux x86_64 REPL/интерпретатор + JIT
qlisp-lsp-linux-x86_64 Linux x86_64 Language Server
qvalent-linux-x86_64 Linux x86_64 пакетный менеджер
qlisp-windows-x86_64.zip Windows x86_64 qlisp.exe, qlisp-lsp.exe, qvalent.exe

SHA256SUMS — контрольные суммы всех файлов. Рантайм без LLVM: ldd qlisp — только OpenBLAS/GOMP/libstdc++.

Что нового — O(1) spine-append для setq-накопителей (FIXED)

Тестер: (setq acc (cons x acc)) в цикле давал квадратичные время и память (глобальный аккумулятор n=2000 → 210 МБ, n=12000 → 6.6 ГБ).

  • O(1) spine-append: новый элемент re-home'ится, хвост переиспользуется по указателю (prim_cons не клонирует — инвариант точен). Захваченные кадры (defun) покрывает то же условие: fast-path setq теперь работает и по captured-биндингам.
  • rehome_loop_binding переведён на append + suffix-скан (setq a (cdr a)) (освобождает ровно пропущенный префикс); записи сканируются base-скоупед — вложенный while со своим setq пушит свою запись (тень), не затирая внешнюю.
  • finish_loop_bindings больше не промоутит запомненное значение записи (терял элементы) — промоутится текущее значение биндинга, цепочка освобождается cdr-спин-волком.
  • do_while не клонирует re-homed значение в ping-pong скоупы; результат клонируется в root один раз перед finish.
  • clone_to для CONS — итеративен по cdr-спайну (car-деревья рекурсивно): длинный аккумулятор не сжигает стек.

Production-check (RSS): глобальный n=2000: 210 МБ → 0 МБ дельты; n=12000: 6.6 ГБ → 1.8 МБ (линейно). Локальный n=8000: 2.1 с → 0.14 с. Корпус 68/68; tests/setq_spine.qlsp 16/16 за 0.8 с; ASan чисто.

QLISP v2.7.4 — память: эвикция пула, cons-блоки, guard глубины

Choose a tag to compare

@FQingLars FQingLars released this 27 Sep 16:16

QLISP 2.7.4 — Release Notes

Тег: v2.7.4 · Платформы: Linux x86_64, Windows x86_64
Бинарники — сборка CI (Linux: GCC/Ninja/OpenBLAS/OpenMP; Windows: MSYS2 MinGW64), коммит 5e054ca ветки main компиляторного репозитория (CI run 36332096385, зелёный). Состав: qlisp (REPL/интерпретатор + JIT), qlisp-lsp, qvalent.

Файл Платформа Состав
qlisp-linux-x86_64 Linux x86_64 REPL/интерпретатор + JIT
qlisp-lsp-linux-x86_64 Linux x86_64 Language Server
qvalent-linux-x86_64 Linux x86_64 пакетный менеджер
qlisp-windows-x86_64.zip Windows x86_64 qlisp.exe, qlisp-lsp.exe, qvalent.exe

SHA256SUMS — контрольные суммы всех файлов.

Что нового — память под давлением

Пул тензоров: эвикция

  • Дефолтный лимит пула буферов 1 ГБ → 256 МБ; при промахе точного размера на 3/4 лимита эвиктируется крупнейшая корзина free-list. Production-check: 120k тензоров разных размеров — плато RSS 1.13 ГБ (при нулевых живых данных) → пик 52 МБ.

ConsCellPool: мелкие блоки

  • Блоки 1 М ячеек (24 МБ) → 64k ячеек (1.5 МБ) — ретеншн пика ограничен, ОС отдаёт блоки естественно. 20k cons setq: пик 34.7 МБ (без регресса против 2.7.3).

Guard глубины рекурсии

  • Лимит 10 000 eval-кадров (~3 400 QLisp-кадров; 8 МБ стек физически падает на ~12 000). Превышение — ловимая ошибка: eval: recursion depth exceeded 10000 (raise the limit with EVAL-MAX-DEPTH).
  • (EVAL-MAX-DEPTH n) поднимает лимит и возвращает старый, (EVAL-MAX-DEPTH) читает; счётчик RAII — после пойманной ошибки eval полностью жив. Windows-бинарник резервирует 8 МБ стека (-Wl,--stack=0x800000); безопасный потолок ручного лимита ~11 000.

Итеративное ядро

  • equal по cdr-цепочкам и stdlib length/reverse/member/last/butlast/nth переписаны итеративно — рекурсивный length сжигал кадр на элемент и упирался бы в guard на списках ~3.5k+.

Попутно исправлено

  • Вложенный while стирал записи loop_setq_ внешних циклов (zombie-nullptr → SIGSEGV); finish_loop_bindings(base) продвигает и обрезает только свои записи.
  • Sandbox alloc-бюджет теперь считает кумулятивно (cells_allocated_total()): не откатывается restore'ом while, циклы ловятся.

Тесты: 67 сюит зелёных; новый tests/memory_pools.qlsp (7). Регресс 75/75.

QLISP v2.7.3 — HibLin OOM-фиксы: loop store и автоочистка ленты

Choose a tag to compare

@FQingLars FQingLars released this 27 Sep 16:15

QLISP 2.7.3 — Release Notes

Тег: v2.7.3 · Платформы: Linux x86_64, Windows x86_64
Бинарники — сборка CI (Linux: GCC/Ninja/OpenBLAS/OpenMP; Windows: MSYS2 MinGW64), коммит bddf9a5 ветки main компиляторного репозитория (CI run 36245817114, зелёный). Состав: qlisp (REPL/интерпретатор + JIT), qlisp-lsp, qvalent.

Файл Платформа Состав
qlisp-linux-x86_64 Linux x86_64 REPL/интерпретатор + JIT
qlisp-lsp-linux-x86_64 Linux x86_64 Language Server
qvalent-linux-x86_64 Linux x86_64 пакетный менеджер
qlisp-windows-x86_64.zip Windows x86_64 qlisp.exe, qlisp-lsp.exe, qvalent.exe

SHA256SUMS — контрольные суммы всех файлов.

Что нового — HibLin OOM-фиксы (production-чеки закрыты)

Память: setq в цикле больше не растит мир

  • setq по let-привязке, обновляемой в while, теперь re-home в loop store с явными правилами владения. До фикса promote-в-root для всех привязок давал O(n²)/линейный immortal-рост: 20k cons-setq в цикле — 12.5 ГБ (OOM), setq тензора 64x64 — +82 МБ на прогон.
  • Production-check RSS (до → после): 20k cons setq — 12.5 ГБ (OOM) → пик 35 МБ; 5k tensor setq — +82 МБ → пик 32 МБ.

Автоград: автоочистка ленты на границе формы

  • reset_scratch → seal() запечатывал любой un-backpropagated граф в stable-память: 30k форм с градиентами без GRAD! — +494 МБ навсегда. Теперь сохраняются только defvar-графы, остальные сбрасываются на границе формы (пик 31.7 МБ).

Тесты: 66 сюит зелёные; новые tests/memory_setq.qlsp (7) и tests/tape_autoclear.qlsp (3). Регресс 74/74.

QLISP v2.7.2 — Tablet: детерминированный DataFrame-аналог pandas

Choose a tag to compare

@FQingLars FQingLars released this 23 Sep 18:15

QLISP 2.7.2 — Release Notes

Тег: v2.7.2 · Платформы: Linux x86_64, Windows x86_64
Бинарники — сборка CI (Linux: GCC/Ninja/OpenBLAS/OpenMP; Windows: MSYS2 MinGW64), коммит 9fd8d66 ветки main компиляторного репозитория (CI run 35897601582, зелёный). Состав: qlisp (REPL/интерпретатор + JIT), qlisp-lsp, qvalent.

Файл Платформа Состав
qlisp-linux-x86_64 Linux x86_64 REPL/интерпретатор + JIT
qlisp-lsp-linux-x86_64 Linux x86_64 Language Server
qvalent-linux-x86_64 Linux x86_64 пакетный менеджер
qlisp-windows-x86_64.zip Windows x86_64 qlisp.exe, qlisp-lsp.exe, qvalent.exe

SHA256SUMS — контрольные суммы всех файлов. Рантайм без LLVM: ldd qlisp — только OpenBLAS/GOMP/libstdc++.

Что нового

Tablet — детерминированный DataFrame-аналог pandas (T0–T9 закрыты)

  • Новый вшитый модуль stdlib/tablet.qlsp (~1300 строк чистого QLisp): tablet/tablet-from-rows, tcol/tcols-pick/trow/tloc/tiloc/twhere, thead/ttail, tdtypes, tastype, tcategorical, tstr-*, tiso-format.
  • Стабильные сортировки (tsort, NA всегда в конец), tunique/tvalue-counts (тайбрейки по первому появлению), NA-дисциплина (tisna/tfillna/tdropna).
  • Группировки и соединения: tgroupby/tgroup-agg (sum/mean/count/min/max/first/last), tmerge (inner/left/right/outer с зафиксированным порядком), tappend.
  • Статистика и окна: tsum/tcol-mean/tcov/tcorr, tcumsum/tcummax/tcummin, trank (average-tie), tshift/tdiff, trolling/texpanding.
  • I/O: tcsv-read (сам типизирует колонки; RFC-4180 с кавычками и переводами строк в полях), tcsv-write, tjson-rows/tfrom-json-rows, tcol->tensor (числовая колонка без NA → Tensor F32).
  • Контракт детерминизма: вывод побитово воспроизводим — порядок вставки, стабильные сортировки, отсортированные ключи groupby, зафиксированный порядок merge; tests/tablet.qlsp — 156 проверок, включая батарею детерминизма (двойной прогон, immutability chain).
  • MultiIndex — явно вне области видимости модуля.

Ядро

  • Строгий if: ровно 2–3 аргумента; четвёртая форма — ошибка программы («if: too many forms (use cond or progn for branches)»), JIT-обход зеркалит проверку (TEMP_ISSUES #36).
  • io: read-csv разворачивает переводы строк внутри кавычек (RFC-4180).
  • datetime: гражданский календарь epoch→ISO для tiso-format.

Инструменты

  • tools/qlsp-check.py — pre-commit проверка stdlib через диагностики qlisp-lsp и defun-outline; AGENTS.md фиксирует обязательный прогон.

Тесты: 64 сюита зелёные (Release, Linux), включая tablet.qlsp.