Kod Katkısı Nasıl Yapılır
BERK Programlama Dili'ne kod katkısı yapmanız için rehber. Kod standartları, best practice'ler ve katkı süreci.
📝 Katkı Süreci
1. İssue Oluşturma veya Seçme
- Yeni özellik mi? Önce issue açın ve tartışın
- Bug fix mi? İlgili issue'yu bulun veya yeni oluşturun
good-first-issuelabel'ı ile başlayın
2. Fork ve Branch Oluşturma
# Repository'yi fork edin (GitHub UI'dan)
# Sonra local'e klonlayın
git clone https://github.com/KULLANICI_ADINIZ/berk.git
cd berk
# Upstream ekleyin
git remote add upstream https://github.com/ArslantasM/berk.git
# Feature branch oluşturun
git checkout -b feature/aciklayici-isim
# veya bug fix için
git checkout -b fix/bug-aciklamasi
3. Kod Yazma
# Değişiklik yapın
# Build ve test
cargo build
cargo test
cargo clippy
cargo fmt
# Değişiklikleri commit
git add .
git commit -m "feat: yeni özellik eklendi"
4. Pull Request Açma
# Değişiklikleri push edin
git push origin feature/aciklayici-isim
# GitHub'da Pull Request açın
# - Açıklayıcı başlık ve description
# - İlgili issue'yu bağlayın (#123)
# - Screenshot/örnek ekleyin (UI değişikliği ise)
📐 Kod Standartları
Rust Kodu
- Rustfmt:
cargo fmtile formatlanmalı - Clippy:
cargo clippyuyarısız olmalı - Naming: snake_case (fonksiyon/değişken), PascalCase (type/trait)
- Documentation: Public API'ler doc comment'e sahip olmalı
/// Parses a BERK expression into an AST node.
///
/// # Arguments
/// * `tokens` - Token stream to parse
/// * `precedence` - Operator precedence level
///
/// # Returns
/// Result containing the parsed expression or error
///
/// # Example
/// ```
/// let tokens = tokenize("5 + 3");
/// let expr = parse_expression(tokens, 0)?;
/// ```
pub fn parse_expression(
tokens: &[Token],
precedence: u8,
) -> Result {
// Implementation
}
BERK Kodu (stdlib)
/// İki sayıyı toplar ve sonucu döndürür.
///
/// @param a İlk sayı
/// @param b İkinci sayı
/// @return Toplam sonucu
///
/// @örnek
/// değişken sonuç = topla(5, 3) // 8
fonksiyon topla(a: tam, b: tam) -> tam {
döndür a + b
}
🧪 Test Yazma
Unit Test
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_simple_expression() {
let input = "5 + 3";
let result = parse_expression(input);
assert!(result.is_ok());
let expr = result.unwrap();
assert_eq!(expr.evaluate(), 8);
}
#[test]
fn test_parse_invalid_syntax() {
let input = "5 +";
let result = parse_expression(input);
assert!(result.is_err());
assert_eq!(
result.unwrap_err().kind,
ErrorKind::UnexpectedEndOfInput
);
}
}
Integration Test
// tests/integration/parser_tests.rs
use berk_lang::*;
#[test]
fn test_full_program_parsing() {
let source = r#"
fonksiyon main() {
değişken x = 10
değişken y = 20
yazdır(x + y)
}
"#;
let ast = parse_program(source).unwrap();
assert_eq!(ast.functions.len(), 1);
assert_eq!(ast.functions[0].name, "main");
}
Test Coverage
# Coverage raporu oluşturma
cargo install cargo-tarpaulin
cargo tarpaulin --out Html --output-dir coverage
# Minimum %80 coverage hedefliyoruz
📋 Commit Message Formatı
Conventional Commits kullanıyoruz:
type(scope): kısa açıklama
Detaylı açıklama (opsiyonel)
Breaking changes (opsiyonel)
Fixes #123
Type'lar:
feat- Yeni özellikfix- Bug fixdocs- Dokümantasyonstyle- Format değişikliğirefactor- Kod refactoringtest- Test ekleme/düzeltmechore- Build/tooling değişikliğiperf- Performans iyileştirmesi
Örnekler:
git commit -m "feat(parser): pattern matching desteği eklendi"
git commit -m "fix(codegen): LLVM pointer hatası düzeltildi"
git commit -m "docs(stdlib): math modülü örnekleri eklendi"
git commit -m "perf(lexer): token buffer size optimize edildi"
🎯 Best Practices
Kod Kalitesi
- ✅ KISS - Keep It Simple, Stupid
- ✅ DRY - Don't Repeat Yourself
- ✅ SOLID prensiplerine uyun
- ✅ Error handling yapın (
unwrap()yerine?) - ✅ Panic'ten kaçının,
Resultkullanın
Performans
- ⚡ Allocasyon'dan kaçının (mümkünse borrow kullanın)
- ⚡ Clone'dan kaçının
- ⚡ String yerine
&strkullanın (uygunsa) - ⚡ Benchmark yazın (kritik kod yolları için)
// ❌ Kötü - gereksiz allocation
fn process_string(s: String) -> String {
s.to_uppercase()
}
// ✅ İyi - borrow kullanımı
fn process_string(s: &str) -> String {
s.to_uppercase()
}
Hata Yönetimi
// ❌ Kötü - panic
fn read_file(path: &str) -> String {
std::fs::read_to_string(path).unwrap()
}
// ✅ İyi - Result döndürme
fn read_file(path: &str) -> Result {
std::fs::read_to_string(path)
}
// ✅ Daha iyi - custom error type
fn read_file(path: &str) -> Result {
std::fs::read_to_string(path)
.map_err(|e| BerkError::FileNotFound {
path: path.to_string(),
source: e,
})
}
🔍 Code Review Süreci
Pull Request Checklist
- ☑️ Tüm testler geçiyor mu?
- ☑️ Yeni testler eklendi mi?
- ☑️ Dokümantasyon güncellendi mi?
- ☑️
cargo clippyuyarısız mı? - ☑️
cargo fmtuygulandı mı? - ☑️ Breaking change var mı? (CHANGELOG.md)
- ☑️ Commit mesajları standartlara uygun mu?
Review Beklerken
- Sabırlı olun - review zaman alabilir
- Feedback'e açık olun
- Requested changes'leri hızlıca adresleyin
- Review'ları
Re-request reviewbutonuna tıklayarak bildirin
🚀 İleri Seviye Konular
LLVM Code Generation
// Örnek: Binary operasyon için LLVM IR üretme
fn codegen_binary_op(
&mut self,
op: BinaryOp,
lhs: &Expr,
rhs: &Expr,
) -> Result {
let lhs_val = self.codegen_expr(lhs)?;
let rhs_val = self.codegen_expr(rhs)?;
match op {
BinaryOp::Add => self.builder.build_add(lhs_val, rhs_val),
BinaryOp::Sub => self.builder.build_sub(lhs_val, rhs_val),
BinaryOp::Mul => self.builder.build_mul(lhs_val, rhs_val),
BinaryOp::Div => self.builder.build_div(lhs_val, rhs_val),
}
}
Parser Optimization
- Pratt parsing kullanın (operatör önceliği için)
- Lookahead minimize edin
- Error recovery ekleyin
🎓 Kaynak ve Öğrenme
- Rustc Dev Guide - Compiler design
- LLVM Documentation
- Crafting Interpreters
- Introduction to Compilers
🤝 İletişim
- GitHub Discussions: Genel tartışmalar
- Issues: Bug report ve feature request
- Pull Requests: Code review
- Email: arslantas.mustafa@gmail.com