Написание простого 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
}
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;
2
3
4
5
6
7
8
9
10
Для запуска программы, я могу вызывать prog([1,2])
и я получу 3 в результате.
Я называю это компилятором потому, что я получаю из него скомпилированную анонимную функцию (prog
) которую в последующем я могу вызывать столько раз сколько захочу. Также я могу использовать разные параметры для каждого вызова. В тоже время, это компилятор для очень специфичной архитектуры — набор функций (как CodegenAdd
) который в этом сценарии могут представляет очень специфичный набор машинных инструкций.
Теперь более понятно, почему я назвал мой компилятор "что-то вроде компилятора". Он не компилирует программу в CPU-исполняемый формат, а использует очень специфичную среду времени выполнения — набор функций скомпилированных в Delphi программу и он не может быть сохранен как отдельно запускаемое приложение. За исключением всех ограничений, это мощная техника, запускаемый код быстрее чем простой интерпретатор того же языка. Но я захожу вперёд.
Эта статья просто введение в серию в которой я буду медленно презентовать мой проект. На данный момент запланированы следующие статьи:
- Языкopen in new window
- Абстрактное синтаксическое дерево (AST)open in new window
- Токинизаторopen in new window
- Парсерopen in new window
- Фреймворкopen in new window
- AST Dumperopen in new window
- Компилятор ASTopen in new window
- Интерпретатор AST
- Ускорение исполнения и расширение языка
- Ускорение интерпретатора
Нетерпеливые могут найти весь код и демонстрационный проект на GitHubopen in new window.