diff --git a/README.md b/README.md index 52857a99..dad55345 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,84 @@ -# Babygo: a go compiler made from scratch +# 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. -# Target machine +It depends only on `as` as an assembler and `ld` as a linker. -x86-64 Linux +It is composed of only 3 files. -# Test +* main.go - the main compiler +* runtime.go - runtime and standard library +* runtime.s - low level of runtime -```terminal +# Design + +## 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](https://github.com/rui314/chibicc) , a C compiler. + +## Remaining parts (Semantic analysis, Type management etc.) +This is purely my design :) + +# Environment + +It supports x86-64 Linux only. + +If you are not using Linux, you can use [a dedicated docker image](https://hub.docker.com/r/dqneo/ubuntu-build-essential/tags) for this project. + +```termiinal +$ docker pull dqneo/ubuntu-build-essential:go $ ./docker-run -# make test ``` -# How to do self hosting +# Usage + +## Hello world ```terminal -$ ./docker-run +# Build babygo +$ go build -o babygo main.go + + +# Build the hello world program by babygo +$ ./babygo < t/hello.go > /tmp/hello.s +$ as -o hello.o /tmp/hello.s runtime.s +$ ld -o hello hello.o -# go build -o babygo main.go # 1st generation compiler -# ./babygo < main.go > /tmp/babygo2.s -# as -o babygo2.o /tmp/babygo2.s runtime.s -# ld -o babygo2 babygo2.o # 2nd generation compiler -# ./babygo2 < main.go > /tmp/babygo3.s -# diff /tmp/babygo2.s /tmp/babygo3.s # assert babygo2.s and babygo3.s are same. +# You can confirm it's a single static binary +$ ldd ./hello + not a dynamic executable + +# Run hello world +$ ./hello +hello world! +``` + +## How to do self hosting + +```terminal +# Build babygo (1st generation) +$ go build -o babygo main.go + +# Build babygo by babygo (2nd generation) +$ ./babygo < main.go > /tmp/babygo2.s +$ as -o babygo2.o /tmp/babygo2.s runtime.s +$ ld -o babygo2 babygo2.o # 2nd generation compiler +$ ./babygo2 < main.go > /tmp/babygo3.s + +# Assert babygo2.s and babygo3.s are exactly same +$ diff /tmp/babygo2.s /tmp/babygo3.s +``` + +## Test + +```terminal +$ make test ``` # LICENSE @@ -31,4 +87,4 @@ MIT # AUTHOR -@DQNEO +[@DQNEO](https://twitter.com/DQNEO) diff --git a/t/hello.go b/t/hello.go new file mode 100644 index 00000000..66054792 --- /dev/null +++ b/t/hello.go @@ -0,0 +1,8 @@ +package main + +import "syscall" + +func main() { + var msg = []uint8("hello world!\n") + syscall.Write(1, msg) +}