Написание простого DSL компилятора на Delphi (0. Введение)

Перевод поста Writing a Simple DSL Compiler with Delphi (0. Introduction)open in new window

Некоторое время назад я слушал подкаст Hanselminutes (YOU should write an interpreter with Thorsten Ballopen in new window) где парень описал как он написал простой интерпретатор на языке Go. В действительности, меня не очень интересовало написание интерпретатора — я уже делал это однажды — но мысль закралась мне в голову. Я спросил себя смогу ли я сделать что-то лучше — написать компилятор (или что-то похожее на компилятор, как вы увидите дальше).

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

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

add(a,b) {
  return a + b
}
1
2
3

Простой, С-подобный синтаксис. Не сложно угадать, что функция складывает два числа и возвращает результат.

Я хочу чтобы мой код конвертировал это в что-то похожее на это (и я здесь сильно упрощаю, в действительности код будет более сложный):

function CodegenAdd(a, b: integer): integer;
begin
  Result := a + b;
end;

prog :=
  function (params: TArray): integer
  begin
    Result := CodegenAdd(params[0], params[1]);
  end;
1
2
3
4
5
6
7
8
9
10

Для запуска программы, я могу вызывать prog([1,2]) и я получу 3 в результате.

Я называю это компилятором потому, что я получаю из него скомпилированную анонимную функцию (prog) которую в последующем я могу вызывать столько раз сколько захочу. Также я могу использовать разные параметры для каждого вызова. В тоже время, это компилятор для очень специфичной архитектуры — набор функций (как CodegenAdd) который в этом сценарии могут представляет очень специфичный набор машинных инструкций.

Теперь более понятно, почему я назвал мой компилятор "что-то вроде компилятора". Он не компилирует программу в CPU-исполняемый формат, а использует очень специфичную среду времени выполнения — набор функций скомпилированных в Delphi программу и он не может быть сохранен как отдельно запускаемое приложение. За исключением всех ограничений, это мощная техника, запускаемый код быстрее чем простой интерпретатор того же языка. Но я захожу вперёд.

Эта статья просто введение в серию в которой я буду медленно презентовать мой проект. На данный момент запланированы следующие статьи:

  1. Языкopen in new window
  2. Абстрактное синтаксическое дерево (AST)open in new window
  3. Токинизаторopen in new window
  4. Парсерopen in new window
  5. Фреймворкopen in new window
  6. AST Dumperopen in new window
  7. Компилятор ASTopen in new window
  8. Интерпретатор AST
  9. Ускорение исполнения и расширение языка
  10. Ускорение интерпретатора

Нетерпеливые могут найти весь код и демонстрационный проект на GitHubopen in new window.

Последниее изменение: 24.08.2023, 06:42:55