Search code examples
cgenericscompiler-constructionvala

Vala generics to C code


I was reading about the language vala and that it compiles to Ansi C code. However I also saw it supports generics like Java or Rust. Now my question is how this is compiled to C code? If I have a gerneric class or function, what kind of C code is generated to simulate the generic behavior?


Solution

  • Vala generics are based on gpointer and GType.

    You can only specialize a Generic class with a pointer based type parameter.

    class MyClass<T> {
    
    public T val;
    
    }
    
    public static int main (string[] args) {
        // This wouldn't compile!
        // var il = new Gee.ArrayList<int> ();
    
        var il = new Gee.ArrayList<int?> ();
        var dl = new Gee.ArrayList<double?> ();
        il.add (5);
        dl.add (3.0);
    
        var im = new MyClass<int?>();
        im.val = 5;
    
        var dm = new MyClass<double?>();
        dm.val = 3.0;
    
        var lm = new MyClass< Gee.List<int?> > ();
        lm.val = il;
    
        return 0;
    }
    

    You can check the generated code yourself with the -C parameter:

    valac -C Main.vala --pkg gee-0.8
    

    This will generate a main.c file. If you read it carefully you will see there is only one struct for MyClass (plus some additional helper structs that are needed for GObject based classes) that has a member gpointer val, it also has a GType t_type as well as a t_dup_func and a t_destroy_func.

    struct _MyClass {
            // ...
            gpointer val;
    };
    
    struct _MyClassPrivate {
            GType t_type;
            GBoxedCopyFunc t_dup_func;
            GDestroyNotify t_destroy_func;
    };
    

    To ensure the correct type is passed in GLib type checking is performed. This makes Vala generics type safe (partially at compile time and partially at runtime).

    This is in contrast with C++ templates which are expanded at compile time. So it is closer to C# generics than to classic C++ templates.

    I wrote "partially at compile time" because the Vala compiler is smart enough to omit the type check in the C code when it knows that the assignment will always be correct.

    Also Vala generated C code is meant to be easily consumable for other programming languages that have GLib bindings (like C, Python, C++, GJS, etc.)