Plans for the next version (9-Oct-2019)

Even if the latest release of BL is closer to the real language we still miss lot of features and have lot of bugs to be fixed. Here is the list of things we're going to do next.

Switch statement

We can use "wall of ifs" now, but the switch is sometimes more elegant. Syntax for switches is not defined yet and we are open to new ideas.


    switch a {
    case A: // implicit fall through when case is empty?
    case B:
        break; // explicit end of the switch branch 
    case C:
        // declarations without need of explicit body '{}'
        i := 10;
    case D:
        print("a is D!!!\n");
        // no need for explicit break when case is not empty
    case E:
        print("a is E!!!\n"); 

    default: // default case like in C

Function overloading

We have no possibility to have the same function name twice in BL for now, but future plan is provide function overloading based on argument types.


    minimum :: fn (a: u32, b: u32) u32 #inline {
    if a < b { return a; } 
    return b;

    minimum :: fn (a: s32, b: s32) s32 #inline {
    if a < b { return a; } 
    return b;

Structure inheritance

The BL is never going to be OO language but we can provide kind of inheritance for structures with some additional features. Common way to simulate inheritance in C is composition:

    struct Entity {
        v3 position;
        quat rotation;

    struct Player {
        struct Entity base;
        const char *name;
        int age;

Since Player's 'base' member of type 'struct Entity' is listed first we can safely cast player instance pointer to entity pointer and build some abstraction on it, but accessing to the entity's members from player requires go through base. player_ptr->base.position. This is quite OK for one level of composition depth but what if we have even more specific structure based on Player, then access to the position looks like this: more_spec_player_ptr->base.base.position, and this is quite annoying…

BL version of the same concept should be something like this:

    Entity :: struct {
    position: v3,
    rotation: quat

    Player :: struct #extends Entity {
    name: string,
    age: s32

With hash directive #extends we're saying to the compiler that content of Entity structure should be implicitly inserted into the Player structure. Using Entity's position from player does not require going through base member then.

    player: Player; = "Travis";
    player.position = {:v3: 0};

Since compiler has an information about connection between player and entity we can allow implicit casting from pointer to the player to pointer to the entity like this:

    entity_update :: fn (entity: *Entity) { ... };

    player: Player;
    entity_update(&player); // no explicit cast needed here

Operator overloading

We've considered this feature as needed after few days of GL-math programming. Explicit calling of methods for vector calculations is not so comfortable. Basic idea is enable users to define custom operator behaviour for custom types.

    v3 :: struct {
    x: f32,
    y: f32,
    z: f32

    #operator + :: fn (a: v3, b: v3) v3 {
    return {:v3: a.x + b.x, a.y + b.y, a.z + b.z};

    #operator + :: fn (a: v3, b: f32) v3 {
    return {:v3: a.x + b, a.y + b, a.z + b};

    // usage
    vec_a: v3;
    vec_b: v3;

    // implicit operator handler call
    vec_a + vec_b;
    vec_a + 10.f;

But we have some open issues here still:

  • We don't want to pass larger structures by value into the operator handlers.
  • Problems with order of expressions in binary operations vec_a + 10.f; is not the same as 10.f + vec_a;. Do we need to specify handlers for both variants?
  • Should we enable overloading of unary operators? -vec_a;

Author: Martin Dorazil

Created: 2020-01-17 Fri 14:32