Написание простого DSL компилятора на Delphi (7. Компилятор AST)

Перевод поста Writing a Simple DSL Compiler with Delphi (7. AST Compiler).

Эта статья представляет собой описание компилятора AST используемого для проекта моего языка программирования. Если вы только начинаете читать эту серию, то я бы рекомендовал вам начать с этого поста. Как минимум вы должны прочитать предыдущий пост Intermezzo так как он разъясняет некоторые части компилятора которых я не касаюсь здесь.

В каркасе моего игрушечного компилятора, компилятор (или codegen, как он называется внутри) — часть кода которая реализует интерфейс ISimpleDSLCodegen. Этот интерфейс предоставляет только одну функцию, Generate, которая принимает абстрактное синтаксическое дерево и преобразует его в объект, который реализует интерфейс ISimpleDSLProgram, который позволяет вам вызывать любую функцию скомпилированной программы по имени.

Читать далее Написание простого DSL компилятора на Delphi (7. Компилятор AST)

Написание простого DSL компилятора на Delphi (Intermezzo)

Перевод поста Writing a Simple DSL Compiler with Delphi (Intermezzo).

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

Результатом всего этого является программа introduction.dpr, автономная программа которая содержит полностью язык (очень тривиальный) вместе с полной документацией, написанная в стиле Грамотного программирования. Упрощено — вы можете читать её сверху вниз как историю.

В качестве intermezzo и для упрощения моего объяснения компилятора, я опишу эту программу здесь полностью, отформатировав её как пост в блог.

Читать далее Написание простого DSL компилятора на Delphi (Intermezzo)

Написание простого DSL компилятора на Delphi (6. Дамп AST)

Перевод поста Writing a Simple DSL Compiler with Delphi (6. AST Dumper).

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

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

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

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

Читать далее Написание простого DSL компилятора на Delphi (6. Дамп AST)

Написание простого DSL компилятора на Delphi (5. Фреймворк)

Перевод поста Writing a Simple DSL Compiler with Delphi (5. Framework).

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

Сейчас у нас есть работающий парсер который преобразует строку кода в абстрактное синтаксическое дерево. Однако ещё не время писать о самой интересной части — компиляторе — сначала мы должны сделать интеграцию и тестирование.

Мой игрушечный компилятор использует очень простой фреймворк доступ к которому производится через интерфейс ISimpleDSLCompiler (модуль SimpleDSLCompiler). Уместная часть интерфейса показана ниже:

Читать далее Написание простого DSL компилятора на Delphi (5. Фреймворк)

Написание простого DSL компилятора на Delphi (4. Парсер)

Перевод поста Writing a Simple DSL Compiler with Delphi (4. Parser).

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

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

После перерыва я вернулся к серии про мой "игрушечный компилятор". Сейчас я опишу работу парсера — части кода которая читает входной поток (обычно в форме токенов) и генерирует внутреннее представление программы (в моём случае абстрактное синтаксическое дерево).

Цель моего проекта была в изучении шагов компиляции и парсер был просто обязательным злом с которым я должен был иметь дело. Вот почему он написан в довольно примитивной форме, без использования улучшений как Pratt parser.

Мой парсер представлен как очень простой интерфейс. Он будет принимать код для разбора (как строку), ссылку на токинизатор которые должен использоваться для чтения входного потока и ссылку на корневой элемент результирующего AST. Функция вернёт False если разбор не удастся, в этом случае вызывающая сторона может преобразовать интерфейс парсера к ISimpleDSLErrorInfo для получения большей информации об ошибке.

Читать далее Написание простого DSL компилятора на Delphi (4. Парсер)

Написание простого DSL компилятора на Delphi (3. Токинезатор)

Перевод поста [Writing a Simple DSL Compiler with Delphi (3. Tokenizer])](https://www.thedelphigeek.com/2017/09/writing-simple-dsl-compiler-with-delphi.html).

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

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

С этой статьёй я перемещаюсь в важную часть проекта — код который читает исходный код и превращает его в красивое абстрактное синтаксическое дерево. Другими словами, я буду говорить о парсере.

Я должен признать что потратил на парсер так мало времени, как мог. В конце концов, моя основная цель конвертировать AST в запускаемый код, не разбор текста. Тем не менее, нельзя написать компилятор без написания парсера.

Читать далее Написание простого DSL компилятора на Delphi (3. Токинезатор)

Написание простого DSL компилятора на Delphi (2. Абстрактное синтаксическое дерево)

Перевод поста Writing a Simple DSL Compiler with Delphi (2. Abstract Syntax Tree).

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

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

Абстрактное синтаксическое дерево является, проще говоря, символическим представлением программы в виде дерева.

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

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

Читать далее Написание простого DSL компилятора на Delphi (2. Абстрактное синтаксическое дерево)

Написание простого DSL компилятора на Delphi (1. Язык)

Перевод поста Writing a Simple DSL Compiler with Delphi (1. The Language).

Эта статья представляет собой неформальное описание простого языка (далее я называю его "Язык") для которого я пишу компилятор. Если вы только начинаете читать эту серию, то я бы рекомендовал вам начать с этого поста.

Давайте начнём с простого примера который вычисляет i-тое число Фибоначчи

Код довольно прост. Первые два числа в последовательности Фибоначчи это единицы, а последующие являются суммой двух предыдущих числе в последовательности.

Следующие правила описывают язык (более или менее):

  • Язык относится к категории C-подобных языков.
  • Пробелы игнорируются.
  • Только один тип данных — целое число (integer)
  • Только три оператора: +, -, и <.
  • a < b возвращает 1 если a меньше чем b, и 0 в противоположном случае.
  • Только два оператора if и return.
  • Оператор if выполняет блок then если условное выражение не равно 0 и выполняет блок else в противном случае. Блок else обязателен.
  • Оператор return только устанавливает результат функции и не прерывает поток управления.
  • Нет оператора присваивания.
  • Каждая функция возвращает integer.
  • Параметры всегда передаются по значению.
  • Функции без оператора return возвращают 0.
  • Функции могут вызывать другие функции (или себя рекурсивно).

Как вы можете видеть, Язык ужасно ограничен, но в нем достаточно функционала для простых примеров. Язык также является функциональным, в терминах computer science. Мы будем использовать это в наших интересах намного позже в этой серии.

Немного более формальное (но всё ещё очень неформальное) описание синтаксиса:

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

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

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

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

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

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

Доклады KnowledgeConf 2019 про ведение конспектов

На конференции KnowledgeConf 2019 в основном были доклады связанные с управлением знания в организации, но были и два доклада связанных с управлением личными знаниями и конспектами. Они показались мне доволльно интересными.

Видео с конференции в открытом доступе сейчас нет, они будут открыты через несколько месяцев. Но по конспектам, ссылки на которые указаны ниже, можно понять основные положения докладов и куда дальше копать.

Применение практик Тиаго Форте для управления своими знаниями

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

Можно попробовать

  • Вести блог
  • Конспектировать
  • Копировать цита

Недостатки у всех этих способов:

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

Тиаго Форте предлагает для этого следующее решение:

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

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

Описание и презентация.

Как я 15 лет делал себе персональную Wiki для программиста

Описана разработка синтаксиса и подсветки для файлов с конспектами, в особенности для конспектов которые содержат много кусков кода. Сами файлы хранятся в Git.

Послушать было довольно интересно. Хотя практически, как мне кажется, удобнее применять распространённые языки лёгкой разметки. Это более переносимо, независимо от платформы и требует меньше времени. Возможно, ценой того что их нельзя настроить под себя. Я использую markdown и редактор Typora.

Описание и презентация.