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

Немного Теории

Для начала немного теоретических рассуждений. Прежде всего, что же из себя представляет "компилятор" в реалиях варкрафта? Можно было бы обратиться к формальному определению компилятора и долго ломать копья об уместности этого слова в текущем контексте, но об этом в другой раз - сейчас важно определиться со смыслом который я вкладываю в это слово здесь и сейчас.
Компилятор - в текущем контексте это утилита, которая берет исходный код карты и преобразует его к виду пригодному для запуска в игре.
Именно так, ни больше ни меньше - только обработка исходного кода. Все остальные действия над картой - задача других утилит.
Поскольку компилятор только трансформирует исходный код, но не трогает карту руками, значит нам нужна еще одна утилита, которая затолкает переработанный код в карту и подготовит её к запуску. Назовем эту утилиту "билдер" или "сборщик".
Билдер/Сборщик - в текущем контексте это утилита, которая перепаковывает карту после обработки кода компилятором, а также запускает другие утилиты, если таковые предусмотрены процессом сборки.
И финальный недостающий для комфортной работы элемент - интеграция с внешней средой разработки. На данный момент для работы с Lua я пользуюсь VSCode, поэтому интеграция будет в виде плагина к VSCode.

Требования

Компилятор: общие требования

  • Должен уметь собирать исходный код из файлов вне архива карты
  • Должен уметь получать код карты, сгенерированный редактором карт и объединять его с кодом из внешних файлов
  • Должен уметь кешировать скомпилированный код для ускорения повторной компиляции
  • Не должен своевольно добавлять что-то в код карты, все действия с кодом должны иметь видимую причину
  • Не должен слепо имитировать работу require

Билдер: общие требования

  • Должен уметь запускать компилятор, передавая ему пути к исходному коду
  • Должен уметь собирать пригодную к запуску карту из папки и исходного кода
  • Должен уметь запускать дополнительные утилиты при условии их наличия
  • Должен уметь игнорировать файлы "только для редактора" при сборке релизной версии карты

Интеграция: общие требования

  • Простота настройки и начала работы
  • Все входящие в базовый комплект утилиты должны скачиваться автоматически, без необходимости ручной установки и тем более компиляции
  • Обязательные настройки перед началом работы должны сводиться к указанию путей к игре и редактору, все остальные настройки должны быть опциональными и иметь приемлемые значения по умолчанию
  • Наличие пресета пустого проекта со стандартными настройками и готовой к работе файловой структурой
  • Возможность работать в редакторе карт параллельно с редактированием кода в VSCode

Проект: общие требования

  • Представлен в виде папки
  • Одна карта - один проект
  • Содержит воркспейс VSCode
  • Содержит файлы конфигурации для конкретного проекта
  • Содержит фиксированную структуру папок, диктующую расположение элементов проекта
  • Содержит карту представленную в виде папки
  • Содержит файлы с исходным кодом
  • Содержит папку, в которую складываются промежуточные результаты и временные файлы
  • Содержит папку, в которую складывается карта после сборки
  • Все файлы находящиеся вне фиксированной структуры не влияют напрямую на происходящие в проекте процессы и формально не являются его частью

Предполагаемые фичи

Интеграция

  • Возможность отдельного запуска компилятора из VSCode
  • Возможность запуска процесса сборки карты из VSCode
  • Возможность запуска карты на тестирование из VSCode
  • Возможность открытия карты в редакторе карт по команде из VSCode
  • Возможность хранить настройки самой интеграции и всех утилит в конфигурационных файлах конкретного проекта
  • Возможность выбирать пресет по которому работают билдер и компилятор
  • Возможность применять набор твиков к исходной карте, например исправленый abilitydata.slk для отображения скрытых способностей

Компилятор

  • Преобразование равкодов в числа на этапе компиляции. Предварительно реализовано макросом RAW('A000')
  • Инлайн переменных и функций. Предварительно частично реализовано макросом --#INLINE для переменных
  • Генерация отладочной информации, позволяющей найти строку в файлах исходного кода по номеру строки в итоговом коде
  • Режим компиляции release. Из кода исключаются фрагменты не нужные в релизной версии карты, а также код карты подвергается минификации
  • Режим компиляции dev. Предназначен для быстрого запуска карты в близком к релизному виде, но с сохранением структуры кода.
  • Режим компиляции debug, в код карты добавляются дополнительные отладочные элементы. Предназначен для поиска причин возникновения ошибок ценой потенциальной потери производительности.
  • Макросы, позволяющие отмечать фрагменты кода соответствующие различным режимам компиляции

Биллдер

  • Несколько режимов работы, отличающихся передаваемыми другим утилитам настройками
  • Режим release - карта максимально очищается от лишних и не обязательных файлов, код компилируется в релизном режиме,возможен запуск внешних оптимизаторов.
  • Режим dev - карта собирается в близком к релизному виде, но с применением только минимального набора оптимизаций.
  • Режим debug - в карту инжектится отладочный модуль, позволяющий выводить сообщения об ошибках в отдельный фрейм.
-Игнор-лист позволяющий указать список файлов которые не будут включены в архив карты при сборке

Запланированные макросы

  • --#INLINE для маркировки функций подлежащих инлайну в пределах текущего файла
  • --#INLINE GLOBAL для маркировки функций и переменных подлежащих инлайну во всех файлах
  • --#IF для начала блока условной компиляции, предварительно без серьезных вычислений, только на основе сравнения констант
  • --#ELSE для начала блока else при условной компиляции
  • --#END для завершения блоков у любых блочных макросов

Реализованные макросы

  • RAW('A000') для конвертации равкодов в число при компиляции.
  • --#INLINE для маркировки переменных подлежащих инлайну в пределах текущего файла. Локальные переменные инлайнятся с удалением объявления/присвоения переменной из кода, а для глобальных объявление/присвоение переменной сохраняется.
  • --#ALIAS для назначения метки файлу. Взаимозаменяем с макросом #NAME.
  • --#AFTER для указания списка меток, которые должны быть включены в код карты прежде чем можно будет включить туда текущий файл. При отсутствии этого макроса файлы включаются в порядке обхода папок и только после кода сгенерированного WE.

На рассмотрении

  • Управление порядком включения файлов кода в итоговый код карты через макрос --#IMPORT вставляющий код из указанного файла в место расположения макроса. При такой реализации импортированный файл включается в код как есть, столько раз, сколько использован макрос, защита от конфликтов имен полностью на совести разработчика.
  • Управление порядком включения файлов кода в итоговый код карты через макрос --#REQUIRE вставляющий код из указанного файла в место расположения макроса. При такой реализации импортированный файл включается в код путем оборачивания в функцию и возврата объекта из этой функции. Также возможно наличие проверки, позволяющей избежать повторного включения одного и того же модуля. В целом, предполагается что этот макрос будет работать аналогично стандартному require, за исключением невозможности динамически формировать пути к включаемым файлам.
  • Фреймворк, который будет поставляться вместе с плагином и который можно будет подключить для получения каких-то дополнительных возможностей в рантайме. Например, система модулей или библиотек, каст-система, различные универсальные утилиты и так далее.
  • Расширенная отладочная система, позволяющая по клику в отладочном фрейме внутри игры получить переход на место в коде, в котором возникла показанная в отладочном фрейме ошибка, если это место возможно обнаружить. Причем переход не к финальному монолитному коду карты, а конкретно в тот файл, из которого эта строка попала в итоговый код. Возможно будет работать в два этапа для упрощения реализации, сперва клик в отладочном фрейме экспортирует данные об ошибке в файл, а потом клик в VSCode читает информацию из файла и выполняет переход.
  • Режим сборки карты, при котором код из внешних файлов переносится в триггеры в таком виде чтобы его мог исправно сохранять редактор. Предназначен для выкладывания карты на сайт, чтобы люди без настроенной среды разработки тоже могли воспользоваться. Поскольку редактор не сможет обработать макросы - их необходимо обработать до импорта в триггеры.
  • Встроенный slk-оптимизатор, конвертирующий данные РО в slk таблицы при запаковке карты.
  • Подсказки и автокомплит для макросов.
  • Доступ к данным карты из среды разработки, в частности подсказки и автокомплит для равкодов.
  • Поддержка линукса, а также других IDE кроме VSCode. Несомненно нужно, но очень затратно по времени.

Разработка

Стартовое состояние

Имеется плагин warcraft-vscode, выполняющий большую часть функций интеграции и билдера. К сожалению, автором этого плагина было принято несколько сомнительных решений, в частности код оборачивается в громоздкую систему имитирующую работу require и это поведение невозможно отключить. Требует серьезной доработки. В составе содержит кастомный сборщик карты, умеющий собрать mpq архив по списку файлов в конфиге.
Для подсветки синтаксиса и поиска синтаксических ошибок используется плагин sumneko.lua, включащий в себя языковой сервер Lua, обработку аннотаций EmmyLua и другие полезные фичи. Не содержит из коробки списка нативок, поэтому их приходится подавать ему из внешних файлов. Мог бы работать лучше, но самостоятельная доработка того не стоит, тем более плагин находится в активной разработке автором и постепенно становится только лучше.

Первая итерация

  • Скачаны исходники warcraft-vscode, проведена настройка окружения для компиляции
  • Безжалостно удалены лишние фичи из кода плагина, такие как обработка кода шаблонами, имитация require и нерабочие макросы условной компиляции, загрузка библиотек с гитхаба и так далее
  • В тестовых целях временно добавлена обработка простых и рабочих макросов условной компиляции
  • Начат процесс приведения плагина к виду, в котором его можно было бы опубликовать не опасаясь проблем с авторским правом, фактически он переписывается с нуля с минимальным использованием оригинального кода

Вторая итерация

  • Начата разработка внешнего компилятора
  • Реализован парсинг кода из файла путем токенизации
  • Реализованы макросы #INLINE и RAW
  • Реализован вывод кода в файл путем обратной конвертации токенов
  • На текущем этапе обрабатывается только один файл - нет ни поиска других внешних файлов ни указания пути по которому должны сохраняться результирующие файлы

Третья итерация

  • В этой итерации планируется допилить компилятор до состояния когда он будет способен самостоятельно найти все внешние файлы с кодом по указанному пути, скомпилировать их и вывести результирующий файл в указанное место. (DONE)
  • Поскольку способ подключения внешних файлов пока под вопросом - принятие этого решения тоже входит в эту итерацию. (DONE, для начала реализованы макросы #NAME/#ALIAS и #AFTER, сойдет пока)
  • Также на эту итерацию запланирована интеграция компилятора с плагином к VSCode, чтобы в плагине остались только функции билдера и интеграции, а вся компиляция выполнялась внешним компилятором.(DONE, в предварительной версии)

Четвертая итерация

  • Мы сейчас здесь
  • Нужно запилить игнор-лист для сборщика карты, чтобы можно было вручную указать какие файлы не надо паковать (DONE)
  • На эту итерацию запланирован первый релиз, пока тестовый, с ручной установкой онли
  • До релиза еще необходимо дочистить код от всего лишнего, завести репозиторий на гитхабе и всякое такое

FAQ

Q: Зачем козе баян? Что не так с Lua без дополнительного компилятора?
A: Прежде всего, ради поддержки импорта кода из внешних файлов и возможности работать с кодом карты вне редактора.
Q: Поддержка JASS?
A: Нет и не планируется. Но вместе с релизом будут выложены исходники - все желающие смогут попробовать самостоятельно адаптировать тулсет под JASS.
Q: Когда релиз? Где скачать?
A: Как только так сразу. Скачать можно будет сразу после релиза, из маркетплейса плагинов к VSCode или с XGM.

Вместо послесловия

Разработка ведется по мере наличия свободного времени, с периодической фиксацией результатов.
Когда плагин и компилятор будут пригодны к использованию - они появятся в маркетплейсе VSCode и здесь.
Идеи и предложения приветствуются.
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
28
5 лет назад
Отредактирован PT153
0
prog, я думаю, что просто возможность создать отдельные файлы для config и main, если их нужно полностью заменить.

Как в принципе собирается код карты? Мне вот сгенерированный код от WE вообще не нужен. Было бы неплохо иметь возможность полностью заменять файл кода.
0
24
5 лет назад
Отредактирован prog
0
PT153, я изначально хотел сохранить возможность расставлять юнитов и ректы в WE и писать гуи триггеры для настроек, поэтому вариант с полной заменой всего оригинального кода WE никогда не рассматривал. Если я когда-нибудь дойду до того чтобы запилить билдфайл по которому будет работать компилятор вместо автоматического режима - такая возможность появится, а раньше я врядли стану тратить на это время.
Автоматический режим сборки кода достаточно прост:
  • файл оригинального кода от WE компилируется, скомпилированная версия падает в папку .build, получает идентификатор MAP и добавляется в список на сборку
  • в указаной директории рекурсивно перебираются все LUA файлы, компилируются, складываются в .build, получают идентификаторы и требования из директив компилятора и добавляются в список на сборку
  • перед компиляцией каждого файла выполняется проверка на наличие его скомпилированной версии и сравнение дат, если компилировать файл заново не нужно, то просто читается его заголовок с директивами компилятора, а компиляция файла пропускается, файл сразу добавляется в список сборки
  • все файлы получают в требования MAP, чтобы оригинальный код от WE всегда шел первым в списке сборки
  • список сборки сортируется таким образом чтобы выполнялись все требования (если требования выполнить невозможно из-за рекурсии или несуществующих индикаторов файлов, то сборка кода фейлится, но пока это только в логе видно - код в любом случае собирается по списку сборки, просто не гарантируется выполнение всех требований )
  • все файлы из списка сборки мержатся в единое целое согласно списку и падают в фиксированное место одним файлом
  • при сборке карты в mpq сборщик подхватывает готовый код карты из известного места и копирует его в архив собираемой карты
Что касается магических файлов для main и config - я не очень хочу плодить магические файлы, работающие определенным образом только потому что они так названы без более явного действия со стороны пользователя.
Поэтому куда более вероятен вариант макроса --#REPLACE или INJECT, который заставит компилятор найти оригинал функции и стереть его, но пока парсер не готов к таким макросам т.к. индивидуально проходит все файлы по очереди, только один раз и в алфавитном порядке продиктованном системой.
0
28
5 лет назад
0
Я думаю, что можно просто добавить опцию "Not include original code" (с пометкой, что это для advanced пользователей), из-за которой пункты сборки 1 и 4 будут просто проигнорированы.
0
24
5 лет назад
0
PT153, дело в том, что компилятор у меня это exe файл, запиленый на C++, а всякие параметры и настройки получает плагин к vscode - это мне нужно будет начинать передавать компилятору дополнительные параметры, чего я не очень хочу делать, отложил так уже несколько фич которые тоже требуют дополнительных флагов - вот когда будет билд-файл, то компилятор будет получать путь к нему и читать оттуда все дополнительные параметры, сколько бы их ни было.
0
28
5 лет назад
0
А, понятно.
Глядишь, в рефорджу будет хорошая утилита.
0
24
4 года назад
0
Выложил план дальнейших действий
Фактически, это то самое обновление, в котором компилятор будет оторван от плагина в вс-коде и переведен на работу с билд-скриптом. Но с нюансами.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.