Skip to content

Releases: KUARU-dotcom/Lupus

Lupus V0.6.0

Choose a tag to compare

@KUARU-dotcom KUARU-dotcom released this 28 Oct 12:36

Lupus V0.6.0 — семантика, GC, сеть, асинхронность, встраивание

BREAKING CHANGES (от 0.5.x)

  • and/or возвращают значение (схема Scheme), а не только булево.
  • () — литерал пустого списка, а не none.
  • head/tail/nth/empty?/contains?/length на неверном типе →
    type-mismatch (ранее местами молчаливое none).
  • Конструкторы defstruct проверяют конкретные типы полей.
    Подробности: docs/ERRATA.md §13, раздел BREAKING CHANGES V0.6.

Новое

  • GC: conservative mark-and-sweep разрывает циклы
    env → контейнер → closure → env (#47): утечка 17.1 МиБ → 80 Б в тесте;
    пауза 8.3 мс на 20k живых замыканий; (gc-collect); порог LUPUS_GC_THRESHOLD.
  • texas (сеть, §3.3): tcp/udp, все ошибки — значения (failure "net: …"),
    таймауты чтения 5 с.
  • lappland: (lappland/malice p), (lappland/delay k) — инъекция отказов
    и задержек для сетевых вызовов; детерминизм через LUPUS_MALICE_SEED.
  • amiya (async, §3.5): spawn/channel/send/recv/recv-timeout/wait/wait-all;
    snapshot-семантика spawn; Socket/Listener/Task не маршалируются.
  • kennel (host-API): профили pure/core/full, Host::register_native,
    run_program; host-нативы под префиксом host/.
  • fuel (#35, #36): лимит шагов LUPUS_FUEL=N / Config.max_steps;
    (set-fuel! n) только уменьшает потолок; исчерпание → exhausted.
  • eval --import w,senko "" — пре-импорт пакетов в REPL-режиме.
  • Семантика: политика типов унифицирована, проверки конструкторов (ERRATA §13).

Метрики

  • 285 тестов; golden 46 / negative 136; LiF 3/3.
  • Fuzz 10 000 программ (20 000 в CI): 0 паник, 0 таймаутов.
  • Oracle-дифференциал против v0.4.0: 118 файлов, 94 pass / 0 fail / 24 skip.
  • fib(25): медиана 309 мс (перф-гейт 315 мс в CI).
  • Коды ошибок: +profile-denied, fuel-raise-denied, exhausted, host-error.

Бинарники

Linux x86_64 + Windows x86_64 (macOS не поставляется: нужен osxcross).

Разработка

Архитектура: Qwen3.8 Max / Qwen3.7 Max. Код: DeepSeek V4.1 Flash (OpenCode).
Аудит: агентская сеть «NikoGPT» (DeepSeek V4.1 Flash).

Lupus V0.5.3

Choose a tag to compare

@KUARU-dotcom KUARU-dotcom released this 28 Oct 07:48

Release Notes — Lupus V0.5.3

Дата: 2026-10-28
Тег: v0.5.3
Коммит: см. тег v0.5.3

Что нового

Утечка памяти в кэше модулей закрыта (#45)

Определение функции через lambda в одном процессе теряло память: цепочка
окружение → замыкание → окружение образовывала Rc-цикл, который не
разбирался при выходе. На CLI это было не видно (процесс живёт один запуск),
но Interpreter — публичный API библиотеки, и хост, крутящий много коротких
скриптов в одном процессе, тёк на каждое определение.

Замер: 20 000 прогонов одного и того же исходника в одном процессе.

Сценарий До После
(+ 1 2) (контроль) +0.2 МБ +0.2 МБ
(import fnmod) (fnmod/inc 1) +21 МБ +0.2 МБ
(define f (lambda (x) (+ x 1))) (f 1) +21 МБ +0.2 МБ

Закреплено тестом tests/memory.rs, который проверяет именно разрыв цикла
через Weak::upgrade(), а не размер RSS — флака не будет.

Встроенные функции стали значениями

Раньше (list-map (list 1 -2) abs) падало с «Переменная 'abs' не определена»:
встроенные функции не были значениями. Теперь они первоклассные:

(list-map (list 1 -2) abs)                             ; → (1 2)
(define f head) (f (list 1 2))                         ; → (some 1)
(import senko) (define root senko/sqrt) (root 81.0)    ; → 9.0

Добавлены list-filter и list-fold. Внутри таблица builtins заменила
матч на ~300 строк.

Runtime-ошибки теперь с позицией

Ошибки, возникшие при вычислении узла AST, больше не имеют location = null:

{"phase":"runtime","code":"type-mismatch","message":"+ требует чисел",
 "location":{"file":"/tmp/loc.lupus","line":2,"col":1,
             "span":{"start":13,"end":22}}}

Это расширение схемы §6.1. location = null остаётся только там, где ошибка
не привязана к исходнику: io-error до разбора, отказ spawn,
no-tests-found.

Фаззинг

В репозитории появилась фаззинг-инфраструктура: cargo-fuzz с таргетами
parse_eval и lexer, workflow по расписанию каждые 6 часов, затравка
корпуса из tests/golden и examples, сохранение артефактов, автосоздание
issue при находке. Первые прогоны: lexer — 2.4 млн исполнений на cov: 747,
parse_eval — 293 тыс. на cov: 3649, падений нет.

Breaking changes от V0.5.2

  • location в runtime-ошибках. Кто парсит JSON по схеме §6.1 и ожидает
    location = null для runtime, увидит объект. Изменение расширяющее, но
    поведение другое.
  • Ошибки без кода больше не классифицируются по тексту. Удалён
    Error::new / infer_code; код ошибки теперь всегда задаётся явно. На
    пользователя не влияет, на сторонние use lupus::error::Error — влияет.

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

  • #47: фикс #45 закрывает циклы окружение → замыкание → окружение, но
    не циклы через контейнеры (окружение → список → замыкание → окружение).
    (define-mutable l (list)) (set! l (append l (list (lambda () 1)))) течёт
    по-прежнему. Списки, накапливающие лямбды в глобальной переменной, —
    основной риск для встраивания (kennel, V0.6). Полное решение требует GC
    или обхода значения при define/set!.
  • #35 / #36: в интерпретаторе нет лимита вычислительных шагов (fuel).
    Скрипт с бесконечным циклом подвешивает процесс — для встраивания в чужой
    хост это неприемлемо. Планируется fuel-exhausted в V0.6.
  • HM-тайпчекер не реализован (V1.0). Аннотации типов проверяются
    синтаксически.
  • Tensor (exusiai) отложен в V2.0.
  • macOS-сборка не поставляется (нужен Apple SDK).

Метрики

Метрика V0.5.2 V0.5.3 Δ
Тестов cargo 217 231 +14
Кодов ошибок 32 32 0
Линий в interpreter.rs ~1420 ~715 −50%
Утечка на 20k определений +21 МБ +0.2 МБ −99%

Установка

wget https://github.com/KUARU-dotcom/Lupus/releases/download/v0.5.3/lupus-v0.5.3-linux-x86_64.tar.gz
tar xzf lupus-v0.5.3-linux-x86_64.tar.gz
./lupus --version

Из исходников:

git clone https://github.com/KUARU-dotcom/Lupus.git
cd Lupus && cargo build --release
./target/release/lupus --version

Разработка

  • Архитектура и спецификация: Qwen3.8 Max / Qwen3.7 Max
  • Реализация: DeepSeek V4.1 Flash
  • Аудит и фаззинг: NikoGPT (github.com/nikogpt-bot; мультимодельная
    агентская платформа, аудит выполнен на DeepSeek V4.1 Flash 1017) —
    фаззинг-инфраструктура, обнаружение утечки #45, триаж ложных находок

Документация

Lupus V0.5.2

Choose a tag to compare

@KUARU-dotcom KUARU-dotcom released this 25 Oct 04:59

Lupus V0.5.2 — патч-релиз по дельта-аудиту

Закрыто (находки дельта-аудита NikoGPT к v0.5.1):

  • #33 (major): комбинирующие знаки (Mn/Mc) допустимы в продолжении идентификатора
    (NFD-café, ко́фе работают); знак первым символом — по-прежнему unknown-token;
    NFC-нормализация источника отложена в V1.0.
  • #31 (major): любая usage-ошибка CLI (нет позиционного аргумента, лишние
    позиционные, флаг без команды, голый вызов) → exit 2 + usage в stderr,
    stdout пустой, JSON нет. --help/-h остался успешным путём (rc 0).
  • #34 (minor): -<буква> трактуется как неизвестный флаг (exit 2), а не как имя
    файла; -<цифра> и одиночный - остались позиционными.
  • #32 (minor): число с буквенным хвостом (1a) → lex-ошибка unknown-token
    с позицией вместо молчаливого разбиения на два токена.

Тестов: 217. Гейты: clippy/fmt чисто, validate_tasks 100/100, LiF 3/3,
fuzz 10 000 программ / 0 паник, oracle (обязательный режим) 109 файлов /
93 pass / 0 fail. ERRATA: §12.
Бинарники: Linux x86_64 + Windows x86_64 (macOS не поставляется: нужен osxcross).

Lupus V0.5.1

Choose a tag to compare

@KUARU-dotcom KUARU-dotcom released this 25 Oct 01:53

Lupus V0.5.1 — патч-релиз

Закрыто по аудиту NikoGPT (issues #23–#30, BUG-40, BUG-41):

  • #24: lupus test без тестов → exit 1, код no-tests-found
  • #30: симлинки больше не дублируют прогоны (canonicalize + без следования по симлинкам)
  • #25: BOM в начале файла пропускается
  • #26: колонки в диагностике — в символах, не в UTF-8 байтах
  • #27: суррогатные пары \uXXXX собираются в scalar; одинокий суррогат → invalid-escape
  • #29: неизвестные escape → ошибка invalid-escape с позицией
  • #28: неизвестный CLI-флаг → exit 2 + plain-text usage (не ошибка языка)
  • BUG-41: отказ spawn потока → JSON io-error, без паники
  • BUG-40: README — раздел «Бенчмарк», пути results/, базовая линия merged-lupus-2bv2
  • #23: Unicode-идентификаторы (кириллица и др. alphabetic); emoji по-прежнему unknown-token
  • Docs: семантика захвата в циклах (while — позднее связывание, for — значение итерации),
    ERRATA §10
  • ERRATA: / в символьном токене (qualified-имена семантически идентичны)

Тестов: 204 (+6). Гейты: clippy/fmt чисто, validate_tasks 100/100,
fuzz 10 000 программ / 0 паник, oracle 107 файлов / 92 pass / 0 fail.

Бинарники: Linux x86_64 + Windows x86_64. macOS не поставляется (требует osxcross).

Lupus V0.5.0

Choose a tag to compare

@KUARU-dotcom KUARU-dotcom released this 23 Oct 21:37

Release Notes — Lupus V0.5.0

Дата: 2026-10-25
Тег: v0.5.0
Коммит: 68d186c

Что нового

Модульная система

  • (import senko), (import kaltsit), (import w) — нативные пакеты в Rust
  • Префиксы: senko/pi, kaltsit/read-file, w/assert-eq
  • Модификаторы :as и :all (:all под линтом import-collision)
  • Файловые модули с кэшем загрузки (исполняются ровно один раз)
  • Детекция циклических импортов (import-cycle)
  • Env-переменная LUPUS_PATH для пользовательских каталогов модулей

Нативная стандартная библиотека (Rust, без Python-FFI)

  • senko (math): pi, e, sqrt, sin, cos, tan, pow, log, log10, abs, floor, ceil, round, min, max
  • kaltsit (file): read-file, write-file, append-file, exists?, is-dir?, list-dir, mkdir, delete, size
  • w (test): форма (test "имя" body...), assert-eq/true/false, JSONL-вывод по §5.3

Новые типы

  • Map — ассоциативные массивы: map-get, map-set, map-keys, map-values, map-has?
  • Дженерик-структуры: (defstruct (Node a) (value a) (next (Option (Node a))))

JSON-ошибки (§6 спеки V1.0)

  • stderr всегда строгий JSON с полями severity, phase, code, message, location, hint, context
  • Флаг --pretty для человекочитаемого рендера
  • 32 кода ошибок, включая новые: integer-overflow, invalid-exit-code,
    stack-depth-exceeded, nesting-too-deep, io-error, import-collision, import-cycle

CLI

  • lupus run <file> (и по умолчанию)
  • lupus test <path> — прогон тестов с JSONL-выводом
  • lupus check <file> — линтер (unused-variable, core-shadowing, missing-return-type и др.)
  • lupus ast <file> — JSON-сериализация AST (§7 спеки)
  • lupus eval "<expr>" — REPL для одного выражения
  • Флаги: --pretty, --verbose, --no-lint, --json, --lenient-parens, --version

Тест-система LiF фаза 2

  • Fuzz: 10 000 программ локально, 20 000 в CI (env LUPUS_FUZZ_N)
  • Oracle-дифференциал против v0.4.0: 104 файла, 92 PASS / 0 FAIL / 12 SKIP
  • Coverage map: 111 символов языка с positive+negative ссылками
  • Структурированные генераторы: random, edge_cases, type_mix, modules, strings

Безопасность рантайма

  • Лимит глубины рекурсии: 10 000 (stack-depth-exceeded вместо SIGSEGV)
  • Лимит вложенности скобок: 1 000 (nesting-too-deep вместо паники парсера)
  • Проверенная арифметика: checked_div/checked_add/checked_mul — ни одной паники на i64::MIN
  • Eval в отдельном потоке со стеком 1 GiB (обоснование: debug-сборка переполняет
    стандартный стек раньше логического лимита)

Breaking changes от V0.4

  • FFI через Python заменён нативными модулями. Директива (#lupus ffi python "...")
    теперь даёт ошибку линта invalid-directive с hint о замене.
  • Negative-тесты: .error-файлы теперь содержат код ошибки (одна строка), а не
    русскую подстроку. Харнес lif матчит поле code из JSON stderr.
  • run_experiment.py: детект ошибок только по returncode != 0, без подстрок stdout.
  • (exit n): валидация 0..=255, иначе runtime-ошибка invalid-exit-code.
  • Арифметика i64: переполнения дают integer-overflow вместо паники.

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

  • HM-тайпчекер не реализован (отложен в V1.0). Аннотации типов в define-public
    проверяются только синтаксически (наличие -> и типов параметров).
  • Tensor (exusiai) отложен в V2.0.
  • macOS-сборка: кросс-компиляция требует Apple SDK (osxcross), бинарники не поставляются.
  • Oracle-дифференциал: для exit≠0 сравнивает stdout по префиксу (V0.4.0 печатал
    диагностику в stdout, V0.5 — JSON в stderr). Расхождение в хвосте текста ошибки
    дифференциалом не ловится.

Метрики

Метрика V0.4.0 V0.5.0 Δ
Тестов cargo 115 198 +72%
Golden-файлов 17 34 +100%
Negative-файлов 71 108 +52%
Fuzz-программ 2 000 10 000 (20 000 в CI) ×5 (×10)
Oracle-файлов 34 104 +206%
Кодов ошибок ~25 32 +7
Покрытие спеки V1.0 ~35% ~65–70% +30 п.п.

Установка

# Из релизного архива
wget https://github.com/KUARU-dotcom/Lupus/releases/download/v0.5.0/lupus-v0.5.0-linux-x86_64.tar.gz
tar xzf lupus-v0.5.0-linux-x86_64.tar.gz
./lupus --version

# Из исходников
git clone https://github.com/KUARU-dotcom/Lupus.git
cd Lupus
cargo build --release
./target/release/lupus --version

Разработка

  • Архитектура и спецификация: Qwen3.8 Max / Qwen3.7 Max
  • Реализация: DeepSeek V4.1 Flash (через OpenCode)
  • Аудит: NikoGPT (github.com/nikogpt-bot; мультимодельная агентская платформа,
    аудит выполнен на DeepSeek V4.1 Flash 1017) — независимый аудит rc1/rc2,
    выявление блокеров, проверка borrow-паник в RefCell, кэша модулей, oracle-логики
  • Стоимость релиза: ~$0.20 (суммарно все агентские сессии)

Документация

Lupus V0.4.0

Choose a tag to compare

@KUARU-dotcom KUARU-dotcom released this 13 Sep 17:08

Lupus V0.4.0

Расширение языка поверх V0.3: числа с плавающей точкой, кортежи, пользовательские
структуры, цикл loop/exit, а также выпускные ворота — тест-система LiF.

  • Бинарники в этом релизе собраны из тега v0.4.0 (не из рабочей копии).
  • Тест-система LiF: 17 golden / 70 negative / 64 символа в карте покрытия.
  • Бенчмарк merged-lupus-2bv2: 81/100, без регрессии к V0.3
    (модель ещё не дообучена на синтаксисе V0.4).

Область изменений (скоуп)

Область Статус
Float: литералы, арифметика, деление IEEE, конверсии, равенство добавлено
Tuple: (tuple ...), match-паттерн, равенство, печать добавлено
defstruct: конструктор, аксессоры, match-паттерн добавлено
loop / exit добавлено
Тест-система LiF (golden/negative/map покрытия) добавлено

Числа с плавающей точкой (Float)

Литералы 3.14, 2.5e-3, 0.5 (литералы Number::Float); арифметика
int+int=int, float+float=float, смешивание int+float — runtime-ошибка.
Деление: int/0 — ошибка; float/0.0 → inf, float/(- 0.0) → -inf (IEEE, без
ошибки). % с float — ошибка. Конверсии int->float, float->int (усечение к
нулю), str->float, float->str. Равенство: (= 1 1.0) → false.
Унарный минус работает и для float: (- x) отрицает число с плавающей точкой,
(- 0.0 x) — разность двух float (в т.ч. получение -0.0 через (- 0.0)).

Кортежи (Tuple)

(tuple 1 "a" true) — арность 0+ любая. Доступ только через match-паттерн
(tuple a b c); несовпадение арности — runtime-ошибка. Равенство поэлементное;
печать (tuple 1 "a").

Структуры (defstruct)

(defstruct point (x int) (y int)) — аннотации типов парсятся, но не проверяются.
Автогенерация конструктора (point 10 20) и аксессоров (point-x p). Аксессор на
чужую структуру — ошибка. Дубликат имени поля — ошибка duplicate-struct-field.
match-паттерн ((point x y) ...) связывает поля позиционно.

Цикл loop/exit

(loop тело...) — бесконечный цикл; (exit n) — немедленное завершение процесса
с кодом n.

Тест-система LiF (выпускные ворота)

tests/golden/ (точный stdout, exit 0), tests/negative/ (подстрока ошибки,
exit ≠ 0) и tests/coverage_map.toml (карта покрытия: у каждого символа ≥1
positive и ≥1 negative). Харнес tests/lif.rs прогоняет всё при cargo test и
проваливает сборку при падении любого файла.

Устойчивость лексера: комментарий с одиночной ;

Одиночная ; (не обязательно ;;) теперь начинает комментарий до конца строки.
Раньше одинокий ; вне строки не потреблялся лексером и приводил к зависанию
(бесконечный цикл токенизации). Символов с ; в языке нет, поэтому семантика
валидных программ не изменилась. Добавлен регрессионный тест и guard-таймаут
5 секунд в харнесе LiF (никакой .lupus не может повесить cargo test).


Обсуждение: #21

Lupus V0.3.1

Choose a tag to compare

@KUARU-dotcom KUARU-dotcom released this 11 Sep 23:47

Lupus V0.3.1

Релиз-фикс поверх V0.3.0: исправления гигиены репозитория и метаданных сборки.
Семантика интерпретатора и тесты не менялись.

Исправления

Область Что сделано
Версия Cargo.toml/Cargo.lock приведены к 0.3.1 (в V0.3.0 было 0.2.0 при теге v0.3.0)
CLI добавлены флаги --version / -V → Lupus 0.3.1 (через CARGO_PKG_VERSION)
Гигиена удалён мусор (subprocess, RELEASE_NOTES.md), results-файлы консолидированы в results/, спека перенесена в docs/, дедупликация legacy/ + legacy/README.md, добавлен .editorconfig, сняты exec-биты с данных
Сборка релизный профиль: opt-level=3, lto, codegen-units=1, strip, panic="abort"; rust-toolchain.toml; build_release.sh приведён к реальному процессу
Размер бинарника Linux x86_64: ~428 КБ (stripped) — при opt-level=3; сравнение скорости vs opt-level=z (fib(30)): ~2.9 c против ~5.2 c

Бинарники собраны строго из тега v0.3.1.

Артефакты

  • lupus-v0.3.1-linux-x86_64.tar.gz — Linux x86_64 (glibc): lupus + LICENSE + README.md
  • lupus-v0.3.1-windows-x86_64.zip — Windows x86_64: lupus.exe + LICENSE + README.md
  • SHA256SUMS-v0.3.1 — контрольные суммы

Сборка и проверки:

  • cargo test — 74 теста (72 integration + 2 doc), 0 failed
  • cargo clippy --all-targets — 0 warnings
  • cargo fmt --check — чисто
  • ./lupus --version → Lupus 0.3.1

Lupus V0.3.0

Choose a tag to compare

@KUARU-dotcom KUARU-dotcom released this 11 Sep 22:39

Заменён релизом v0.3.1 (корректные метаданные версии и оптимизация сборки). Сохранён для истории.

Lupus V0.2

Choose a tag to compare

@KUARU-dotcom KUARU-dotcom released this 09 Sep 17:25
68a7da6

🐺 Lupus V0.2 — The Rust Rewrite

Lupus V0.2 — это первый стабильный релиз интерпретатора, полностью переписанный на Rust. Мы отказались от Python-прототипа в пользу производительности, строгой типизации и модульной архитектуры.

Этот релиз знаменует переход от "эксперимента в одном файле" к полноценному языковому ядру.

🚀 Что нового

⚡ Полная переписка на Rust

Интерпретатор теперь работает на Rust. Это дало нам:

  • Мгновенный запуск: Никаких накладных расходов на старт Python VM.
  • Безопасность памяти: Строгая типизация на этапе компиляции интерпретатора.
  • Модульность: Код разделен на логические компоненты (lexer, parser, ast, interpreter, environment), что упрощает поддержку и развитие.

🧠 Результаты бенчмарка (LLM Coding)

Мы протестировали дообученную модель Qwen 2.5 (merged-lupus-2bV2) на наборе из 100 алгоритмических задач.

  • Общий Pass Rate: 81% (81/100 задач решены верно).
  • Арифметика и Логика: 100% (идеальное понимание базовых операций).
  • Циклы и Списки: ~85-90% (уверенная работа с while, list, nth).
  • Рекурсия: ~80% (факториалы, Фибоначчи, GCD работают стабильно).

Сравнение: Базовая модель без дообучения (Qwen 3.5 2B) показывала ~45% на тех же задачах. Дообучение на датасете Lupus дало прирост +36%.

🛠 Технические детали реализации

  • Tree-Walk Interpreter: Классическая архитектура обхода AST.
  • Lexical Scoping: Корректная работа замыканий (lambda) и областей видимости.
  • Error Handling: Понятные сообщения об ошибках с указанием строки и колонки (на русском языке).
  • Built-ins: Реализованы все базовые функции спецификации V1.0 (print, int->str, string-append, list, nth, length, арифметика).

📦 Установка и запуск

Готовые бинарники

Скачайте архив для вашей ОС в разделе Assets ниже:

  • lupus-v0.2.0-linux-x86_64.tar.gz
  • lupus-v0.2.0-windows-x86_64.zip
# Linux
tar -xzf lupus-v0.2.0-linux-x86_64.tar.gz
./lupus hello.lupus

# Windows
Expand-Archive lupus-v0.2.0-windows-x86_64.zip
.\lupus.exe hello.lupus

Сборка из исходников

Требуется установленный Rust toolchain.

git clone https://github.com/KUARU-dotcom/Lupus.git
cd Lupus
cargo build --release
./target/release/lupus examples/hello.lupus

📝 Пример кода (Lupus)

;; Факториал с рекурсией
(define (factorial n)
  (if (= n 0)
    1
    (* n (factorial (- n 1)))))

(print (int->str (factorial 5))) ;; Вывод: 120

;; Работа со списками и циклами
(define-mutable sum 0)
(define-mutable i 1)
(while (<= i 10)
  (set! sum (+ sum i))
  (set! i (+ i 1)))

(print (int->str sum)) ;; Вывод: 55

🔜 Что дальше? (Roadmap)

В следующих версиях (V0.3+):

  • Расширение стандартной библиотеки (map, filter, fold).
  • Поддержка модулей и импортов.
  • Оптимизация хвостовой рекурсии.
  • FFI (вызов функций C/Rust).

Полная спецификация языка: Lupus V1.0 Specification

Lupus v0.1R Alpha

Lupus v0.1R Alpha Pre-release
Pre-release

Choose a tag to compare

@KUARU-dotcom KUARU-dotcom released this 30 Aug 14:23
23c9586

🐺 Lupus v0.1R Alpha

Исследовательский релиз — первый честный бенчмарк Lupus против Python на 5 LLM-моделях разного размера и точности квантования.

TL;DR

  • Lupus — Lisp-подобный язык, спроектированный под маленькие LLM (1.5–14B)
  • Гипотеза: «Lupus даёт ≥20% меньше ошибок, чем Python» ❌ не подтвердилась в zero-shot
  • Но обнаружен сильный эффект масштабируемости: Lupus растёт круче, чем Python
  • Фикс интерпретатора дал +10 п.п. на 2B бесплатно (35% → 45%)
  • 1-битный квант 27B-модели набирает 73% на Lupus — уровень честной 9B

📊 Результаты бенчмарка (100 задач)

Модель Lupus Python Разрыв
Qwen3.5-2B 45% 75% −30
Qwen3.5-4B 55% 93% −38
Qwen3.8-4B-distill 53% 96% −43
Qwen3.5-9B 74% 96% −22
Bonsai-27B (Q1_0, 1-bit) 73% 99% −26

Ключевое наблюдение: кривая Lupus идёт 45→55→74 (почти линейно), а Python насытился на 93-99%. Разрыв сужается с ростом модели — это главный сигнал в пользу гипотезы обучаемости.

Bonsai-27B: 1-битная квантованная 27B-модель (4.7 ГБ) показывает 73% на Lupus — паритет с Qwen3.5-9B (74%), при этом Python у неё почти идеален (99%). Преимущество в 3× параметров съедено экстремальной квантовацией: S-выражения оказались чувствительнее к шуму кванта, чем знакомый Python. Провалы Bonsai — те же классы ошибок (галлюцинации let/expt, иммутабельность, небаланс скобок), что подтверждает таксономию на шестой модели.

🔧 Что починили с v0.1e

  1. Полиморфный print — теперь принимает int, bool, str без явного int->str. Убрало ~15 ложных падений на арифметике.
  2. if без else — снято жёсткое требование 3 аргументов. Модели перестали падать на (if cond (print x)).
  3. Литералы true/false — добавлены в лексер, больше не нужно определять их через define.
  4. Скрипт бенчмарка — run_experiment.py с поддержкой --resume, --ids, --cat, --report.
  5. Шпаргалка LLM — lupus_cheatsheet.txt на ~800 токенов, единая для всех прогонов.

🧪 Методология

  • Интерпретатор: tree-walk на Python (~900 строк)
  • Бенчмарк: 100 задач × 2 языка = 200 генераций на модель
  • Промптинг: только системная шпаргалка, без few-shot
  • Верификация: детерминированная сверка stdout с эталоном
  • Температура: 0.1, max_tokens: 700
  • Thinking: отключён во всех прогонах (иначе Qwen3.5 сжигает все токены на reasoning)

📋 Таксономия провалов Lupus

Класс Пример Причина
Галлюцинации stdlib expt, append, let, string-reverse Модель тянет из Scheme/Common Lisp
Иммутабельность «Переменная sum не изменяемо» Забывает define-mutable перед set!
Небаланс скобок «Неожиданный токен: RPAREN» Классика S-выражений у малых моделей
Алгоритмические обратный порядок, off-by-one Ошибки логики, не синтаксиса

🎯 Выводы и следующие шаги

  1. Zero-shot сравнение некорректно — Python в преобучении на терабайтах кода, Lupus — на нуле. Разрыв ~30 п.п. это эффект данных, а не языка.
  2. Lupus масштабируется — на 9B в «чистых» категориях (arithmetic, logic, strings) уже паритет с Python.
  3. Квантование — отдельная ось качества — 1-bit 27B ≈ 4-bit 9B на Lupus; для редкого синтаксиса точность весит больше, чем сырой размер.
  4. Этап 2 (в работе): генерация датасета Lupus учителем (DeepSeek V4 Flash) → LoRA-дообучение 2B/4B → повторный бенчмарк. Честный тест гипотезы: «что легче выучить при равном объёме данных».
  5. Этап 3 (план): переписать интерпретатор на Rust для production-скорости.

api_client.py Не проверялся!

🐺 Lupus v0.1R Alpha

Research Release — the first honest benchmark of Lupus against Python on 5 LLM models of varying sizes and quantization precision.

TL;DR

  • Lupus is a Lisp-like language designed for small LLMs (1.5–14B)
  • Hypothesis: "Lupus yields ≥20% fewer errors than Python" ❌ did not hold in zero-shot
  • However, a strong scalability effect was discovered: Lupus scales steeper than Python
  • Interpreter fix gave +10 p.p. on 2B for free (35% → 45%)
  • 1-bit quantized 27B model scores 73% on Lupus — on par with a solid 9B model

📊 Benchmark Results (100 tasks)

Model Lupus Python Gap
Qwen3.5-2B 45% 75% −30
Qwen3.5-4B 55% 93% −38
Qwen3.8-4B-distill 53% 96% −43
Qwen3.5-9B 74% 96% −22
Bonsai-27B (Q1_0, 1-bit) 73% 99% −26

Key observation: The Lupus curve goes 45→55→74 (almost linear), while Python saturated at 93–99%. The gap narrows as model size increases — this is the main signal in favor of the learnability hypothesis.

Bonsai-27B: A 1-bit quantized 27B model (4.7 GB) achieves 73% on Lupus — parity with Qwen3.5-9B (74%), while its Python score is near-perfect (99%). The 3× parameter advantage is eaten up by extreme quantization: S-expressions turned out to be more sensitive to quantization noise than familiar Python. Bonsai's failures are the same error classes (hallucinations of let/expt, immutability, paren imbalance), confirming the taxonomy across a sixth model.

🔧 What Was Fixed Since v0.1e

  1. Polymorphic print — now accepts int, bool, str without explicit int->str. Eliminated ~15 false failures in arithmetic.
  2. if without else — removed the strict 3-argument requirement. Models no longer crash on (if cond (print x)).
  3. true/false literals — added to the lexer; no longer need to define them via define.
  4. Benchmark script — run_experiment.py with support for --resume, --ids, --cat, --report.
  5. LLM cheat sheet — lupus_cheatsheet.txt at ~800 tokens, unified across all runs.

🧪 Methodology

  • Interpreter: tree-walk in Python (~900 lines)
  • Benchmark: 100 tasks × 2 languages = 200 generations per model
  • Prompting: system cheat sheet only, no few-shot
  • Verification: deterministic stdout comparison against reference
  • Temperature: 0.1, max_tokens: 700
  • Thinking: disabled in all runs (otherwise Qwen3.5 burns all tokens on reasoning)

📋 Lupus Failure Taxonomy

Class Example Cause
Stdlib hallucinations expt, append, let, string-reverse Model draws from Scheme/Common Lisp
Immutability "Variable sum is not mutable" Forgets define-mutable before set!
Paren imbalance "Unexpected token: RPAREN" Classic S-expression issue for small models
Algorithmic reverse order, off-by-one Logic errors, not syntax

🎯 Conclusions and Next Steps

  1. Zero-shot comparison is unfair — Python has terabytes of code in pretraining, Lupus has zero. The ~30 p.p. gap is a data effect, not a language effect.
  2. Lupus scales — on 9B in "clean" categories (arithmetic, logic, strings) it already achieves parity with Python.
  3. Quantization is a separate quality axis — 1-bit 27B ≈ 4-bit 9B on Lupus; for rare syntax, precision matters more than raw size.
  4. Stage 2 (in progress): generating a Lupus dataset with a teacher (DeepSeek V4 Flash) → LoRA fine-tuning 2B/4B → re-benchmark. An honest test of the hypothesis: "what is easier to learn given equal data volume".
  5. Stage 3 (planned): rewrite the interpreter in Rust for production speed.

api_client.py Not tested!