Типы данных под капотом ВМ:
null
unsigned int — 4 байта (для счетчиков)
int — 8 байт
double — 8 байт (5.0E-324… 1.7E308, значащих цифр: 15-16)
string — динамическая длина, 1 символ = 1 байт
array — массив указателей, длина фиксированная, размер зависит от разрядности ос, но её можно изменять через SetLen()
Для работы с битовыми операциями или же с байтами по-отдельности предусмотрены языковые операторы и ряд классов по типу stream, в будущем этот функционал языка будет расширен.
Т.к. Mash с динамической типизацией и относительно других современных языков производительностью не выделяется, то писать какие-либо низкоуровневые вещи, кодеки и т.п. требующие производительности разумно на нативных языках и в дальнейшем возможно использовать это все из Mash, если это необходимо.
Ну а так, в Mash будет все это поддерживаться на уровне "работает медленно, но корректно".
:)
В компиляторе каждая нода AST представляет собой класс (под каждый языковой блок — отдельный) + интерфейс базовой ноды.
Ноды, содержащие блоки кода, т.е. ноды class, enum, method, for, while и т.д. содержат массив, в который в процессе разбора кода закидываются по порядку ноды, входящие в блок кода.
Полное AST даже простого кода, который приведен в начале статьи выглядело бы очень громоздким, чтобы его тут постить, т.к. для того чтобы собрать этот код нужно также включить в сборку ряд файлов с базовыми классами & методами, благодаря которым все работает (например поддержка некоторых операторов языковых, инициализация выполнения кода, частичное управление памятью, обработка и traceback исключений, реализованы полностью на Mash'е, см. /bin/win64/inc/sys/*)
По поводу infinity — не во всех языках деление на ноль определено.
Деление — вещественная операция, т.е. при делении числа из типа int превращаются в тип float. Для целочисленного деления в языке есть отдельный оператор, как и во многих других языках.
Для закрытия стримов/сокетов и т.п. объявлены методы close(), т.е. после вызова поток закрыт, но все ещё находится в памяти ВМ, ждет своего часа, когда GC освободит память :)
Ну, хаб о высокой производительности, просто потому что можно выбрать 5 хабов :)
self-hosting уже делал, есть версия транслятора для Mash, написанная на Mash'e.
Но у неё есть один недостаток — время компиляции через неё кода на Mash. Одинаковый код компилятор на FPC и на Mash'е могут собирать 0,0001 сек. и 6-7 сек. соответственно.
Подводных камней очень много, начиная от того, что нужно изучить всю доступную теорию перед началом разработки (иначе выйдет полная фигня), заканчивая тем что нужно продумать ряд сложных моментов в архитектуре языка и ВМ, например как реализовать параллельную сборку мусора, передачу объектов по указателям из одного потока в другой, чтоб сборщик мусора случайно не освободил память, чтоб не было утечек памяти и т.п.
Пока занимался разработкой, понял почему эта сфера деятельности у разработчиков не очень популярна :)
Проект начал своё развитие в 2018-м и сейчас до сих пор он все ещё не завершенный :)
Возможно как доучусь до 4-го курса, то получится оформить все как конечную готовую работу.
Синтаксис в этом плане похож на Ruby немного :)
?= — присваивание указателя на объект.
= — присваивание значения.
@= — присваивание значения по виртуальному указателю (на сайте есть небольшая документация).
1. В репозитории лежит сборка языка, для тех у кого нет желания собирать проект самостоятельно, думаю таких людей много, ещё и на FPC все написано…
2. В репозитории полно примеров кода, bin/win64/test, примеры также включены в архив с пре-релизной сборкой.
3. Перегрузка операторов ещё не отлажена, будет добавлена в язык позже. Это второстепенная задача пока что.
4. Деструкторы в языке отсутствуют, т.к. есть сборщик мусора. Освободить память от того же экземпляра класса можно присвоив переменной с указателем на него — null.
5. Язык поддерживает конструкции try/catch/finally/raise, выравнивание стека при исключении, обратную трассировку исключений и в целом исключения довольно хорошо проработаны в Mash.
6. Ну опять же по API. Откройте любой пример, вы можете увидеть там println(). ВМ по умолчанию не поддерживает ни одной лишней функции, даже такой простой как вывод чего-либо в консоль. Весь функционал, расширяющий ВМ лежит в виде модулей в папке lib рядом с ней, либо должен лежать рядом с проектом (если требуется распространять потом mash приложение + свою библиотеку).
Исходники библиотек можно глянуть в ветке /runtime/libs/
7. Инструкция по сборке? Проект написан без зависимостей, .lpi файлы идут вместе с исходниками. Можно скачать Lazarus и собрать все за 5 минут. Ну а вообще для FPC процесс сборки выглядит очень даже просто, достаточно пары команд в консоль послать :)
8. Я не упоминал вроде, что язык высокопроизводительный. Без JIT'a он все ещё остается интерпретируемым, хоть и через стековую ВМ. Производительность языка пока что на уровне старых версий Python'а.
9. В языке можно разбивать проекты на кучу файлов, есть оператор uses. В этом плане все супер :)
Пока ещё рано говорить о преимуществах не завершенного проекта, перед альтернативами, над которыми трудились тысячи людей, на протяжении десятилетий :)
Пока что можно сказать, что это отечественный аналог Python'а, который можно встроить в какой-нибудь софт.
Спасибо за развернутый комментарий. В нем есть хорошие замечания, но стоит сказать пару слов про OpReg: Pointer и TList для хранения переменных.
Доступ к классам в Object Pascal осуществляется по указателю на экземпляр класса.
Конструктор класса возвращает указатель на созданный экземпляр.
Таким образом мы можем передавать доступ к экземплярам классов по через любой тип указателя (Pointer).
Использовать TList для хранения переменных — это действительно жутко не производительно.
Использовать хеш-таблицу — гораздо более лучший вариант.
Я реализовал более производительный вариант, в котором в процессе интерпретации не нужно обращаться к TList или хеш-таблице за переменными.
Указатели на экземпляры классов переменных помещаются в OpReg в процессе анализа кода и затем обращение к переменным идет по уже готовым указателям в этом буфере.
«и раз в 15 минут закатно смеяться в офисе без причины»
Хитрый ход headhunter. Коварный хитрый ход... :)
null
unsigned int — 4 байта (для счетчиков)
int — 8 байт
double — 8 байт (5.0E-324… 1.7E308, значащих цифр: 15-16)
string — динамическая длина, 1 символ = 1 байт
array — массив указателей, длина фиксированная, размер зависит от разрядности ос, но её можно изменять через SetLen()
Для работы с битовыми операциями или же с байтами по-отдельности предусмотрены языковые операторы и ряд классов по типу stream, в будущем этот функционал языка будет расширен.
Т.к. Mash с динамической типизацией и относительно других современных языков производительностью не выделяется, то писать какие-либо низкоуровневые вещи, кодеки и т.п. требующие производительности разумно на нативных языках и в дальнейшем возможно использовать это все из Mash, если это необходимо.
Ну а так, в Mash будет все это поддерживаться на уровне "работает медленно, но корректно".
:)
Тайпхинты в Python нужны чтоб код был более выразительным. Если нужно больше производительности, то на помощь придут декораторы @njit :)
Править AST можно как и любое дерево.
Речь шла про массив указателей на другие ноды.
Поддержку макросов можно внедрить хоть сейчас, только вот необходимость её наличия в таком языке конечно сомнительна :)
В компиляторе каждая нода AST представляет собой класс (под каждый языковой блок — отдельный) + интерфейс базовой ноды.
Ноды, содержащие блоки кода, т.е. ноды class, enum, method, for, while и т.д. содержат массив, в который в процессе разбора кода закидываются по порядку ноды, входящие в блок кода.
Полное AST даже простого кода, который приведен в начале статьи выглядело бы очень громоздким, чтобы его тут постить, т.к. для того чтобы собрать этот код нужно также включить в сборку ряд файлов с базовыми классами & методами, благодаря которым все работает (например поддержка некоторых операторов языковых, инициализация выполнения кода, частичное управление памятью, обработка и traceback исключений, реализованы полностью на Mash'е, см. /bin/win64/inc/sys/*)
Reference Counting + Interlocked операции, STW нету.
Для закрытия стримов/сокетов и т.п. объявлены методы close(), т.е. после вызова поток закрыт, но все ещё находится в памяти ВМ, ждет своего часа, когда GC освободит память :)
Ну, хаб о высокой производительности, просто потому что можно выбрать 5 хабов :)
self-hosting уже делал, есть версия транслятора для Mash, написанная на Mash'e.
Но у неё есть один недостаток — время компиляции через неё кода на Mash. Одинаковый код компилятор на FPC и на Mash'е могут собирать 0,0001 сек. и 6-7 сек. соответственно.
В языке отсутствует оператор;
Т.е. нельзя написать кучу кода в одну строку.
Если вам сложно собрать проект без зависимостей, путем нажатия 2-3 кнопок в ide, то в таком случае придется подождать до релиза :)
Пока занимался разработкой, понял почему эта сфера деятельности у разработчиков не очень популярна :)
Проект начал своё развитие в 2018-м и сейчас до сих пор он все ещё не завершенный :)
Возможно как доучусь до 4-го курса, то получится оформить все как конечную готовую работу.
?= — присваивание указателя на объект.
= — присваивание значения.
@= — присваивание значения по виртуальному указателю (на сайте есть небольшая документация).
2. В репозитории полно примеров кода, bin/win64/test, примеры также включены в архив с пре-релизной сборкой.
3. Перегрузка операторов ещё не отлажена, будет добавлена в язык позже. Это второстепенная задача пока что.
4. Деструкторы в языке отсутствуют, т.к. есть сборщик мусора. Освободить память от того же экземпляра класса можно присвоив переменной с указателем на него — null.
5. Язык поддерживает конструкции try/catch/finally/raise, выравнивание стека при исключении, обратную трассировку исключений и в целом исключения довольно хорошо проработаны в Mash.
6. Ну опять же по API. Откройте любой пример, вы можете увидеть там println(). ВМ по умолчанию не поддерживает ни одной лишней функции, даже такой простой как вывод чего-либо в консоль. Весь функционал, расширяющий ВМ лежит в виде модулей в папке lib рядом с ней, либо должен лежать рядом с проектом (если требуется распространять потом mash приложение + свою библиотеку).
Исходники библиотек можно глянуть в ветке /runtime/libs/
7. Инструкция по сборке? Проект написан без зависимостей, .lpi файлы идут вместе с исходниками. Можно скачать Lazarus и собрать все за 5 минут. Ну а вообще для FPC процесс сборки выглядит очень даже просто, достаточно пары команд в консоль послать :)
8. Я не упоминал вроде, что язык высокопроизводительный. Без JIT'a он все ещё остается интерпретируемым, хоть и через стековую ВМ. Производительность языка пока что на уровне старых версий Python'а.
9. В языке можно разбивать проекты на кучу файлов, есть оператор uses. В этом плане все супер :)
Спасибо за вопросы :)
Пока что можно сказать, что это отечественный аналог Python'а, который можно встроить в какой-нибудь софт.
Язык создан в основном в академических целях.
Но вообще, т.к. он встраиваемый, то применение ему найти думаю можно :)
Доступ к классам в Object Pascal осуществляется по указателю на экземпляр класса.
Конструктор класса возвращает указатель на созданный экземпляр.
Таким образом мы можем передавать доступ к экземплярам классов по через любой тип указателя (Pointer).
Использовать TList для хранения переменных — это действительно жутко не производительно.
Использовать хеш-таблицу — гораздо более лучший вариант.
Я реализовал более производительный вариант, в котором в процессе интерпретации не нужно обращаться к TList или хеш-таблице за переменными.
Указатели на экземпляры классов переменных помещаются в OpReg в процессе анализа кода и затем обращение к переменным идет по уже готовым указателям в этом буфере.
В посте я решил разобрать задачу на стажировку, а не подать апелляцию в JB, так что было бы правильно указывать такие моменты без обобщения :)