Язык программирования Rave

от автора

Приветствую всех читателей данной статьи.

Тут я постараюсь описать год усердной, тяжёлой работы на моим собственным компилятором языка программирования Rave.

Предыстория

Я уже много раз делал различные языки программирования — их создания стало для меня чем-то вроде хобби после учёбы.

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

В итоге, когда я всё переосмыслил, я решил надёжно подготовиться к созданию нового компилятора, синтаксис и устройство которого я попытался разметить перед написанием кода.

Что получилось, то получилось.

Основные языковые конструкции и синтаксис

В языке программирования Rave весь синтаксис, в целом, похож на синтаксис языка С.
Это было сделано, чтобы С и С++ программисты могли за пару-дней полностью освоить Rave и свободно на нём писать.

Вот пример программы, которая выводит «Hello, world!» в консоль на Rave:

import <std/io> // Импортируем файл io из глобальной папки std  void main { // Если функция без аргументов, скобки указывать необязательно     std::println("Hello, world!"); }

Как можно заметить, препроцессора в Rave нет.

Было решено полностью отказаться от него ещё в середине проектирования из-за его недостатков, которые перевешивали возможные преимущества его использования.

Также, вместо С функции printf и С++ функции cout у Rave есть своя функция — println.
В неё, как и в cout, можно вводить значения по-порядку, без указания типов аргументов в первой строке:

import <std/io>  void main {     std::println("Текущий год - ",2023,"."); }

Но, если вы предпочитаете использовать printf, вы можете вызвать std::printf:

import <std/io>  void main {     std::printf("Текущий год: %d\n",2023); }

Одна из причин, почему я сам начал писать свои остальные проекты на Rave — это красивые лямбды(как бы смешно это не звучало):

import <std/io>  void bow {     std::println("Bow"); }  void main {     void() func = bow;     void() func2 = void() {std::println("Func2");};     func(); }

Как и в С, в Rave есть указатели и арифметика указателей.

Она чуть более многословная, чем в С, однако и более безопасная, за счёт наличия runtime-проверок(отключаемых через флаг компилятора) и compile-time проверок:

void main {       void* a; // Переменные автоматически инициализируются в null(можно отключить)       a = itop(void*,0); // Ошибка       int b;       std::scanf("%d",&b);       a = itop(void*,b); // Если b == 0 - runtime ошибка       b = ptoi(a);       std::assert(b == 1, "b != 1"); }

Обработка ошибок также своя — она более легковесная, чем работа с исключениями, однако может показаться некоторым несколько неудобной:

import <std/error>  // Оператор => является сокращением вызова команды return в конце блока функции std::error<int> func => std::error<int>(10,"",0); // Первый аргумент - значение // Второй - сообщение, которое нужно вывести при ошибке // Третий - код ошибки  void main {     // Все вызовы функций с возвращаемым типом std::error     // в try автоматически проверяются на ошибку, и возвращают     // исходный тип, который указан в std::error        try {         int base = func();     }     // base виден во всей функции        auto base2 = func();     base2.catch();     // Также, std::error поддерживает свой обработчик ошибки     base2.catch(void(char* msg,int code) {       std::println("Error: '",msg,"', code: ",code);       std::exit(1);     }); }

Как я уже сказал, в Rave нету препроцессора, однако, есть система compile-time, популярная среди новых языков программирования:

@if(__RAVE_OS != "LINUX") {     @errorln("Данная библиотека не поддерживает платформу ",__RAVE_OS,"."); }

Через эти команды реализована обработка переменного количества аргументов.

Также, эти команды позволяют управлять флагами компилятора(вроде включения/выключения runtime-проверок), что может пригодится, если вы уверены, что участок кода не будет порождать ошибки и баги.

Rave не имеет классов, но структуры имеют все возможности классов — наследование(пока-что без возможности приведения дочерней структуры к родительской и наоборот), наличие методов и так далее.

Все эти концепции разрабатывались и писались в конце 2021 и на протяжении всего 2022 года.

Хоть это — лишь часть всего, что есть в Rave, я считаю, что этих примеров достаточно, чтобы оценить уровень работы, которую провёл лично я и участники моей команды.

Возможные преимущества

Преимуществ перед тем же С у Rave предостаточно:

  • Наличие базовой работы с ООП;

  • Наличие улучшенной безопасности работы с указателями и улучшенной обработки ошибок;

  • Отсутствие многих недостатков С, С++ и прочих языков(вроде того же препроцессора, хоть помечать его как недостаток довольно спорно), и так далее.

Возможные недостатки

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

Эпилог

Разработка Rave для меня и моей команды является полезным опытом в конструировании компиляторов, что может в будущем пригодится каждому из нас.

Если вы хотите поддержать наш проект или присоединиться к его пользователям, то вот ссылка на наш сайт и GitHub.

Спасибо за прочтение статьи. До встречи!


ссылка на оригинал статьи https://habr.com/ru/post/712036/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *