Development Guide
This guide covers setting up your development environment, building the Lotus compiler, running tests, and contributing to the project.
Prerequisites
- Go 1.20+ - Programming language for the compiler
- LLVM 14+ - Required for the LLVM backend (default)
- GCC or Clang - For the legacy assembly backend (--gcc flag)
- Git - Version control
- Make - Build automation (optional)
Install Dependencies
Linux (Arch):
pacman -S go llvm gcc git make
Linux (Ubuntu/Debian):
sudo apt-get install golang-go llvm-dev gcc git make
macOS:
brew install go llvm gcc git make
Windows (WSL2):
# Inside WSL2
sudo apt-get install golang-go llvm-dev gcc git make
Setting Up Development Environment
1. Clone Repository
git clone https://github.com/j-alexander3375/Lotus.git
cd Lotus
2. Install Go Dependencies
go mod tidy
3. Build Compiler
go build -o lotus ./src
4. Verify Installation
./lotus -v
Should output version information if successful.
Project Structure
Directory Layout
Lotus/
├── src/
│ ├── main.go # Entry point and CLI
│ ├── tokenizer.go # Tokenization
│ ├── parser.go # Syntax parsing
│ ├── llvm_codegen.go # LLVM IR generation (default)
│ ├── codegen.go # Legacy x86-64 assembly generation
│ ├── optimizer.go # Peephole optimizations
│ ├── stdlib.go # Standard library
│ └── ... (other modules)
├── tests/ # Test files (.lts)
├── examples/ # Example programs
├── ext/ # VS Code extension
└── site/ # Documentation website
Module Responsibilities
- main.go - CLI interface and program entry point
- tokenizer.go - Tokenizes source code into tokens
- parser.go - Parses tokens into AST
- llvm_codegen.go - Generates LLVM IR (default backend)
- codegen.go - Generates x86-64 assembly (--gcc flag)
- optimizer.go - Peephole optimizations for assembly
- stdlib.go - Standard library implementation
Building and Testing
Development Build
go build -o lotus ./src
Optimized Build
go build -ldflags="-s -w" -o lotus ./src
Testing
# Run all tests
go test ./src
# Run specific test
go test -run TestName ./src
# Verbose output
go test -v ./src
Running a Lotus Program
./lotus -S -o output.s program.lts # Generate assembly
gcc -c output.s -o output.o # Assemble
gcc output.o -o program # Link
./program # Run
Common Development Tasks
Adding a New Built-in Function
- Declare function in
stdlib.go
- Implement code generation in appropriate module
- Add test cases in
*_test.go
- Update documentation
- Test thoroughly
Fixing a Bug
- Create a test case that reproduces the bug
- Verify test fails
- Fix the bug
- Verify test passes
- Check for regressions
Implementing a Language Feature
- Update lexer for new tokens (if needed)
- Update parser to handle new syntax
- Add type checking logic
- Implement code generation
- Write comprehensive tests
- Update documentation
Debugging
Generated Assembly
View generated assembly code:
./lotus -S -o output.s program.lts
cat output.s
Using GDB
# Build with debug symbols
go build -gcflags="-N -l" -o lotus ./src
# Run with debugger
gdb ./lotus
Printf Debugging
Add fmt.Printf statements in Go code to trace execution:
fmt.Printf("Debug: value=%d\n", value)
Test Failures
Run specific test with verbose output:
go test -v -run TestName ./src
Code Review Checklist
Before Submitting PR
- ✅ Code follows style guide
- ✅ All tests pass
- ✅ No regressions introduced
- ✅ Documentation updated
- ✅ Commit messages are clear
- ✅ Changes are focused and minimal
- ✅ Code is properly commented
Contributing to Lotus
Getting Started
- Fork the repository on GitHub
- Clone your fork locally
- Create a feature branch:
git checkout -b feature/your-feature
- Make your changes
- Write or update tests
- Update documentation
- Commit with clear messages
- Push to your fork
- Create a Pull Request
Pull Request Guidelines
- Title: Clear, concise description of changes
- Description: Explain what and why (not just what)
- Tests: Include test cases for new functionality
- Documentation: Update relevant docs
- Linked Issues: Reference any related issues
- One concern per PR: Keep scope focused
Reporting Issues
When reporting a bug, include:
- Clear description of the issue
- Steps to reproduce
- Expected vs actual behavior
- Environment (OS, Go version, Lotus version)
- Minimal reproducible example
Standard Library Development
Adding a New Module
- Define module structure in
stdlib.go
- Implement module functions
- Add to module registry
- Create comprehensive tests
- Document module API
Module Categories
- io - Input/output and formatting
- mem - Memory management
- math - Mathematical operations
- str - String operations
- future - Time, file I/O, collections, etc.
Performance Optimization
Profiling
Profile compiler performance:
go test -cpuprofile=cpu.prof -memprofile=mem.prof ./src
go tool pprof cpu.prof
Benchmarking
Write benchmarks in test files:
func BenchmarkCompile(b *testing.B) {
for i := 0; i < b.N; i++ {
// Code to benchmark
}
}
Common Optimization Areas
- Parser efficiency
- Type checking algorithms
- Code generation speed
- Memory allocations
Release Process
Version Numbering
Follow semantic versioning: MAJOR.MINOR.PATCH
- MAJOR: Breaking changes
- MINOR: New features (backward compatible)
- PATCH: Bug fixes
Release Steps
- Update version in appropriate files
- Update CHANGELOG
- Create release notes
- Tag release in Git
- Build release binaries
- Upload to GitHub Releases
- Update package managers (AUR, etc.)