A small compiler for a Go-like language, implemented in Go.
tiny-go demonstrates a complete compiler pipeline: lexical analysis, parsing, AST construction, LLVM IR generation, and native executable generation through Clang. It also includes experimental WebAssembly build support through LLVM wasm tools.
- Hand-written lexer for tokenising
.tgosource files - Parser for a small Go-like language subset
- AST representation with text and JSON output
- LLVM IR generation for functions, variables, expressions, and control flow
- Native build and run support through Clang
- Experimental WebAssembly output support
- CLI commands for inspecting each compilation stage
The current implementation focuses on a small but useful subset of Go-style syntax:
packagedeclarationsimportdeclarations- function declarations
- global and local variables
- assignment with
=and short declaration with:= - integer, float, and character literals
- arithmetic and logical expressions
if / elsestatementsforloopsbreak,continue, andreturn- simple built-in function calls, such as
builtin.println(...)
.
├── ast/ # AST node definitions and printing utilities
├── build/ # Build context: lex, parse, compile, run, and build orchestration
├── builtin/ # Built-in runtime support and embedded LLVM IR
├── compiler/ # AST-to-LLVM IR compiler
├── lexer/ # Tokeniser for tGo source code
├── parser/ # Parser for files, expressions, functions, and statements
├── token/ # Token and source-position definitions
├── main.go # CLI entry point
├── hello.tgo # Example tGo source file
└── run_wasm.js # Helper script for running wasm output
.tgo source
↓
Lexer
↓
Tokens
↓
Parser
↓
AST
↓
Compiler
↓
LLVM IR
↓
Clang / LLVM wasm tools
↓
Executable / WebAssembly output
- Go 1.19 or later
- Clang, for native executable generation
- Optional: LLVM wasm tools, such as
wasm-llcandwasm-ld, for WebAssembly output
Clone the repository:
git clone https://github.com/BOOSTERLEL/tiny-go.git
cd tiny-goDownload Go dependencies:
go mod downloadCheck the CLI:
go run . --helpInspect tokens:
go run . lex hello.tgoPrint the AST:
go run . ast hello.tgoPrint the AST as JSON:
go run . ast --json hello.tgoGenerate LLVM IR:
go run . asm hello.tgoCompile and run a tGo program:
go run . run hello.tgoBuild an executable:
go run . build hello.tgoThe current build command writes the output executable as a.out.exe.
package main
import "builtin"
func main() {
builtin.println(42)
}Save the file as hello.tgo, then run:
go run . run hello.tgoExpected output:
42
tgo run <file> # Compile and run a tGo program
tgo build <file> # Compile a tGo source file
tgo lex <file> # Print the token list and comments
tgo ast <file> # Parse source code and print the AST
tgo ast --json <file> # Print the AST in JSON format
tgo asm <file> # Generate and print LLVM IRGlobal options:
--goos Target operating system
--goarch Target architecture
--clang Path to clang
--wasm-llc Path to wasm llc tool
--wasm-ld Path to wasm linker
--debug, -d Keep intermediate build filesExample with a custom Clang path:
go run . --clang /usr/bin/clang run hello.tgoThe compiler is organised around a clear staged design:
lexerscans source code into tokens.parserconverts tokens into AST nodes.astdefines the intermediate tree representation.compilerlowers the AST into LLVM IR.buildwrites intermediate LLVM files and invokes Clang or wasm tools.builtinprovides the small runtime layer used by generated programs.
This makes the project useful for learning how a compiler frontend and a simple LLVM-based backend can be connected in Go.
Run tests:
go test ./...Format code:
go fmt ./...