3

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?

Exagon
  • 4,798
  • 6
  • 25
  • 53
  • Say you write a generic `list` and then use a `list` and a `list`. The Vala compiler will write C-structs `list_int` and `list_double` that have the appropriate behavior. In other words the work of instantiating a specific generic is done by Vala. – nwp Jul 04 '16 at 09:02
  • 1
    Wouldn't this be the same as C++ templates? But templates haven't the exactly same behavior as generics I think. – Exagon Jul 04 '16 at 09:05
  • C++ templates behave similarly to C# generics (as explained [here](http://stackoverflow.com/a/31929/69809)). It's the same way vala generics will create actual structs for each generic parameter you pass. – vgru Jul 04 '16 at 09:09
  • 1
    C++ templates are not compiled into C-code, but the concept is the same. Of course the C-structs are written in a way to have the behavior that is correct according to Vala specs, not what C++ or C# say. – nwp Jul 04 '16 at 09:14
  • 1
    @nwp Only one C struct is created, see my answer. – Jens Mühlenhoff Jul 04 '16 at 10:45

1 Answers1

6

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.)

Jens Mühlenhoff
  • 14,565
  • 6
  • 56
  • 113