Axum: The Enhanced C# 3.0 Compiler

Axum ships with an enhanced C# 3.0 compiler, which has support for certain Axum concepts – namely isolation and immutability. This compiler is necessary, because having separate C# projects with safety annotations is not always very convenient, plus, these annotations are not actually verified. The Axum C# 3.0 compiler can verify that classes/methods marked with isolated and readonly behave as they should. The Axum C# 3.0 compiler is invoked on files with the .qcs extension.

First of all, we have the isolated keyword. This is a class and method modifier. What it does is placing a guarantee that a class or method will not modify any statics (shared state). Under the hood, it applies the StrictAttribute. The Axum compiler fully verifies this. For example, this wouldn’t compile:

public static class AxumCSharp
{
    public static int Value;
    
    public isolated static void Evil()
    {
        Value = 42;
    }
}

This would yield a compiler error since we try to modify Value from Evil, which is an isolated method. If you had marked the entire class isolated, you wouldn’t be able to modify Value from any method at all. And I do mean, at all. There is no escape hatch. The unsafe keyword in the context of Axum C# 3.0 has the same effect as that of C# 3.0.

Isolated can be applied to interfaces, structs, etc. There are some subtle compiler bugs in some cases, though, where you might have to apply [Strict] instead.

Next up, we have the readonly keyword. This applies ReadableAttribute. And I don’t mean the field modifier. In Axum C# 3.0, we have a new method modifier called readonly, which can be used to enforce absolute immutability within a method; that is, a method marked with readonly must not modify any state whatsoever – except for local and parameters. That is, this is valid:

public static class AxumCSharp
{
    public static void Evil(List<int> l)
    {
        l = null;
    }
}

This compiles since l’s reference will only be set to null in the method’s context – it would be different if l was passed with ref.

But this is not:

public static class AxumCSharp
{
    public static void Evil(List<int> l)
    {
        l.Add(42);
    }
}

This will error, since Add is known to be a mutating method.

Furthermore, this will error too:

public isolated sealed class ValueHolder
{
    public ValueHolder(T value)
    {
        Value = value;
    }
    
    public readonly T Value { get; private set; }
    
    public readonly void Evil()
    {
        Value = default(T);
    }
}

Since we’re trying to modify the this object, the compiler complains.

So, what can we do with this? As I mentioned earlier, in the context of .ax files, where the Axum language compiler is used, the unsafe keyword allows you to call methods that may potentially modify statics. Or, to be more precise, methods that haven’t been annotated with [Strict] and [Readable]. By using isolated ([Strict]) and readonly ([Readable]) in our code, we can tell the Axum compiler that calling into some code is safe to do in parallel, and thus we won’t need the unsafe keyword. This greatly improves code correctness. However, as said, to get full compile-time checking, you need to use the Axum C# 3.0 compiler; the retail C# compiler won’t check the correctness of [Strict] and [Readable].

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s