Rave programming language

Greetings to all readers of this article.

Here I will try to describe a year of hard, hard work on my own compiler of the Rave programming language.

background

I have made various programming languages ​​many times already – creating them became something of a hobby for me after my studies.

However, all my programming languages ​​up to Rave were not very successful – some were too difficult to use, some had awkward syntax and low speed.

In the end, when I rethought everything, I decided to reliably prepare for the creation of a new compiler, the syntax and structure of which I tried to mark up before writing the code.

What happened, happened.

Basic language constructs and syntax

In the Rave programming language, the whole syntax is, in general, similar to the syntax of the C language.
This was done so that C and C++ programmers could fully master Rave in a couple of days and write freely on it.

Here is an example program that prints “Hello, world!” to the console on Rave:

import <std/io> // Импортируем файл io из глобальной папки std

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

As you can see, there is no preprocessor in Rave.

It was decided to completely abandon it in the middle of the design because of its shortcomings, which outweighed the possible advantages of using it.

Also, instead of the C printf function and the C++ cout function, Rave has its own println function.
In it, as in cout, you can enter values ​​in order, without specifying the types of arguments in the first line:

import <std/io>

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

But, if you prefer to use printf, you can call std::printf:

import <std/io>

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

One of the reasons why I myself started writing my other projects on Rave is beautiful lambdas (no matter how ridiculous it may sound):

import <std/io>

void bow {
    std::println("Bow");
}

void main {
    void() func = bow;
    void() func2 = void() {std::println("Func2");};
    func();
}

Like C, Rave has pointers and pointer arithmetic.

It is slightly more verbose than in C, but also safer due to the presence of runtime checks (disabled via a compiler flag) and compile-time checks:

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");
}

Error handling is also its own – it is more lightweight than working with exceptions, but it may seem somewhat inconvenient to some:

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);
    });
}

As I said, Rave does not have a preprocessor, however, there is a compile-time system that is popular among newer programming languages:

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

Through these commands, processing of a variable number of arguments is implemented.

Also, these commands allow you to control compiler flags (like turning on / off runtime checks), which can be useful if you are sure that a piece of code will not generate errors and bugs.

Rave has no classes, but structures have all the features of classes – inheritance (so far without the ability to cast a child structure to a parent one and vice versa), the presence of methods, and so on.

All these concepts were developed and written at the end of 2021 and throughout 2022.

Although this is only a part of everything that is in Rave, I believe that these examples are enough to appreciate the level of work that I personally and my team members have done.

Possible benefits

Rave has plenty of advantages over the same C:

  • Basic work with OOP;

  • Improved pointer security and improved error handling;

  • The absence of many shortcomings of C, C++ and other languages ​​(like the same preprocessor, although it is rather debatable to mark it as a shortcoming), and so on.

Possible disadvantages

Since Rave is developed by a fairly small number of people, there are bugs not found in the compiler, as well as not the best error handling (in the compiler itself).
For this very reason, the standard library is not developed at the level of similar programming languages ​​(like Zig), although it has all the basic (and even advanced) functionality needed to create programs and libraries.

Epilogue

The development of Rave for me and my team is a useful experience in constructing compilers, which may be useful for each of us in the future.

If you want to support our project or join its users, then here link to our site and GitHub.

Thanks for reading the article. See you!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *