Babygo, a go compiler made from scratch

Babygo is a small and simple go compiler. (Smallest and simplest in the world, I believe.)It is made from scratch and can compile itself.

  • No dependency to any libraries. Standard libraries and calling of system calls are home made.
  • Lexer, parser and code generator are hand written.
  • Emit assemble code which resutls in a single static binary.

It depends only on as as an assembler and ld as a linker.

It is composed of only a few files.

  • main.go - the main compiler
  • parser.go - parser
  • scanner.go - scanner(or lexer)
  • src/ - internal packages
  • lib/ - libraries


Lexer, Parser and AST

The design and logic of ast, lexer and parser are borrowed (or should I say "stolen") from go/ast, go/scanner and go/parser.

Code generator

The design of code generator is borrowed from chibicc , a C compiler.

Remaining parts (Semantic analysis, Type management etc.)

This is purely my design :)


It supports x86-64 Linux only.

If you are not using Linux, you can use a dedicated docker image for this project.

$ docker pull dqneo/ubuntu-build-essential:go
$ ./docker-run


Hello world

# Build babygo
$ go build -o babygo *.go

# Compile the hello world program by babygo
$ ./babygo example/hello.go

# Assemble and link
$ as -o hello.o /tmp/*.s
$ ld -o hello hello.o

# Run hello world
$ ./hello
hello world!

How to do self hosting

# Build babygo (1st generation)
$ go build -o babygo *.go

# Build babygo by babygo (2nd generation)
$ rm /tmp/*.s
$ ./babygo *.go
$ as -o babygo2.o /tmp/*.s
$ ld -o babygo2 babygo2.o # 2nd generation compiler

# You can generate babygo3 (3rd generation), babygo4, and so on...
$ rm /tmp/*.s
$ ./babygo2 *.go
$ as -o babygo3.o /tmp/*.s
$ ld -o babygo3 babygo3.o # 3rd generation compiler


$ make test