January progress update and 2017 summary

Since the last update I am now able to import external functions from Go. This simple example compiles to valid Go:

module Main

extern func println = "fmt.Println" (str: string) -> ()
extern func printf1 = "fmt.Printf" (str: string, arg1: string) -> ()

let main = {
    printf1("Woo I can print %s\n", "6")
    println("Another print")

The generated Go code will correctly import the fmt package only once, and imported functions have Braid stubs generated, which are type-checked. This means, for example, that calling printf1 with a second argument that isn’t a string won’t compile.

(I’ve not yet thought about how to handle importing variadic functions, but may just add a specific type annotation that requires and correctly unpacks an array argument on any subsequent calls.)

Speaking of which, handling external imports necessitated handling type annotations, so here they are! These work for both external and internal function definitions. This means a function like the following, which would have previously inferred a generic “number” type, can be specialised to handle only the int type using type annotations:

let add = (a: int64, b: int64) -> int64 {
	a + b

My next job will be handling complex type annotations. This will allow list types, sum and record types containing complex types and referring to each other, and crucially, the importing of external Go types. I have a minimal “hello world” web server example I’m working against that requires external types (for example, ResponseWriter and Request), and that, after this is done, should be valid compilable Braid code.

Looking back on 2017

I started writing this iteration of Braid in March 2017, focussing on lexing and parsing. I wasn’t doing much with the resulting AST for a long time, was only able to infer types from August, and wasn’t able to compile any of this to Go until October. In November I was able to compile fully valid Go, ignoring unused variables, and in December I added external imports. Looking back on it here it’s clear that development accelerated as I built more of a foundation to work on, which is very encouraging!

However, I still don’t like Go much at all. This is a problem.

I never really liked Go the language, only Go the platform, but I thought I would move through the stages of grief and arrive at acceptance more quickly. Right now I think I still move between anger, depression, and bargaining, depending on the day. Go is not a bad language, and I know I’m writing some very non-idiomatic code for a domain that Go may not be suited for, so I’m not exactly helping… but it’s still really not my jam. So many of its design decisions frustrate me even now, which makes me think that I am just not its intended audience.

The whole idea was to create a language that wasn’t Go, but targeted Go, meaning I could write in a nicer language and still take advantage of static binaries, speed, and a thriving ecosystem. That may still work in future, but I have to put up with it for a while before that situation can be realised.

I hope I’ll be able to stand it, at least long enough that I have some useful source code to share. If I can make it until then, perhaps others will help share the burden.