Barego is a minimalist implementation of the Go language for use in barebone programming. Go code is transpiled into Zig's and compiled according to the target OS and ARCH. This makes compact binaries, especially with the freestanding
OS ( a few Kb!), hence the project name.
Motivation
Writing an operating system is challenging for a few reasons:
- safe by nature
- no control over the runtime and its overhead
- binaries are very large
Doing so is enjoyable nonetheless because of the expressiveness and simplicity of the language. In order to work around those challenges, barego
takes a very minimalist approach by stripping some of the core features of Go.
Differences with Go
A program written for barego
will work in go
but not the other way around.
- no runtime - no GC, channels, goroutines
- no generics
- no reflection
- no
goto
statements
- own basic std package
- explicit allocations with
new
, make
and append
- inline asm support
- no variable shadowing
- no support for complex numbers
- untyped values or expressions are not allowed
- unused function arguments generate a compilation error
- using the define operator (
:=
) generates a const in Zig
- single embedded files support (no pattern)
- defer handling
- no defer allowed in loops
- defer only accepts a function literal or a function declaration
- continue and break statements must use a label
fallthrough
not supported
- embedded types fields must be accessed by specifying the type name
e.g. var s = struct{MyType; x bool}
s.MyType.field
- methods are only supported on structs
Memory management (WIP)
Memory is manually managed. That's a step back from go
, but it helps in keeping barego
simpler and more predictable. However, there are specific rules that make this easier:
- pointers on local variables cannot be returned, they have to be no allocated (via new or make) variables
- object instantiation are only stack allocated (so they can only be returned as values)
- ...
Design
Go code is converted to Zig by a transpiler written in Go. It outputs a binary based on the OS and ARCH constraints same as Go.
Interfaces
Interfaces are one of the greatest feature of go
, and are also available in barego
. This is how they are modeled in Zig:
- all used interfaces are identified
- all types involved in those are grouped into their own dedicated union, generated at comptime, that implements that interface
TODO
Non exhaustive list of planned items:
- support closures
- asm
- guard against identifiers clashing with Zig's keywords (types.Universe)
e.g. var i1 = ...