Locic 1.1 Soon

I’m currently working hard on the second release of ‘Locic’, the compiler tools for the Loci programming language. The initial target date was around mid-August and it looks likely that I will be able to release on schedule.

While 1.0 provides the key features of the language (classes, algebraic datatypes, templated types), this new release really fleshes out the language implementation (and the language itself!) to include lesser but nevertheless important features. The internal structure is also being improved thoroughly, to generate better error messages, better quality code, etc. Performance wise, the compiler is now around 50 times faster than 1.0 (tested on the Chain Reversi example), due mainly to optimisations focused on CodeGen. Testing is also much more thorough, with a much larger set of integration tests for accept/reject cases, and I’m planning to add some unit tests on top.

One of the most valuable improvements to the compiler in this release is the ‘template fix’. Specifically, you can now put a templated implementation in one module, a declaration in another module, and then just link* them together and everything will work nicely!

In other words, you can do this:

// ModuleA.loci
template <typename T>
interface Addable {
    T add(const T& other) const;
}

template <typename T: Addable<T>>
T addValues(T value0, T value1) {
    return value0 + value1;
}
// ModuleB.loci
template <typename T>
interface Addable {
    T add(const T& other) const;
}

template <typename T: Addable<T>>
T addValues(T value0, T value1);

void yourFunction() {
    int a = 1;
    int b = 2;
    int c = addValues<int>(a, b);
    // etc.
}

So the point here is that unlike C++ you can use a templated class or function without needing its implementation**. This is one of the many ground breaking features of Loci that enables:

  • No more avoiding Templated APIs; they can now be part of a stable API!
  • Switching between different implementations of a templated class/function by simply linking them together.
  • Much faster compile times.
  • Optimisations to more effectively balance trade-off of code size versus performance (i.e. it’s easier to generate multiple instantiations of a template than to merge them).
  • No need to release templated code to clients (in a commercial setting).

So now when users write templated constructs they don’t need to treat them any differently from normal constructs!

* You could generate object code and then use the platform linker. However, I’d strongly encourage the use of llvm-link followed by opt so that you can benefit from inter-procedural optimisation.

** Naturally some users will be interested in the implementation, and this will be explained fully in the language design document. To summarise, the compiler will generate vtables for each type and then effectively perform virtual calls as needed. If you then link two modules together and run opt on the result you’ll find that all the virtual calls are eliminated by inlining (unless the compiler determines it’s not beneficial, though currently it always inlines), generating similar (or better) code to what you’d write if you ‘manually’ instantiated the templates.