Relying on Go

Everyone is creating a new programming language these days, often one that's "like Go but with more features" or "like Rust but simpler".

Solod, a systems language for C and Go developers, might look like one of those languages, but it takes a different approach.

Go's tooling

Solod is not "Go-like" in the usual sense, nor is it an attempt to "fix Go's mistakes". At the language level, Solod is literally a subset of Go. Solod reuses much of Go's existing tooling, including syntax highlighting, LSP, linters, and the package management system.

Take this quick-start guide, for example:

Quick start

Install the So command line tool:

go install solod.dev/cmd/so@latest

Create a new Go project and add the Solod dependency to use the So standard library:

go mod init example
go get solod.dev@latest

Write regular Go code, but use Solod packages instead of the standard Go packages:

package main

import "solod.dev/so/math"

func main() {
    ans := math.Sqrt(1764)
    println("Hello, world! The answer is", int(ans))
}

Run without saving the binary:

so run .

That's it!

There's nothing new here. It's mostly standard Go workflow, except for so run, which is a Go program that mimics go run.

Go's standard library

Solod also reuses a lot of Go's standard library code and tests. Some of it is taken verbatim from Go's source code, like these two string functions:

// CutPrefix returns s without the provided leading prefix string
// and reports whether it found the prefix.
func CutPrefix(s, prefix string) (string, bool) {
    if !HasPrefix(s, prefix) {
        return s, false
    }
    return s[len(prefix):], true
}

// HasPrefix reports whether the string s begins with prefix.
func HasPrefix(s, prefix string) bool {
    return len(s) >= len(prefix) && s[:len(prefix)] == prefix
}

Of course, Solod retains the Go authors' copyright.

Some code requires changes to support the manual memory management with explicit allocators used by Solod:

// Go version.
func Clone(s string) string {
    if len(s) == 0 {
        return ""
    }
    b := make([]byte, len(s))
    copy(b, s)
    return unsafe.String(&b[0], len(b))
}
// Solod version.
func Clone(a mem.Allocator, s string) string {
    if len(s) == 0 {
        return ""
    }
    b := mem.AllocSlice[byte](a, len(s), len(s))
    copy(b, s)
    return string(b)
}

You can probably see the resemblance.

A grain of salt

Go tools don't know that Solod is a subset of the full Go language, so they won't flag features Solod doesn't support, like function literals or iterators. These diagnostics come from the custom so tooling:

package main

func main() {
    f := func(n int) {
        println(n)
    }
    f(42)
}
main.go:4:7: function literals are not supported
    f := func(n int) {
         ^here

Also, although a substantial part of Go's standard library is ported verbatim or with minimal changes from the original source, that doesn't mean the code is automatically correct. Solod still needs its own tests, including ones that run under sanitizers and static analyzers.

It's all C in the end

All Solod code is translated to regular C11 and then compiled with GCC or Clang. Solod therefore relies on C tooling and decades of optimization work just as much as on Go's.

Solod code:

package main

import "solod.dev/so/math"

func main() {
    // What might it be?
    ans := math.Sqrt(1764)
    println("Hello, world! The answer is", int(ans))
}

Translated C code:

// -- main.h --
#pragma once
#include "so/builtin/builtin.h"
#include "so/math/math.h"

// -- main.c --
#include "main.h"

int main(void) {
    // What might it be?
    double ans = math_Sqrt(1764.0);
    so_println("%s %" PRIdINT, "Hello, world! The answer is", (so_int)(ans));
    return 0;
}

The C version is noisier, of course, especially for more complex programs than this one. But it remains readable.

And since there's no runtime, interoperability between Solod and C costs nothing.

Final thoughts

A new language doesn't necessarily need a new ecosystem.

Solod relies heavily on Go, and I see that as a strength, not a weakness. Reusing Go's proven tools and standard library makes Solod more reliable and easier to work with.

If you're interested, take a look at Solod's readme — it has everything you need to get started. Or try it online without installing anything.

★ Subscribe to keep up with new posts.