Releases: ediah/flower
"Барбарис"
Основные изменения кратко:
- Реализована поддержка многопоточности: директивы thread, fork, lock.
- Введён новый (и первый) модификатор типа: shared.
- Введён новый блок кода: bytecode {}.
- Введена новая директива include: можно включать файлы.
- Доработано взаимодействие со структурами.
- Удалёна операция REGR.
- Введена операция SHARE для общих переменных.
- Введена операция LOCK для ожидания завершения потоков.
- Настроен анализ покрытия кода, благодаря этому выявлено и исправлено множество ошибок.
- Настроена работа Doxygen. Пока задокументирован только один класс.
- Улучшена структура проекта, обрезаны лишние связи, выявленные построением графов Doxygen.
- Теперь у проекта новое название.
Многопоточность
Чтобы воспользоваться многопоточностью, необходимо описать поток следующим образом: thread: <номер потока> { <операции> }
. Номер потока должен быть от 1 до MAXTHREADS
. Затем вызвать поток с помощью функции fork(<номера через запятую>)
. Для ожидания главным потоком всех остальных можно использовать функцию lock()
. В потоках можно использовать только разделяемые переменные.
Разделяемые переменные
Понятие, которое имитирует поведение ссылок в C++. Это такая переменная, которая будет изменена в блоке, где вызвали функцию с передачей этой переменной в качестве параметра, после завершения этой функции.
Директивы bytecode
и include
Первой директивой можно открывать блоки для написания байт-кода, компилятор встроит такой код без изменений. Похожая возможность есть, например, в компиляторе gcc служебным словом __asm__
.
Вторая директива позволяет включать код из других файлов.
Структуры
Структуры были и до этого, но с этой версии теперь доступна передача их как параметров для функций. Сами функции теперь могут иметь структуры в качестве типа возвращаемого значения. Добавлена возможность арифметических действий над структурами, теперь можно упростить код такого вида:
A.x = B.x * 2 + C.x;
A.y = B.y * 2 + C.y;
A.z = B.z * 2 + C.z;
до одной строки:
A = B * 2 + C;
При этом в байт-коде второй вариант будет выглядеть так же, как и первый, так что это можно считать синтаксическим сахаром.
"Календула"
Рад сообщить, что фундамент для оптимизатора положен. Скорее всего, некоторые моменты я всё же перепишу, но с первого раза это уже выглядит солидно. Что работает на данный момент:
- Разбор кода на базовые блоки (построение графа потока управления). Затем можно получить .dot файл, который автоматически обрабатывается с помощью Graphviz.
- Построение ориентированного ациклического графа по базовому блоку. Необходимо для оптимизаций выражений.
Реализованные оптимизации:
- Выпрямление исполнения. Байт-код становится более линейным, исчезают "пустые" блоки, меньше переходов.
- Исключение одинаковых констант. Размер бинарного файла становится меньше за счёт удаления дубликатов констант.
- Оптимизация глобальных общих подвыражений (бета). При вычислении выражений используются результаты предыдущих вычислений, больше не придётся пересчитывать одно и то же. Иногда не замечает возможные замены, буду это исправлять.
- Удаление мёртвого кода (частично). Работает только удаление очевидно недостижимых блоков (на которые нет безусловного перехода), в том числе и неиспользуемые функции.
"Георгина"
В этом релизе впервые стало возможным использовать функции.
Разбивайте сложные задачи на множество маленьких, чтобы Ваше решение было таким же красивым, как георгина!
Правила работы с функциями
- def <идентификатор> ( [<описания переменных>] ): <простой тип> { [<описания переменных>] [ <операторы> ] return <выражение>; }
- <идентификатор> ( [ <идентификатор> ] {, <идентификатор>})
- Каждое описание начинается с ключевого слова def.
[A15-17, A19, B10]
- Формальные параметры одинакового типа можно описать через запятую без повторения типа. Параметры разного типа следует отделять ;.
[A15-17, A19, B9]
- После описания формальных параметров идёт определение типа возвращаемого функцией значения.
[A15-17, A19, B12]
- Переменные, описанные внутри некоторой функции (в том числе, в заголовке), доступны только в этой функции.
[A15-17, A19, B6, B8]
- В функции обязательно должен быть оператор возврата return.
[A15-17, A19, B11]
- На момент вызова функции она должна быть описана.
[A15-17, A19, B13]
- Количество фактических параметров должно совпадать с количеством формальных.
[A15-17, A19, B14]
- Типы фактических параметров должны совпадать с типами формальных.
[A15-17, A19, B14]
"Подснежник"
Версия с кодовым названием "Подснежник" компилятора модельного языка программирования представляет собой первый стабильный релиз.
Особенности реализации:
- Разбор кода методом рекурсивного спуска
- Основные операции: if - else, for, while, break, continue, goto, read, write
- Основные простые типы: int, real, string, bool
- Возможность описания пользовательского составного типа: struct
- Вычисление выражений с любыми простыми типами и полями структур простого типа
- При обнаружении ошибки выводится соответсвующее сообщение и продолжается чтение до конца
- Компиляция проводится для виртуальной стековой машины (
vmachine.cpp
)
Для запуска программ необходимо поместить код программы в папку test, скомпилировать:
./mlc path/to/prog.ml
и запустить бинарный файл на виртуальной машине:
./mlc