HWW Portfolio

Software and Hardware Developer

SOOT

Компилятор и виртуальная машина для строго типизированного языка с интерактивной разработкой

English Русский

О проекте

Я уже довольно давно разрабатываю компилятор и виртуальную машину (VM) для его рантайма. В основном в одиночку, и в первую очередь потому, что хотела с самых основ разобраться, как такие сложные системы устроены изнутри.

Проект давно перерос рамки простого компилятора. Теперь в нём есть:

Происхождение

Сам компилятор вырос из кода OpenGOAL (открытого проекта по переработке Jak & Daxter). Архитектура виртуальной машины основана на моих собственных исследованиях: с помощью написанных на Python утилит я проанализировала форматы байткода скриптов игры и объединила эти данные с публичными докладами студии и технической документацией.

Прямой бинарной совместимости я не добиваюсь. Там, где оригинальное устройство было неясным или недокументированным, я проектировала собственные архитектурные решения.

Какие вопросы приходится решать

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

Ни один из этих вопросов не тривиален, и каждый ответ напрямую определяет поведение всего движка.

Цикл статей

В этом цикле я рассказываю об инженерных решениях, которые стоят за проектом: об альтернативах, которые я рассматривала, о логике, которая привела к итоговому выбору, и о компромиссах, с которыми пришлось согласиться.

  1. Обзор архитектуры SOOT История разработки SOOT и обзор его архитектуры: путь от нескольких запусков на разных языках до системы типов, интерпретатора и компилятора на C++; почему код генерируется для виртуальной машины, а не для процессора; устройство VM (32-битные инструкции, дерево StackFrame) и формат бинарного файла.
  2. Инкрементальная интерактивная компиляция: как совместить строгий компилятор и REPL Как REPL использует тот же компилятор, что и сборка проекта: модуль на каждый ввод, глобальная таблица имён, инициализация top-level и сознательный отказ от выгрузки модулей.
  3. Управление памятью в SOOT: от reference count к простому сборщику мусора Как менялась модель памяти: от передачи значений и reference count через данные на один кадр к простому неперемещающему сборщику мусора; дескрипторы типов, которые отделяют менеджер памяти от VM, арены и size-class, номер прохода вместо сброса меток, инкрементальный sweep, известные ограничения и планы по улучшению.
  4. Анатомия интерпретатора SOOT: три инженерных решения Как интерпретатор помогает находить ошибки: TextDb связывает S-выражения с местом в исходном коде, vararg_check описывает контракт аргументов встроенных функций в одну строку, а накопление трассировки и обработчики ошибок на самом языке дают управляемое выполнение; происхождение этих механизмов от GOOS и их цена.
  5. Variant: универсальный контейнер данных виртуальной машины Как устроены регистры виртуальной машины: тег плюс union из трёх типов (целое, вещественное, указатель); почему идея хранить тип в виде CRC оказалась тупиковой; почему от суррогатных типов (булево значение, StringId, строка) пришлось отказаться, раз система команд не гарантирует их правильную установку; как показывать значения в терминале на стороне инструментов; связь с сборщиком мусора и передача аргументов в нативные функции.
  6. Глобальная область видимости: почему в SOOT нет приватных имён Почему все определения всех модулей живут в одной глобальной области: во что обошлась бы изоляция модулей виртуальной машине, где каждый вызов начинается с поиска по имени, как устроен индекс Globals, чем приходится платить (коллизии имён, нет настоящей инкапсуляции) и как это компенсируется дисциплиной именования, а также планируемый define private и формат файла с разделением определений на публичные и приватные.
  7. Полиморфизм в SOOT Как один и тот же вызов (-> obj method) работает для разных типов объектов: почему методы у структур сами по себе полиморфизма не дают, зачем нужен тип basic с идентификатором типа в заголовке, почему там лежит SID, а не указатель (ради перезагрузки модулей), как инструкция CallMethod решает проблему нехватки операндов, и какую цену это стоит; с разбором примера от Lisp до ассемблера.
  8. Модульная система SOOT: полное руководство Как компилятор и runtime работают с именами, чем require отличается от load-module, что сохраняют save-session и save-module, работа с SIDBase и типичные подводные камни.

Следующие статьи цикла будут добавляться сюда по мере выхода.

Статус

SOOT — молодой проект, он продолжает активно развиваться. Недавно репозиторий был выбран для включения в публичный индекс кода для ИИ-агентов.

Контакты

Сейчас я ищу работу на полную занятость в сферах разработки компиляторов (Compiler Development), инструментария для языков (Language Tooling) и системного программирования (Systems Programming). Если вы работаете в этих областях, буду рада пообщаться.