Thank you for your interest in contributing to Roast! We welcome contributions from developers of all experience levels. This guide will help you get started.
- Fork the repository on GitHub
- Clone your fork locally:
git clone https://github.com/your-username/roast-compiler.git cd roast-compiler
- Build the project:
cargo build
- Run tests to ensure everything works:
cargo test
Found a bug? We'd love to hear about it!
- Search existing issues first
- Create a new issue with:
- Clear, descriptive title
- Steps to reproduce the bug
- Expected vs actual behavior
- Environment details (OS, Rust version)
- Sample code that demonstrates the issue
- Error messages (if any)
Have an idea for a new feature?
- Check discussions for similar ideas
- Open a discussion to get community feedback
- Create an issue with the
enhancement
label if approved
Ready to write some code? Great!
Look for issues labeled good first issue
. These are:
- Well-defined problems
- Limited in scope
- Perfect for newcomers
- Include mentoring support
- Choose an issue or create one for your feature
- Comment on the issue to let others know you're working on it
- Create a branch from main:
git checkout -b feature/your-feature-name
- Make your changes following our coding standards
- Add tests for new functionality
- Run the full test suite:
cargo test cargo clippy cargo fmt --check
- Commit with clear, descriptive messages
- Push your branch and create a Pull Request
- Rust 1.70+ - Install from rustup.rs
- Git - For version control
- Your favorite editor - VS Code with rust-analyzer is recommended
# Build in debug mode
cargo build
# Build in release mode (optimized)
cargo build --release
# Run tests
cargo test
# Run specific test
cargo test test_name
# Check code formatting
cargo fmt --check
# Format code
cargo fmt
# Run linter
cargo clippy
# Run with debug output
cargo run -- --debug --interpret examples/hello.rst
# Generate documentation
cargo doc --open
Understanding the codebase:
src/
βββ main.rs # CLI interface and argument parsing
βββ lexer.rs # Tokenization of source code
βββ parser.rs # Syntax analysis (AST building)
βββ ast.rs # Abstract Syntax Tree definitions
βββ semantic.rs # Type checking and semantic analysis
βββ symbol_table.rs # Variable and function scope management
βββ codegen.rs # Code generation (interpreter + LLVM)
βββ optimizer.rs # Code optimization passes
βββ error.rs # Error types and handling
βββ gc.rs # Garbage collection (future)
βββ module_system.rs # Module resolution (future)
βββ async_runtime.rs # Async support (future)
βββ llvm_backend.rs # LLVM code generation (optional)
We use standard Rust formatting:
# Format your code before committing
cargo fmt
- Functions:
snake_case
- Variables:
snake_case
- Types/Structs:
PascalCase
- Constants:
SCREAMING_SNAKE_CASE
- Modules:
snake_case
- Public APIs: Must have doc comments
- Complex functions: Add inline comments explaining logic
- Examples: Include usage examples in doc comments
/// Parses a Roast expression from tokens.
///
/// # Arguments
/// * `tokens` - The token stream to parse
///
/// # Returns
/// * `Ok(Expression)` - Successfully parsed expression
/// * `Err(ParseError)` - Parse error with location info
///
/// # Examples
/// ```
/// let tokens = vec![Token::Integer(42)];
/// let expr = parse_expression(tokens)?;
/// ```
pub fn parse_expression(tokens: Vec<Token>) -> Result<Expression> {
// Implementation here
}
- Use
Result<T, CompilerError>
for fallible operations - Provide detailed error messages with location information
- Use the
?
operator for error propagation
// Good
fn parse_token(&mut self) -> Result<Token> {
match self.current_char() {
Some('+') => Ok(Token::Plus),
Some(c) => Err(CompilerError::LexicalError {
line: self.line,
column: self.column,
message: format!("Unexpected character: '{}'", c),
}),
None => Err(CompilerError::LexicalError {
line: self.line,
column: self.column,
message: "Unexpected end of input".to_string(),
}),
}
}
- Unit tests: Test individual functions/methods
- Integration tests: Test complete compilation flows
- Example tests: Ensure all examples compile and run correctly
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tokenize_integer() {
let mut lexer = Lexer::new("42");
let token = lexer.next_token().unwrap();
assert_eq!(token.kind, TokenKind::Integer(42));
}
#[test]
fn test_parse_assignment() {
let tokens = vec![
Token::new(TokenKind::Identifier("x".to_string()), 1, 1),
Token::new(TokenKind::Equal, 1, 3),
Token::new(TokenKind::Integer(42), 1, 5),
];
let mut parser = Parser::new(tokens);
let stmt = parser.parse_statement().unwrap();
// Assert statement structure
}
}
# Run all tests
cargo test
# Run tests with output
cargo test -- --nocapture
# Run specific test module
cargo test lexer
# Run integration tests
cargo test --test integration
# Run with coverage (requires cargo-tarpaulin)
cargo tarpaulin --out Html
-
Unit Tests (
#[test]
)- Test individual functions
- Mock dependencies when needed
- Fast execution
-
Integration Tests (
tests/
directory)- Test complete workflows
- Use real file I/O
- End-to-end scenarios
-
Example Tests
- Ensure all examples compile
- Verify expected output
- Regression testing
#[test]
fn test_binary_addition() {
// Arrange
let left = Expression::Literal(Literal::Integer(2));
let right = Expression::Literal(Literal::Integer(3));
let expr = Expression::BinaryOp(BinaryOperation {
left: Box::new(left),
operator: BinaryOperator::Add,
right: Box::new(right),
location: None,
});
// Act
let mut interpreter = InterpreterCodeGenerator::new("test", false);
let result = interpreter.evaluate_expression(expr).unwrap();
// Assert
assert_eq!(result, Value::Integer(5));
}
Help us expand Roast's capabilities:
- List and dictionary types: Implement built-in collections
- For loops: Add
for item in collection
syntax - List comprehensions: Python-style
[x*2 for x in numbers]
- Exception handling: try/except blocks
- Classes and objects: Object-oriented programming support
- Decorators: Function and class decorators
Enhance the compiler itself:
- Better error messages: More helpful suggestions and context
- Performance optimization: Faster compilation and execution
- Memory usage: Reduce compiler memory footprint
- Incremental compilation: Only recompile changed files
- Parallel compilation: Multi-threaded compilation
Help others learn Roast:
- Tutorial series: Step-by-step guides for beginners
- Advanced examples: Complex real-world programs
- API documentation: Comprehensive standard library docs
- Video tutorials: Screencasts and presentations
- Blog posts: Technical deep-dives and case studies
Improve the development experience:
- Language server: IDE support with autocomplete and error checking
- Debugger: Step-through debugging support
- Package manager: Dependency management system
- Build tools: Project scaffolding and build automation
- Editor plugins: Syntax highlighting and snippets
Build the Roast ecosystem:
- Standard library: Core modules and utilities
- Package registry: Central package repository
- Web framework: HTTP server and web development tools
- Data science tools: NumPy-like numerical computing
- GUI toolkit: Desktop application development
Join our Discord server for:
- Real-time discussion
- Help with contributions
- Design decisions
- Community events
Use GitHub Discussions for:
- Feature proposals
- Design questions
- Show and tell
- Q&A
Use GitHub Issues for:
- Bug reports
- Feature requests
- Documentation improvements
- Task tracking
We appreciate all contributions! Contributors are recognized through:
- Contributor list in README
- Release notes acknowledgments
- Discord roles for active contributors
- Special mentions in blog posts and social media
By contributing to Roast, you agree that your contributions will be licensed under the MIT License.
Don't hesitate to ask questions:
- Discord: Real-time help and discussion
- GitHub Discussions: Longer-form questions and proposals
- Issues: Specific bugs or feature requests
- Email: [email protected] for private matters
Thank you for making Roast better! π