В отпуске есть время подумать и исследовать. Я натолкнулся на несколько вещей и открытий для себя. Оказалось, что мне как программисту перестали быть нужны самые умные и дорогие ИИ‑модели. Оказывается, есть такой параметр «Cost per Task», и по этому параметру на первое место вырвалась модель GPT-5.6 Luna (max).

При этом, если вы пользуетесь Codex, она самая тупая в списке моделей. Artificial Analysis Intelligence Index у нее всего 38. Для сравнения, у самой умной GPT-6 Astra (max) этот индекс равен 53. В итоге цена выполненной Luna задачи составляет $0.18 против $3.26 у Astra. Разница почти в 20 раз.

Как я понимаю, бенчмарк «Cost per Task» высчитывается так: когда ставится нормальная, грамотно описанная задача, замеряется, сколько токенов было потрачено на ее выполнение. То есть не в формате «из ХЗ сделаю ТЗ», а в формате, когда в хорошо заданном вопросе уже содержится половина ответа.

Я сначала не поверил, что так и есть, и стал работать, используя самую тупую модель Luna в линейке. И знаете, какие меня ожидали результаты? У меня перестали кончаться 5-часовые лимиты и недельные лимиты. На тарифе за 20 баксов в месяц, Карл!:)

Притом что я программист, Codex не водит меня по кругу, и мне не требуется переключаться на более умную модель, чтобы она все‑таки смогла выполнить задачу, о которой я прошу уже в пятый раз. Я вижу, как многие вайбкодеры‑непрограммисты всегда выходят из ситуации: если ИИ водит тебя по кругу, включи более умную модель, и она точно решит проблему. Да, это правда: для неквалифицированных программистов это работает, а для квалифицированных лишено смысла, если они, конечно, не обленились и вообще не выключили мозг.

То есть ситуация такая: даже самые дешевые и самые тупые фронтирные модели стали достаточно умными. Если ты разбираешься в теме, их уровня хватает за глаза. Похоже, гонка за тем, у кого модель умнее, подходит к концу. Но я столкнулся с другой проблемой: скоростью.

Особенно это заметно на DeepInfra и OpenRouter. Сейчас средняя скорость генерации на более‑менее нормальных моделях составляет 25–50 токенов в секунду. Даже Luna у меня в Codex выполняет задачу в среднем за 5–15 минут. Для агентского режима это очень медленно. Это начинает раздражать.

Если взять модель DeepSeek‑V4.1-Flash напрямую через API DeepSeek, скорость там достигает 300 токенов в секунду. Заметьте: задача выполняется не за 5 минут, а меньше чем за минуту. А если задача тяжелая, вместо 15 минут уходит всего 5. Когда ты программист, ты запускаешь задачу и хочешь, чтобы ИИ выполнил ее как можно быстрее. Так гораздо комфортнее, чем ждать 5–15 минут. При этом Artificial Analysis Intelligence Index у DeepSeek‑V4.1-Flash равен 40, что на 2 пункта выше, чем у Luna.

В общем, следующим этапом развития агентского ИИ становится скорость. На текущий момент китайские модели выигрывают. Но, как я понял, нас ждут сюрпризы от американских LLM‑провайдеров. У Anthropic, вроде, с этим проблемы, но OpenAI, похоже, скоро получит дата‑центры, где скорость будет измеряться тысячами токенов в секунду. Представьте: раньше вы ставили задачу и ждали минуты, а теперь все готово за 10–30 секунд. Бизнес со скоростью мысли:) Только придумал, подумал, а результат уже можно проверять:)

Вы же помните, какой была гонка за размером контекстного окна? «У нас 65 тыс. токенов!» «У нас 250 тыс.!» «У нас полмиллиона!» «У нас контекст размером в 1 млн токенов!» Так вот, ребята, я думаю, гонка завершена. Дальше наращивать его смысла нет. Кстати, именно с ростом контекста и появились ИИ‑агенты для кодинга, которые в цикле, решая задачу, итеративно наращивали контекст и успевали за 20–30 циклов сделать что‑то полезное, дойдя до 500 тыс. или 1 млн токенов.

Сейчас главная проблема в том, что ИИ‑агент при каждой новой задаче заново изучает код и правила работы с репозиторием, чтобы выполнить вашу задачу. 80% его работы уходит на то, чтобы заново разобраться, что тут происходит, и только 20% составляют правки в коде. А все это из‑за долбаного контекстного окна в 1 млн токенов, которое приходится постоянно сбрасывать в ноль и начинать заново. То есть у всех уже пришло понимание, что в идеале нужна некая долгосрочная память. Тогда контекстное окно становится бесконечным.

То есть, если модели не требуется из‑за переполнения контекстного окна начинать с нуля, получается, что чем дольше модель работает с кодовой базой, тем больше у нее накапливается общее представление о том, где что находится в этом проекте. В общем, давай stateful LLM, надоели твои stateless LLM! И, кстати, такие работы уже ведутся, и есть несколько проектов. В общем, рынок созрел, и, я думаю, это будет следующим этапом, а не увеличение контекстного окна до 2 или 3 млн токенов.

Кстати, вопрос. А у вас как трансформировались привычки программирования в связи с последними событиями? Например, из‑за того, что мне перестали быть нужны крутые средства IDE, я перестал оплачивать подписки JetBrains и перешел на Zed IDE. Он бесплатный, поддерживает шорткаты, как у JetBrains, и я, по сути, использую его, чтобы смотреть diff кода и навигироваться в дереве исходников.

И, кстати, я что‑то все меньше использую Codex или Claude Code: они тянут слишком много лишнего и раздувают контекст, что отвлекает LLM от задачи. Перешел на Pi harness. У него минимальный набор тулов: редактирование кода, запуск команд и так далее. В итоге в среднем один самый простой запрос к LLM, типа «привет», у Pi занимает 3 тыс. токенов. У Codex 18 тыс., у Claude Code 30 тыс. Тут даже неважно, что меньше. Важно, что модель хуже понимает задачу, отвлекаясь на более раздутый контекст.

А у вас какой стек в итоге образовался? И вообще, как думаете, что дальше будет? Чего ждать от ИИ‑продуктов в сфере программирования? Куда дальше все идет?

Комментарии (283)


  1. Dhwtj
    17.09.2026 11:08

    Для агентского режима это очень медленно. Это начинает раздражать. Если взять модель DeepSeek-V4.1-Flash напрямую через API DeepSeek, скорость там достигает 300 токенов в секунду

    Для агентского режима с четкой проверкой можно. В остальных случаях - брезгую: столько вранья давно не видел.


    1. jorgvonfrundsberg
      17.09.2026 11:08

      А есть какая-то корреляция между измеримой скоростью  токенов в секунду и количеством вранья?


      1. Ka463
        17.09.2026 11:08

        Есть реальная польза от агентского режима с многоступенчатой доказательной проверкой, ловится куча багов, пустышек, обещаний и т.д, это работает на любой модели, а разницы из за скорости генерации я не разу не замечал.


        1. jorgvonfrundsberg
          17.09.2026 11:08

          Спрошу по-другому - агентский режим на локальной модели с, допустим 12Гб видео и 64Гб оперативки будет работать, пусть и неспеша, но без такого же количества вранья как в упомянутом DeepSeek-V4.1-Flash ?


          1. Ka463
            17.09.2026 11:08

            Скажем так, гарантии я не дам, потому что работаю на своем собственном агенте, а что возьмете вы и как настроите я не знаю, а от агентского контура зависит все.

            А на счет DeepSeek-V4.1-Flash, у меня он сейчас как раз подключен, как облачная модель, и вот наблюдение, я ему кинул ссылку на статью, и сказал, хочу то что в статье но с своим блэкджеком, к вечеру полный функционал был готов, в агентском режиме он работает на ура.


            1. igumnov Автор
              17.09.2026 11:08

              О чем и говорю. Luna модель от OpenAI на том же уровне. Притом если ее попросить вместо DeepSeek-V4.1-Flash будет результат в 5 раз дольше ждать.


              1. Ka463
                17.09.2026 11:08

                Это я еще не нативный API от дипсика взял,а пользую облачную ollama, там все несколько тормознее =)


              1. swap2bin
                17.09.2026 11:08

                По моим тестам Luna еще хуже чем DeepSeek и несет полный бред и скорость, да это тоже косяк


          1. Ka463
            17.09.2026 11:08

            Вот кстати если интересно, как работает режим проверки, это дипсик 4.1, режим работы swarm когда есть оркестратор и воркер, и вот как раз воркер закончил работу и прислал отчет оркестратору, а тот не поверил ему, и не зря, нашел косяки и отправил воркера исправлять, без моего вмешательства в работу агента.


            1. Z55
              17.09.2026 11:08

              Вот кстати если интересно, как работает режим проверки

              Расскажите по подробней, где этот режим? Какой-то дополнительный агент?


              1. IlyaStroynov
                17.09.2026 11:08

                вы всегда можете в промте задать типа "создай план, делегируй исполнение субагенту, его результат провалидируй(тут тоже опция - через независимого агента-ревьюера)". я такую механику сразу в AGENTS.md зашил, чтобы ни одно решение по проекту не принималось без проверки независимым агентом с моделью другого семейства, чем агент-исполнитель


              1. Ka463
                17.09.2026 11:08

                Вам нужен режим где основной агент делегирует работу суб-агенту, а сам оценивает его работу


          1. garageman
            17.09.2026 11:08

            12 - мало совсем. Сейчас даже квантованные модели типа квен-кодер не влезают уже в 20ГБ.


      1. Dhwtj
        17.09.2026 11:08

        Статистическая есть. Логической связи нет


    1. TimurZhoraev
      17.09.2026 11:08

      А были ли внешние инструменты - тот же Qdrant+BAAI-m3 эбмеддер, сейчас в облачных сервисах полно этого добра. Делается векторная БД, затем чанкуется любой даташит что под руку попал (включая код с коммент-промпт форматом - не пренебрегайте этим!) и модель всё делает почти так как руками, хоть Алиса хоть Сбер. Мне очень всё это дело помогло сделать микро-проект с PWM/ADC/UART/I2C/SPI с DMA, все адекватные конечные автоматы с фоллбеками и обработчиками ошибок, практически на уровне main(){} с таймерами миниатюрная RTOS, полное понимание проблем RMW с гонкой данных и всё это впихнуть в 64 к флеша и 20к озушки, прочих вкусных протокольных внешних микрух а-ля SPI дисплейчик, мультиплексоры I2C и умные драйверы шаговых. Плюс ещё скиллы соответствующие и промпт-инъекции чтобы направить в нужное русло ну и конечно же md-саммари с хорошей цепочкой и контрольным выводом, плюс питонячьи тесты (уже давно отодвинул Matlab) и тестирующие C-обёртки. Практически можно не использовать stdlib а генерировать printf/scanf по месту и прочие парсеры, умещаясь в килобайты как на каком-нибудь спектруме, самое невероятное - практически отпала необходимость искать чьи-либо библиотеки (!) для периферии, шрифтов, рендеров итд, всё генерируется по месту, остаётся только что-то вроде HAL/SPL на уровне спецификаций регистров управления. Вообщем это добротный джун/миддл с опытом работы 50+ лет в отрасли, начиная от Z80 и до GPU/FPGA.


      1. igumnov Автор
        17.09.2026 11:08

        Кстати интересная идея, подключить тулзу к кодинг агенту которая проиндексирует кодовую базу через ембединг вектора и будет давать возможность искать по смыслу а не только по ключевым словам. Надо попробовать с PI Harness такое проделать.


        1. swap2bin
          17.09.2026 11:08

          пробовал AST граф от разных репозиториев, да это немного другое, но суть та же — дать агенту инструмент для поиска по кодовой базе, в итоге работает так себе, современные LLM ужн обучены на некую чуйку лазить по коду как надо а инструмент применяется только по узкой необходимости, когда я прошу это делать (в системном промпте также оформлено как его использовать и тд, не помогает), разве что позволяет мертвый код искать, но как отдельная сессия, а не в процессе решения. Возможно оно нормально будет работать на ООП коде, а не на несколько микросвервисов с разными языками в них, но вот мой опыт ну такое и про индексацию с помощью эмбедингов и векторой базы думаю также будет, работать реально только если много доков и лить top k сразу перед самой таской в промпт тогда может быть


          1. TimurZhoraev
            17.09.2026 11:08

            В точку. Нужен самостоятельный AST-инструмент. Настоящий пример который использую прямо сейчас. Лучше потратить пару дней для генерации того что необходимо, тем более модель с этим отлично справляется. Для Питона там куча нативных AST, для C - Clang
            Саммари:

            AST Python
            # PyScanPyAST — Сканер зависимостей Python
            
            ## Обзор
            
            Модульный инструмент для статического анализа зависимостей Python-проектов. Сканирует все `.py` файлы, строит направленный граф связей импортов и вызовов, генерирует отчёты о цепочках зависимостей и двусторонней достижимости.
            
            ---
            
            ## Архитектура
            
            ```
            scanner.py (CLI точка входа)
                └── ini_reader.py (конфигурация)
                └── graph_builder.py (сборщик графа)
                    ├── file_scanner.py (поиск файлов)
                    └── ast_parser.py (парсинг AST)
                └── chain_report.py (отчёт цепочек)
                └── targeted_deps.py (целевой анализ)
                └── runner.py (режимы выполнения)
                    ├── association_engine.py (двусторонний поиск)
                    └── reporter.py (полный отчёт)
            ```
            
            ---
            
            ## Модули
            
            ### ini_reader.py — Менеджер конфигурации
            - Читает `config.ini` из корня проекта (без дефолтов)
            - Парсит `requirements.txt` для извлечения имён venv-пакетов
            - Классифицирует узлы графа: Project / System / Venv через O(1) lookup по frozenset
            
            ### file_scanner.py — Поиск файлов
            - Рекурсивный обход проекта, исключение директорий и расширений по конфигу
            - Преобразование путей файлов в точечные имена модулей
            - Фильтрация: `.venv`, `__pycache__`, `.pyc`, скрытые файлы
            
            ### ast_parser.py — Парсинг AST
            - Извлечение рёбер зависимостей через `astroid`: импорты, определения функций, вызовы
            - Нормализация импортов: `from X import Y` → `X.Y` каноническое имя
            - Разрешение вызовов: вывод astroid → статический фолбэк с трассировкой вложенных атрибутов
            - Внешние вызовы сворачиваются к корневому модулю
            
            ### graph_builder.py — Сборщик графа
            - Построение `networkx.DiGraph` из распаршенных рёбер
            - Разделение узлов: пространства имён модулей vs функции/методы (через анализ рёбер `contains`)
            - Назначение scope каждому узлу: Project / System / Venv
            - Анализ степеней: топ импортируемых модулей, топ вызывающих функций
            
            ### association_engine.py — Двусторонний поиск достижимости
            - Downstream: BFS вперёд от начального модуля — все зависимые модули и функции
            - Upstream: BFS назад от начального модуля — все вызывающие модули и тесты
            - Построение кратчайших путей (chain) от корня к каждому достижимому узлу
            - Классификация всех достижимых узлов по scope
            
            ### chain_report.py — Генератор отчёта цепочек
            - BFS-трассировка полной цепочки импортов от целевого файла до листьев
            - Группировка импортов по пакету верхнего уровня (напр., `ASTPythonIO/editable_ast`)
            - Форматирование: дерево root → leaves + список прямых импортов для каждого файла
            
            ### targeted_deps.py — Целевой анализ зависимостей
            - Фаза 1: парсинг целевого файла → внешние импорты (stdlib + third-party) + внешние вызовы
            - Фаза 2: сканирование всех файлов проекта → поиск вызывающих (кто импортирует цель)
            - Вывод: список внешних импортов, внешних вызовов, список модулей-вызывающих
            
            ### reporter.py — Генератор полного отчёта
            - Сводная статистика: узлы, рёбра, модули, count по типам
            - Топ импортируемых модулей (по in-degree) и топ вызывающих функций (по out-degree)
            - Деревья зависимостей модулей + деревья вызовов функций
            - Полный список всех рёбер (импорт / contains / call)
            - Сворачивание внешних узлов: `typing.Any` → `typing`, `tkinter.ttk` сохраняется
            
            ### runner.py — Режимы выполнения
            - Режим ассоциации: двусторонний поиск от `--init`, upstream/downstream с цепочками
            - Режим полного отчёта: полная статистика проекта, деревья, все рёбра
            - Форматирование текста с группировкой по scope и rollup внешних узлов
            
            ### scanner.py — Точка входа CLI
            - Полный скан: `python scanner.py <проект>` → полный отчёт
            - Целевой: `python scanner.py <проект> --init <модуль>` → двусторонний отчёт
            
            ---
            
            ## Внешние пакеты
            
            | Пакет | Назначение |
            |-------|-----------|
            | `astroid` | Парсинг AST, вывод типов, разрешение импортов |
            | `networkx` | Построение и анализ направленного графа зависимостей |
            
            ---
            
            ## Использование CLI
            
            ```bash
            # Полный отчёт по проекту
            python scanner.py /путь/к/проекту
            
            # Целевой: двусторонний поиск
            python scanner.py /путь/к/проекту --init alice_agent_ast.examples.foo
            
            # Цепочка: root → leaves
            python chain_report.py /путь/к/проекту alice_agent_ast.examples.foo
            
            # Целевые зависимости: внешние импорты + вызывающие
            python targeted_deps.py /путь/к/проекту alice_agent_ast.examples.foo
            ```
            
            ---
            
            ## Файлы вывода
            
            | Файл | Содержание |
            |------|-----------|
            | `dependency_report.txt` | Полный проект: сводка, топ модули, деревья зависимостей, все рёбра |
            | `association_report.txt` | Двусторонний: upstream вызывающие, downstream помощники, цепочки |
            | `result.txt` | Цепочка: полное дерево цепочки + прямые импорты для каждого файла |
            
            ---
            
            ## Конфигурация
            
            `config.ini` (обязателен в корне проекта):
            ```ini
            [exclusions]
            dirs = .git, venv, .venv, env, __pycache__, build, dist
            extensions = .pyc, .pyo
            
            [scopes]
            stdlib_prefixes = builtins, abc, importlib, typing, collections, os, sys, ...
            
            [reporting]
            top_imported_limit = 15
            top_calling_limit = 15
            sample_call_trees_limit = 10
            ```
            
            ---
            
            ## Ключевые решения
            
            1. **Только config**: нет захардкоженных списков stdlib или правил исключения
            2. **Модуль vs функция**: разделение пространств имён модулей и узлов функций через анализ рёбер `contains`
            3. **Нормализация импортов**: `from X import Y` → `X.Y` канонические имена, совпадающие с рёбрами импорта
            4. **Разрешение вызовов**: вывод astroid → статический фолбэк, внешние вызовы сворачиваются к корневому модулю
            5. **Сворачивание внешних узлов**: `typing.Any` → `typing`, `tkinter.ttk` сохраняется как исключение
            6. **O(1) классификация**: lookup по frozenset для префиксов stdlib и venv пакетов
            

            Для скана C поиск dead-code

            Сканер по С файлам
            # CScanFuncsPyClang — Справочник проекта
            
            ## Обзор
            
            Python-инструментарий для статического анализа C-проектов на базе **Clang LibIndex**. Сканирует дерево исходников, извлекает AST (абстрактное синтаксическое дерево), строит матрицу вызовов, выявляет мёртвый код, отслеживает макросы и генерирует отчёты.
            
            ---
            
            ## Архитектура конвейера
            
            ```
            загрузка конфигурации → парсинг AST → анализ дерева → санитизация → флаги → экспорт
                                                     ↕
                                            верификатор мёртвого кода
                                                     ↕
                                            отдельный скрипт верификации
            ```
            
            ```
            главный скрипт (оркестратор)
              ├── Шаг 1: Загрузка конфигурации из INI-файла
              ├── Шаг 2: Разрешение препроцессорных флагов из CMake/Make
              ├── Шаг 3: Инициализация движка Clang
              ├── Шаг 4: Обход дерева файлов проекта
              ├── Шаг 5: Параллельный парсинг файлов через пул потоков
              ├── Шаг 6: Агрегация результатов в общие словари
              ├── Шаг 7: Разрешение целевых функций по вызовам
              ├── Шаг 8: Санитизация сырых данных
              ├── Шаг 9: Верификация мёртвого кода
              ├── Шаг 10: Запись выходных файлов
              └── Шаг 11: Печать сводной статистики
            ```
            
            ---
            
            ## Модули
            
            ### 1. Модуль загрузки конфигурации
            
            **Назначение:** Читает INI-файл конфигурации, разрешает системные пути к заголовочным файлам LLVM, извлекает параметры конвейера и пула потоков.
            
            **Алгоритм:**
            - Парсит секции конфигурации: параметры конвейера, компилятора, исключения
            - Автопоиск директории ресурсов LLVM по списку стандартных путей
            - Парсинг многострочных списков (запятые, переносы строк)
            - Возвращает объединённый словарь параметров
            
            ---
            
            ### 2. Модуль разрешения препроцессорных флагов
            
            **Назначение:** Извлекает определения препроцессора из файлов сборки и подставляет их в аргументы компилятора Clang.
            
            **Алгоритм:**
            - Парсит файл CMake для поиска директив определения определений
            - Парсит файлы Make для поиска переменных флагов препроцессора
            - Объединяет результаты, устраняет дубликаты с сохранением порядка
            
            ---
            
            ### 3. Модуль парсинга единиц трансляции
            
            **Назначение:** Инициализация движка Clang и парсинг файлов в AST.
            
            **Алгоритм:**
            - Создаёт разделяемый индекс Clang для всех потоков
            - Формирует аргументы компилятора динамически: базовые флаги, ресурсы, include-пути, флаги из сборки
            - Для заголовочных файлов пропускает тела функций для ускорения
            - Проверяет файлы на соответствие критериям обработки (расширение, исключения)
            - Возвращает единицу трансляции с полным AST
            
            ---
            
            ### 4. Модуль однопроходного обхода AST
            
            **Назначение:** Один проход по дереву AST извлекает все метаданные без повторных обходов.
            
            **Извлекаемые сущности:**
            - Объявления и определения функций с метаданными (имя, строка, тип, статичность, длина тела)
            - Определения структур с очисткой анонимных имён
            - Явные вызовы функций с дедупликацией по строке и имени
            - Косвенные вызовы через указатели (только если целевой узел — функция)
            - Определения макросов
            - Точки расширения макросов
            
            **Алгоритм:**
            - Прямой обход дерева с проверкой принадлежности узла текущему файлу
            - O(1) дедупликация через хеш-множества для каждого типа сущности
            - Вычисление длины тела функции по диапазону строк
            
            ---
            
            ### 5. Модуль санитизации данных
            
            **Назначение:** Фильтрация ложных срабатываний, обработка граничных паттернов C-кода.
            
            **Алгоритмы:**
            - **Дедупликация заголовков:** при многократном включении одного заголовка из разных файлов сохраняется только первый парсинг
            - **Разрешение коллизий имён:** для статических функций формируется составной ключ из пути файла и имени, предотвращающий столкновения
            - **Фильтрация мёртвого кода:** проверяет наличие вызовов по составному ключу с fallback на простое имя, исключает заданный список функций
            - **Полный пайплайн:** последовательное применение всех трёх шагов
            
            ---
            
            ### 6. Модуль генерации отчётов
            
            **Назначение:** Буферизованная запись трёх выходных файлов в виде единого блока данных.
            
            **Выходные файлы:**
            - Сводка функций: список всех функций по файлам, неиспользуемые, статические с локальным охватом, функции с единственным вызовом
            - Сводка структур: список структур с дедупликацией
            - Сводка перекрёстных ссылок: определения макросов, точки расширения, неиспользуемые макросы
            
            **Алгоритм:**
            - Формирование каждого раздела в памяти через буфер строки
            - Однократная запись всего содержимого в файл
            
            ---
            
            ### 7. Модуль верификации мёртвого кода
            
            **Назначение:** Классификация кандидатов в мёртвый код по агрегированным данным вызовов без повторного парсинга.
            
            **Алгоритм для каждой функции:**
            1. Проверка списка исключений → ложноположительный результат
            2. Двухключевой поиск в словаре вызовов: составной ключ → простое имя → сырое имя
            3. Наличие записей о вызовах → ложноположительный, отсутствие → действительно мёртвый
            
            **Возврат:** Разделённый список на подтверждённо мёртвые и ложноположительные функции.
            
            ---
            
            ### 8. Отдельный скрипт верификации через чистый AST
            
            **Назначение:** Верификация мёртвого кода исключительно через Clang AST, без regex и grep.
            
            **Алгоритм:**
            - Парсит все файлы исходного кода проекта
            - Для каждого узла AST проверяет явные вызовы и ссылки на функции
            - Пропускает узлы, соответствующие определению самой функции
            - Проверяет принадлежность узла текущему файлу (исключает включённые заголовки)
            - Строит матрицу: подтверждённо мёртвые / живые с AST-верифицированными точками вызова
            
            ---
            
            ### 9. Главный скрипт (оркестратор)
            
            **Назначение:** Объединяет все модули в единый конвейер.
            
            **Конвейер:**
            1. Загрузка конфигурации
            2. Разрешение флагов из файлов сборки
            3. Инициализация движка Clang
            4. Сбор списка файлов обходом дерева
            5. Параллельный парсинг через пул потоков (движок Clang освобождает блокировку интерпретатора)
            6. Агрегация результатов в общие словари без копирования данных
            7. Разрешение целевых функций по матрице вызовов
            8. Санитизация сырых данных
            9. Верификация мёртвого кода
            10. Запись выходных файлов
            11. Печать сводной статистики
            
            ---
            
            ## Зависимости
            
            ```
            clang.cindex          # Bindings Python для движка Clang LLVM
            configparser          # Стандартная библиотека — парсинг INI
            pathlib               # Стандартная библиотека — работа с путями
            concurrent.futures    # Стандартная библиотека — пул потоков
            io.StringIO           # Стандартная библиотека — буферизованная запись
            ```
            
            ---
            
            ## Запуск
            
            ```bash
            # Полный конвейер
            python checker.py /path/to/c/project
            
            # Только верификация мёртвого кода
            python verify_dead.py /path/to/c/project
            
            # По умолчанию (без аргумента) — путь по умолчанию
            python verify_dead.py
            ```
            
            ---
            
            ## Выходные файлы
            
            | Файл | Путь | Содержимое |
            |------|------|-----------|
            | Сводка функций | В корне проекта | Функции, неиспользуемые, статические, с единственным вызовом |
            | Сводка структур | В корне проекта | Структуры |
            | Сводка перекрёстных ссылок | В корне проекта | Макросы, расширения, неиспользуемые макросы |
            
            ---
            
            ## Ключевые оптимизации
            
            | Оптимизация | Где | Эффект |
            |-------------|-----|--------|
            | Однопроходный обход AST | Модуль анализа | В 6 раз быстрее (было 6 отдельных обходов) |
            | Пул потоков | Главный скрипт | Параллельный парсинг с освобождением блокировки интерпретатора |
            | Дедупликация O(1) через хеш-множества | Модуль анализа | Устранение дубликатов вызовов, ссылок, макросов |
            | Дедупликация заголовков | Модуль санитизации | Предотвращение дублирования при многократном включении |
            | Составные ключи для статических функций | Модуль санитизации | Корректное отслеживание символов с локальной областью |
            | Буферизованная запись блоков | Модуль экспорта | Однократная запись в диск вместо тысяч мелких записей |
            | Пропуск тел функций в заголовках | Модуль парсинга | Ускорение парсинга заголовочных файлов |
            | Верификация мёртвого кода O(1) | Модуль верификации | Без повторного парсинга файлов |
            | Автоопределение флагов препроцессора | Модуль флагов сборки | Автоматическое извлечение определений из файлов сборки |
            

            Фактически можно сказать код больше уже и не нужен - достаточно знать его внутреннюю структуру. Это уже новый этап развития языков - по-сути от них ничего не требуется кроме скелета AST, а далее там и рефакторинг и всё что угодно, благо LLM понимает этот формат особенно для Питона, достаточно указать необходимые тулы и можно таргетированно менять всё что угодно без ошибок синтаксиса как таковых, так как операция производится уже внутри языка.

            -> также дело не в том что модель может по тексту шагать (это кстати можно сделать в виде скилла - что после нахождения чанков идти по путям к этим txt), а в существенной экономии токенов при множественных запросах по смыслу. То есть в векторной БД уже сразу она может сходу найти ответ на запрос, там сразу видно что то вроде ADC калибровка, PWM тайминги, GPIO назначение входов, ADC режимы семплирования итд. При прямом поиске вероятность глюков без вектора возрастает очень сильно. Тем более эту задачу вполне можно сплавить субагентам, причём самым "туповатым" и использовать только для взаимодействия с этой базой но саммари будет более чем достаточно для принятия решений уже оркестрирующей моделью.


            1. BugM
              17.09.2026 11:08

              Лисп уже давно создан.


              1. TimurZhoraev
                17.09.2026 11:08

                А внутри легендарного Лиспа тот самый AST который суть связка между тумблерами, машинным кодом, ассемблером и языком. Он даже в микро-форме присутствует в прошивке Спектрума. Чтобы не перегружать контекст, желательно использовать гарантированный тул который читает по 100 строк что-то вроде grep с заглушкой по длине, даже специально делаю shell-обёртку чтобы он не промахнулся с этим числом. Мало того, можно даже сделать Питошу который поможет модели посёрфить по ассемблерному коду (вот это уже было бы супер - ждём агентов, которые поддерживают генерацию специализированных тулов налету с прокруткой нагенерённого в отдельном окне вместо one-liner-code мучающий терминал). Скачал тут прошивку для ZX-48k просто для интереса во что там БЭЙСИК превращается

                БЭЙСИК превращается, Бэйсик превращается.. в элегантный
                # ZX Spectrum 48K ROM — BASIC Interpreter (Часть 1/3)
                
                ## 1. Обзор архитектуры
                
                ZX Spectrum BASIC — ROM-интерпретатор Z80 с токенизированным вводом, двумя режимами выполнения (syntax-check / runtime), стековым FP-калькулятором (FORTH-like) и переменной памятью.
                
                **Ключевые концепции:**
                - Ввод токенизируется: команды → байты `$80`–`$FF` (1 байт вместо слова)
                - Два режима: syntax-check (бит 7 `FLAGS`) и runtime
                - Переменные хранятся в области `$5C00`–`5CFF` (64 байта системных переменных)
                - Калькулятор — стековый, 5-байт FP числа
                - Программа: `[line_num:2][len:2][tokens][end_marker=$80]`
                
                ---
                
                ## 2. Системные переменные (Memory Map `$5C00`–`$5CFF`)
                
                Доступ через регистр `IY`. Всего 64 байта.
                
                | Смещение | Имя       | Размер | Описание |
                |----------|-----------|--------|----------|
                | `$00`    | `ERR_NR`  | 1      | Номер ошибки (`$FF` = OK, 0–255 = коды ошибок) |
                | `$01`    | `FLAGS`   | 1      | Битовые флаги: бит 0 — ведущий пробел (print), бит 5 — новая клавиша, бит 6 — тип результата (0=string, 1=numeric), бит 7 — режим синтаксической проверки |
                | `$02`    | `FLAGS2`  | 1      | Расширенные флаги: бит 0 — TV (нижний экран), бит 1–3 — режимы |
                | `$07`    | `MODE`    | 1      | Режим клавиатуры: 0=KLC, 1=E, 2=graphics |
                | `$08`    | `LASTK`   | 1      | Код последней нажатой клавиши |
                | `$0B`    | `DEFADD`  | 5      | Указатель определения пользовательской функции |
                | `$10`    | `KSTATE`  | 16     | Состояние клавиш: `[raw][counter][delay][decoded]` × 4 |
                | `$36`    | `OSPPC`   | 1      | Старый указатель оператора (для CONTINUE) |
                | `$38`    | `STRLEN`  | 1      | Имя переменной из 1 символа (FOR/NEXT) |
                | `$3B`    | `CHARS`   | 2      | Адрес таблицы битовых шрифтов (`$5C36`) |
                | `$3D`    | `ERR_SP`  | 2      | Указатель стека ошибок (база GOSUB) |
                | `$42`    | `NEWPPC`  | 2      | Номер новой строки программы (target) |
                | `$45`    | `PPC`     | 2      | Текущий указатель программы (line number) |
                | `$4B`    | `VARS`    | 2      | Начало области переменных |
                | `$51`    | `CURCHL`  | 2      | Текущий адрес канала (указатель I2C-потока) |
                | `$53`    | `PROG`    | 2      | Начало области BASIC-программы |
                | `$55`    | `NXTLIN`  | 2      | Указатель следующей строки (поиск программы) |
                | `$57`    | `DATADD`  | 2      | Указатель оператора DATA |
                | `$59`    | `E_LINE`  | 2      | Конец текущей строки |
                | `$5D`    | `CH_ADD`  | 2      | Текущий адрес символа (указатель парсера) |
                | `$5F`    | `X_PTR`   | 2      | Указатель ошибки (маркер позиции) |
                | `$61`    | `WORKSP`  | 2      | Начало рабочей области (стек калькулятора) |
                | `$63`    | `STKBOT`  | 2      | Нижняя граница стека калькулятора |
                | `$65`    | `STKEND`  | 2      | Верхняя граница стека (свободная память) |
                | `$68`    | `MEM`     | 2      | Указатель памяти (область переменных/данных) |
                | `$74`    | `T_ADDR`  | 2      | Временный адрес (указатель таблицы синтаксиса) |
                | `$76`    | `SEED`    | 2      | Сид для `RND` |
                
                ---
                
                ## 3. Токенизация
                
                ### 3.1. Формат токенизированного BASIC
                
                | Элемент         | Кодировка                          |
                |-----------------|------------------------------------|
                | Команды (NEW, RUN, IF…) | байт `$80`–`$FF` (1 байт) |
                | Функции (RND, SIN, LEN…) | байт `$80`–`$FF` (1 байт) |
                | Операторы сравнения (`<=`, `>=`, `<>`) | байт `$80`–`$FF` |
                | Обычные символы | ASCII-код                         |
                
                ### 3.2. Таблица токенов (адрес `$0095`)
                
                Структура: чередование `DEFB` (байт-разделитель с `$80`) и `DEFM` (строка без разделителя). Последний байт токена инвертирован (`$80 | char`) для обозначения конца.
                
                **Функции:**
                
                | Токен | Байт   | Расшифровка |
                |-------|--------|-------------|
                | RND   | `$80+'D'` | `"RND"`    |
                | INKEY$| `$80+'$'` | `"INKEY$"` |
                | PI    | `$80+'P'` | `"PI"`     |
                | FN    | `$80+'F'` | `"FN"`     |
                | POINT | `$80+'T'` | `"POINT"`  |
                | SCREEN$| `$80+'$'`| `"SCREEN$"`|
                | ATTR  | `$80+'R'` | `"ATTR"`   |
                | AT    | `$80+'A'` | `"AT"`     |
                | TAB   | `$80+'B'` | `"TAB"`    |
                | VAL$  | `$80+'$'` | `"VAL$"`   |
                | CODE  | `$80+'E'` | `"CODE"`   |
                | LEN   | `$80+'V'` | `"LEN"`    |
                | SIN   | `$80+'N'` | `"SIN"`    |
                | COS   | `$80+'N'` | `"COS"`    |
                | ASN   | `$80+'C'` | `"ASN"`    |
                | TAN   | `$80+'N'` | `"TAN"`    |
                | SGN   | `$80+'B'` | `"SGN"`    |
                | ABS   | `$80+'S'` | `"ABS"`    |
                | SQR   | `$80+'B'` | `"SQR"`    |
                | INT   | `$80+'A'` | `"INT"`    |
                | PEEK  | `$80+'K'` | `"PEEK"`   |
                | USR   | `$80+'I'` | `"USR"`    |
                | STR$  | `$80+'$'` | `"STR$"`   |
                | CHR$  | `$80+'$'` | `"CHR$"`   |
                | NOT   | `$80+'T'` | `"NOT"`    |
                | BIN   | `$80+'N'` | `"BIN"`    |
                
                **Команды BASIC (`$E6`–`$FF`):**
                
                | Токен | Команда  | Описание              | Токен | Команда  | Описание           |
                |-------|----------|-----------------------|-------|----------|--------------------|
                | `$E6` | NEW      | Очистить программу    | `$F0` | LLIST    | Вывести программу  |
                | `$E7` | BORDER   | Цвет рамки            | `$F1` | LET      | Присваивание (`=`) |
                | `$E8` | CONT     | Продолжить            | `$F2` | PAUSE    | Ожидание           |
                | `$E9` | DIM      | Объявить массив       | `$F3` | NEXT     | Итерация FOR       |
                | `$EA` | REM      | Комментарий           | `$F4` | POKE     | Запись в память    |
                | `$EB` | FOR      | Цикл с переменной     | `$F5` | PRINT    | Вывод              |
                | `$EC` | GOTO     | Переход к строке      | `$F6` | PLOT     | Точка на экране    |
                | `$ED` | GOSUB    | Подпрограмма          | `$F7` | RUN      | Запустить          |
                | `$EE` | INPUT    | Ввод с клавиатуры     | `$F8` | SAVE     | Сохранить на ленту |
                | `$EF` | LOAD     | Загрузить с ленты     | `$F9` | RANDOMIZE| Сид RND            |
                |       |          |                       | `$FA` | IF       | Условие            |
                |       |          |                       | `$FB` | CLS      | Очистить экран     |
                |       |          |                       | `$FC` | DRAW     | Линия/дуга         |
                |       |          |                       | `$FD` | CLEAR    | Очистить переменные|
                |       |          |                       | `$FE` | RETURN   | Из подпрограммы    |
                |       |          |                       | `$FF` | COPY     | На принтер         |
                
                ---
                
                ## 4. Таблица синтаксиса (Syntax Table, адрес `$1A48`)
                
                ### 4.1. Формат записи
                
                ```
                [ClassByte] [SeparatorByte] [ClassByte] [SeparatorByte] ... [ClassByte] [OFFSET]
                ```
                
                ### 4.2. Коды классов параметров
                
                | Класс | Описание                                      |
                |-------|-----------------------------------------------|
                | `$00` | Без операндов (конец оператора)               |
                | `$01` | Переменная требуется (для LET: `VAR = EXPR`)  |
                | `$02` | Выражение (число или строка)                  |
                | `$03` | Числовое выражение, необязательное (по умолч. 0) |
                | `$04` | Односимвольная переменная                     |
                | `$05` | Полный синтаксический контроль (PRINT, INPUT) |
                | `$06` | Числовое выражение требуется                  |
                | `$08` | Два числа через запятую                       |
                | `$09` | Два числа + необязательный цвет               |
                | `$0B` | Команда ленты (SAVE/LOAD/VERIFY/MERGE)        |
                
                ### 4.3. Классы-рутины (CLASS-TABLE, адрес `$1C01`)
                
                | Класс | Рутин   | Адрес  | Описание                                  |
                |-------|---------|--------|-------------------------------------------|
                | `$00` | L1C14   | No operands                         |
                | `$01` | L1C1B   | Variable assignment + `=`           |
                | `$02` | L1C2E   | Expression (SCANNING)               |
                | `$03` | L1C48   | Optional numeric (default 0)        |
                | `$04` | L1C59   | Single char variable                |
                | `$05` | L1C6A   | Full syntax check                   |
                | `$06` | L1C82   | Numeric expression                  |
                | `$08` | L1E85   | Two comma-separated params          |
                | `$09` | L21E2   | Colour items + coords               |
                | `$0B` | L0609   | Tape command dispatch               |
                
                ### 4.4. Примеры записей
                
                | Команда | Токен | Синтаксис        | Описание                          |
                |---------|-------|------------------|-----------------------------------|
                | LET     | `$E1` | `[$01] [=] [$02]` | `VAR = EXPR`                     |
                | GOTO    | `$EC` | `[$06] [$00]`     | `GOTO 100` — число, конец        |
                | IF      | `$FA` | `[$06] [THEN] [$05]` | `IF A>5 THEN ...` — условие + оператор |
                | FOR     | `$EB` | `[$04] [=] [$06] [TO] [$06] [STEP] [$05]` | `FOR I=1 TO 10 STEP 2` |
                | PRINT   | `$F5` | `[$05]`           | Полный синтакс-чек (строки, выражения, TAB) |
                | INPUT   | `$EE` | `[$05]`           | Полный синтакс-чек                |
                | DIM     | `$E9` | `[$05]`           | Объявление массивов               |
                | SAVE    | `$F8` | `[$0B]`           | Команда ленты                     |
                | RUN     | `$F7` | `[$03]`           | Необязательное число (строка, по умолч. 0) |
                
                # ZX Spectrum 48K ROM — BASIC Interpreter (Часть 2/3)
                
                ## 5. AST-подобная структура данных в памяти
                
                ### 5.1. Программа (Program Area)
                
                **Layout (линейная память, отсортирована по номеру строки):**
                
                ```
                +-------------------+
                | Line Number (2B)  |  $0000–$FFFF, $8000+ = end marker
                +-------------------+
                | Line Length (2B)  |  Количество байт токенов
                +-------------------+
                | Token 1           |  $E6 = NEW, $F7 = RUN, ...
                +-------------------+
                | Token 2..N        |  Или ASCII для нетокенизированного текста
                +-------------------+
                | End Marker ($80)  |  Конец строки
                +-------------------+
                | ... (следующая)   |
                +-------------------+
                | $80 (global end)  |  Конец всей программы
                +-------------------+
                ```
                
                **Пример:** `10 PRINT "HELLO"`
                ```
                Line Num: $0010  Length: $000D (13 байт)
                Tokens: $F5 $22 "HELLO" $22 $0D
                End: $80
                ```
                
                ### 5.2. Переменные (Variables Area)
                
                **Layout (начинается с `VARS`):**
                
                ```
                +-------------------+
                | Name Length (1B)  |  $01–$7F (бит 7 = инвертирован для последнего символа)
                +-------------------+
                | Name Chars (N B)  |  1–30 символов, регистронезависимо (в нижнем регистре)
                +-------------------+
                | Data (5B / var)   |  5 байт FP-число ИЛИ дескриптор строки
                +-------------------+
                | Name Length (1B)  |  Следующая переменная
                +-------------------+
                | ...               |
                +-------------------+
                | $80               |  Конец переменных
                +-------------------+
                ```
                
                **Типы переменных:**
                
                | Тип         | Байт 0           | Байты 1+                   |
                |-------------|------------------|----------------------------|
                | Numeric     | Знак/экспонента  | 5 байт FP-число           |
                | String      | Длина (0–255)    | Данные строки             |
                | Array       | `$80 + dim`      | Размеры измерений + данные |
                
                **Numeric (5 байт):**
                ```
                Byte 0: Sign (0=+, 1=−) + Exponent high (biased)
                Byte 1: Exponent low
                Byte 2–3: Mantissa (high)
                Byte 4–5: Mantissa (low)
                ```
                Нормализация: мантисса ∈ [0.5, 1.0), экспонента со смещением 128.
                Ноль: все байты = `$00`.
                
                ### 5.3. Калькулятор (Calculator Stack)
                
                **Layout (растёт вниз от `STKEND`):**
                
                ```
                High Memory
                +-------------------+
                | STKEND            | ← системная переменная
                +-------------------+
                | FP Number 5B      | ← Operand 3 (самый глубокий)
                +-------------------+
                | FP Number 5B      | ← Operand 2
                +-------------------+
                | FP Number 5B      | ← Operand 1 (top)
                +-------------------+
                | STKBOT            | ← системная переменная
                +-------------------+
                Low Memory
                ```
                
                ---
                
                ## 6. Калькулятор (Floating-Point Stack)
                
                ### 6.1. Формат 5-байтного FP-числа
                
                ```
                Byte 0: [S][EEEEEEE]  ← бит 7 = знак, биты 0–6 = экспонента high
                Byte 1: [EEEEEEEE]    ← экспонента low
                Byte 2: [MMMMMMMM]    ← мантисса, байт 3 (MSB)
                Byte 3: [MMMMMMMM]    ← мантисса, байт 2
                Byte 4: [MMMMMMMM]    ← мантисса, байт 1 (LSB)
                ```
                
                Нормализация: мантисса ∈ [0.5, 1.0), bias = 128. Ноль: все `$00`.
                
                ### 6.2. FP-CALC (Restart `$0028`) — Opcode Table
                
                FORTH-like стековая машина. Однобайтовые операнды:
                
                | Операнд | Мнемоника    | Описание                        |
                |---------|--------------|---------------------------------|
                | `$01`   | EXCHANGE     | Swap top 2                       |
                | `$02`   | DELETE       | Pop top                          |
                | `$03`   | SUBTRACT     | `A = B - A` (pop both, push res) |
                | `$04`   | MULTIPLY     | `A = B * A`                      |
                | `$05`   | DIVISION     | `A = B / A`                      |
                | `$07`   | FP-CALC-2    | Рекурсивный вызов                |
                | `$0F`   | ADDITION     | `A = B + A`                      |
                | `$10`   | NEGATE       | `A = -A`                         |
                | `$27`   | INT          | FP → integer (truncate)          |
                | `$31`   | DUPLICATE    | Duplicatetop                      |
                | `$34`   | STK-DATA     | Push 5B literal из след. байт    |
                | `$38`   | END-CALC     | Return, HL = top of stack        |
                | `$A1`   | STK-ONE      | Push 1.0                         |
                | `$C0`–`$C4` | ST-MEM-0..4 | Pop → MEM-N (scratch pad)      |
                | `$E0`–`$E4` | GET-MEM-0..4| Push MEM-N на стек             |
                
                ### 6.3. Пример: BEEP dur, pitch
                
                ```
                Stack before: [duration] [pitch]
                
                $31 DUPLICATE     → [dur] [pitch] [pitch]
                $27 INT           → [dur] [pitch] [int_pitch]
                $C0 ST-MEM-0      → [dur] (int_pitch stored)
                $03 SUBTRACT      → [dur] [frac_pitch]
                $34 STK-DATA      → [dur] [0.05762265]
                $04 MULTIPLY      → [dur] [0.0576 × frac]
                $A1 STK-ONE       → [dur] [0.0576×frac] [1.0]
                $0F ADDITION      → [dur] [1 + 0.0576×frac]
                $38 END-CALC      → HL = top of stack
                
                Result: freq = base_freq × (1 + 0.0576 × fractional_pitch)
                ```
                # ZX Spectrum 48K ROM — BASIC Interpreter (Часть 3/3)
                
                ## 7. Оценка выражений (Expression Scanning)
                
                ### 7.1. SCANNING (адрес `$24FB`) — Главный парсер выражений
                
                Парсит выражение от `CH_ADD` до `)` или конца оператора. Алгоритм: **shunting-yard variant**.
                
                **Алгоритм:**
                1. Инициализация: `FLAGS` бит 7 = 1 (syntax-check) или 0 (runtime)
                2. `E-LINE-NO` — извлечь необязательный номер строки (для RUN)
                3. Цикл по токенам выражения:
                   - `GET-CHAR` → пропуск пробелов, следующий значимый символ
                   - Цифра/буква → разбор числа или переменной
                   - `(` → рекурсивный вызов SCANNING для подвыражения
                   - Токен функции → push на стек операторов
                   - Оператор (+, -, *, /, ^…) → обработка приоритета
                   - `,` → конец выражения (для многопараметрических команд)
                
                **Приоритет операторов:**
                
                | Приоритет | Оператор | FP-CALC Opcode |
                |-----------|----------|----------------|
                | `$0A`     | `^`      | `$C6` (to-power) |
                | `$08`     | `*`      | `$C4` (multiply) |
                | `$08`     | `/`      | `$C5` (division) |
                | `$06`     | `+`      | `$CF` (addition) |
                | `$06`     | `-`      | `$C3` (subtract) |
                | `$05`     | `<=, >=, <>, >, <, =` | `$C9`–`$CE` |
                | `$03`     | `AND`    | `$C8` |
                | `$02`     | `OR`     | `$C7` |
                
                **Правило:** новый оператор с более низким приоритетом → pop и вычислить стек операторов.
                
                ### 7.2. Разбор чисел и переменных
                
                **Числа:** `[digits].[digits]E[±digits]` — пример: `123.45E-2 = 1.2345`
                1. Пропуск пробелов
                2. Чтение цифр в мантиссу (нормализация к 0.5–1.0)
                3. Точка → коррекция экспоненты
                4. `E` → умножить экспоненту на 10
                5. Знак `−` → инвертировать
                6. Push 5B FP на стек калькулятора
                
                **LOOK-VARS (адрес `$28B2`) — поиск переменной:**
                1. Первый символ из `CH_ADD`
                2. Чтение имени (1–30 символов)
                3. Поиск в области переменных (от `VARS` до `$80`)
                4. Сравнение регистронезависимо
                
                | Carry | C     | Результат          |
                |-------|-------|--------------------|
                | 1     | `$00` | Простая numeric    |
                | 1     | `$40` | Простая string     |
                | 1     | `$80` | Array              |
                | 0     | —     | Не найдена (создать новую) |
                
                ### 7.3. Функции (Functions)
                
                Диспатч при `token - $A5` в таблице `$1A48`:
                
                | Токен | Функция | Описание | Токен | Функция | Описание |
                |-------|---------|----------|-------|---------|----------|
                | `$A5` | RND     | Случайное (LCG) | `$B4` | TAN     | Тангенс |
                | `$A6` | INKEY$  | Клавиатура (non-blocking) | `$B5` | ASN     | Arc sine |
                | `$A7` | PI      | 3.14159265… | `$B6` | ACS     | Arc cosine |
                | `$A8` | FN      | Пользоват. функция | `$B7` | ATN     | Arc tangent |
                | `$A9` | POINT   | Цвет пикселя | `$B8` | LN      | Натуральный лог |
                | `$AA` | SCREEN$ | Дамп памяти экрана | `$B9` | EXP     | e^x |
                | `$AB` | ATTR    | Атрибут символа | `$BA` | INT     | Целая часть |
                | `$AC` | AT      | Позиция курсора | `$BB` | SQR     | Корень (Newton) |
                | `$AD` | TAB     | Позиция TAB | `$BC` | SGN     | Знак (−1,0,+1) |
                | `$AE` | VAL$    | Строка → значение | `$BD` | ABS     | Модуль |
                | `$AF` | CODE    | Код символа | `$BE` | PEEK    | Байт памяти |
                | `$B0` | VAL     | Строка → число | `$BF` | IN      | Порт ввода |
                | `$B1` | LEN     | Длина строки | `$C0` | USR     | Машинная функция |
                | `$B2` | SIN     | Синус (CORDIC) | `$C1` | STR$    | FP → строка |
                | `$B3` | COS     | Косинус | `$C2` | CHR$    | Код → символ |
                
                ---
                
                ## 8. Обработка команд (Statement Handlers)
                
                ### 8.1. MAIN DISPATCH — STMT-LOOP (адрес `$1B28`)
                
                **Алгоритм:**
                1. `NEXT-CHAR` → advance `CH_ADD`
                2. `GET-CHAR` → текущий символ
                3. `CR` (`$0D`) → `LINE-END`; `:` (`$3A`) → `STMT-LOOP`
                4. Push `STMT-RET` (обработчик ошибок)
                5. Символ → `C`, `NEXT-CHAR` → past command name
                6. Вычесть `$CE` (DEF FN offset) → < 0 → `REPORT-C` (Nonsense)
                7. Индекс в таблицу `L1A48` → смещение к syntax entry
                8. `HL = syntax entry` → `GET-PARAM`:
                   - Load param byte из `[HL]`, inc HL → `T_ADDR`
                   - Push `SCAN-LOOP` return, param → `C`
                   - Param > `' '` → `SEPARATOR`; иначе → `CLASS-TABLE` dispatch
                   - Indirect jump к class routine → pop → back to `SCAN-LOOP`
                
                ### 8.2. LET (Присваивание, `$E1`)
                
                **Синтаксис:** `VAR = EXPR`
                1. Class `$01`: fetch variable name
                2. Разделитель `=`
                3. Class `$02`: scan expression → результат на стеке (`HL`)
                4. `LET` рутинa (`$2AFF`):
                   - Проверить совпадение типов
                   - String: копировать данные; Numeric: копировать 5B FP
                   - Type coercion (int → FP)
                
                ### 8.3. IF (Условие, `$FA`)
                
                **Синтаксис:** `IF condition THEN statement [ELSE statement]`
                1. Class `$06`: evaluate condition
                2. Разделитель `THEN`
                3. Class `$05`: full syntax check following statement
                4. Runtime: pop condition → 0 (false): искать `ELSE` или конец строки; ≠ 0 (true): выполнить → skip к `ELSE`/конец
                
                ### 8.4. FOR (Цикл, `$EB`)
                
                **Синтаксис:** `FOR var = start TO end [STEP step]`
                1. Class `$04`: single-char variable
                2. Разделитель `=`, Class `$06`: start expr
                3. Разделитель `TO`, Class `$06`: end expr
                4. Class `$05`: optional STEP (default 1)
                5. Runtime:
                   - Store initial value
                   - Allocate 13B: current(5B) + limit(5B) + step(5B) + line(2B) + stmt(1B)
                   - Set bit 7 of variable name (FOR marker)
                   - Call `NEXT-LOOP` test → continue/skip to matching NEXT
                
                ### 8.5. NEXT (Итерация, `$F3`)
                
                **Синтаксис:** `NEXT [var]`
                1. Class `$04`: optional variable, Class `$00`: end
                2. Runtime:
                   - Check `FLAGX`, lookup variable
                   - Not found / not FOR → `REPORT-1`
                   - Check bit 7 (FOR marker) → not set → `REPORT-I` (NEXT без FOR)
                   - Increment: `GET-MEM-0` + `GET-MEM-2` → `ADDITION` → `ST-MEM-0`
                   - `NEXT-LOOP` test: within range → continue; beyond → clear marker, free 13B, set `NEWPPC/NSPPC`
                
                ### 8.6. PRINT (Вывод, `$F5`)
                
                **Синтаксис:** `PRINT [items;items;items...]`
                Элементы: строки `"text"`, выражения `A,B+C`, `TAB(n)`, `AT row,col`, `;` (без newline), `,` (tab stop 10 cols)
                1. Class `$05`: full syntax check
                2. Runtime: loop → `SCANNING` → `STK-FETCH` → `PO-ABLE` → `PO-STORE`
                3. `;` skip newline, `,` next tab stop, `TAB(n)` abs column, `AT r,c` abs position, CR newline
                
                ### 8.7. INPUT (Ввод, `$EE`)
                
                **Синтаксис:** `INPUT ["prompt";] var1 [,var2...]`
                1. Class `$05`: full syntax check
                2. Runtime: string literal → prompt; set `FLAGX` bit 7; call `EDITOR`
                3. `CH_ADD` → input buffer; for each var: `GET-CHAR`, `VAL-FET-2` → parse/store
                
                ### 8.8. GOTO (Переход, `$EC`)
                
                **Синтаксис:** `GOTO line_num`
                1. Class `$06`: numeric expression → target line number
                2. Runtime: set `NEWPPC` to target, `NSPPC` = 0, jump to line
                
                ### 8.9. GOSUB / RETURN (Подпрограммы, `$ED` / `$FE`)
                
                **GOSUB:**
                1. Class `$06`: target line number
                2. Push `NEWPPC/NSPPC` на стек ошибок (`ERR_SP`)
                3. Set `NEWPPC` to target
                
                **RETURN:**
                1. Pop `NEWPPC/NSPPC` из стека (`ERR_SP`)
                2. Resume execution at saved position
                
                ### 8.10. RUN / NEW / CLEAR (Управление, `$F7` / `$E6` / `$FD`)
                
                | Команда | Токен | Действие |
                |---------|-------|----------|
                | RUN     | `$F7` | Start program from `PROG`, reset runtime vars |
                | NEW     | `$E6` | Clear entire program area (`$80` end marker) |
                | CLEAR   | `$FD` | Clear variables/screen, reset `VARS`, `MEM` |
                | CONT    | `$E8` | Continue from `OSPPC` (saved line) |
                | LOAD    | `$EF` | Load from tape → program area |
                | SAVE    | `$F8` | Save program area to tape |
                | LLIST   | `$F0` | List program to screen/printer |
                | CLS     | `$FB` | Clear screen (black) |
                | BORDER  | `$E7` | Set border colour |
                | PAUSE   | `$F2` | Wait for interrupt (frame sync) |
                | RANDOMIZE | `$F9` | Set `SEED` for RND |
                | POKE    | `$F4` | Write byte: `POKE addr, value` |
                | PLOT    | `$F6` | Draw point: `PLOT x,y` |
                | DRAW    | `$FC` | Draw line/arc: `DRAW dx,dy` |
                | COPY    | `$FF` | Copy screen to printer |
                | DIM     | `$E9` | Declare array: `DIM A(10,20)` |
                | REM     | `$EA` | Comment (skip to end of line) |
                | PAUSE   | `$F2` | Wait for interrupt |
                

                Вот собственно и есть тот самый AST-мотор под катом, тот же самый ассемблер. Достаточно просто визуализировать его токены на экране, это собственно то что назовём Бэйсиком, а там можно и представить хоть как Go хоть как Python или что ещё, даже индексы менять не нужно, добавить новые для классов, лямбд функций итд. В будущем как раз LLM-ка наверняка научится работать с этим напрямую без потери контекста за счёт hold-тегов.


          1. Yarus23
            17.09.2026 11:08

            А ведь мысль то здравая по ast модель не будет у себя в головешке строить модель код а ей уже это дадут. Вопрос в том что была статья на Хабре про использование инструментов что она может написать кучу инструментов классных но пользоваться все равно grep rg и тп. Думаю это вопрос промта и по идее должно сильно улучшить качество на моделях с малым контекстом. Надо эксперимент провести у меня куча кода на go и ts


        1. Aleksandrit2332
          17.09.2026 11:08

          https://github.com/DeusData/codebase-memory-mcp

          Даже визуализация графа строится с фильтрами...


        1. funca
          17.09.2026 11:08

          GitNexus например или CodeGraph. Хотя в последнем вроде только BM25.


        1. Robastik
          17.09.2026 11:08

          А что насчёт ведения карты кода как части документации проекта? В виде json: модули с описанием функционала - подсистемы с архитектурой - файлы с ролями и сущностями. В начале новой задачи агент сразу видит всю карту и понимает фронт работы.


        1. dkfbm
          17.09.2026 11:08

          интересная идея, подключить тулзу к кодинг агенту которая проиндексирует кодовую базу

          Так идея, мягко говоря, не новая. Давно уже пользуюсь.


    1. Joolg
      17.09.2026 11:08

      Если привязать агента к тайпчекеру и прогону юнит-тестов, фантазии отсекаются сами собой. Модель просто делает еще одну итерацию, пока компилятор не заткнется


      1. Dhwtj
        17.09.2026 11:08

        На все случаи чекеров не напасешь


        1. vanxant
          17.09.2026 11:08

          Для этого у тестировщиков есть свои модели, которые придумывают интеграционные/Е2Е тесты, не видя кода, а только лишь тз и юзерсторисы. Тоже не 100% гарантия, но ОЧЕНЬ полезно