4.7 KiB
Compiler Modülü
Konum: src/compiler.rs
AST'yi bytecode'a dönüştürür. Tek geçişli (single-pass) derleme yapar. Tüm değişkenler global scope'tadır.
Konfigürasyon
MAX_REGISTERS = 8— Hesaplama için kullanılabilir register sayısı
Hata Türleri (CompileError)
| Hata | Açıklama |
|---|---|
UndefinedFunction(SmolStr) |
Tanımlanmamış fonksiyon (built-in dışı çağrı) |
RegisterLimitExceeded |
Register limiti aşıldı |
InvalidExpression(String) |
Geçersiz ifade |
InvalidStatement(String) |
Geçersiz deyim |
BytecodeError(String) |
Bytecode üretim hatası |
Compiler Yapısı
struct Compiler {
writer: BytecodeWriter,
used_registers: Vec<bool>,
// Jump address resolution
pending_jumps: Vec<(usize, usize)>,
labels: HashMap<usize, usize>,
next_label: usize,
// Debug info generation
debug_info: DebugInfo,
current_span: Span,
}
Derleme Akışı
Ana Derleme: compile(statements) -> Vec<u8>
Tek geçişli derleme süreci:
1. Deyimleri sırayla derle
2. End opcode'u yaz
3. Atlama adreslerini çözümle (resolve_jumps)
Kaynak Koddan Derleme: compile_from_source(source) -> (Vec<u8>, DebugInfo)
Parse ile birlikte pozisyon bilgisi de toplar ve DebugInfo üretir.
Deyim Derleme
Assignment (Atama)
- İfadeyi register'a derle
StoreGlobalemit et (tüm değişkenler global)
Mantıksal Operatörler (&&, \|\|) — Short-Circuit
compile_logical_op(); And/Or opcode'u yerine atlama ile derlenir, sağ taraf gerekmedikçe çalışmaz (x != null && x.name == "a" x null iken hata vermez):
<left> -> rL
JumpIfFalse rL, END (|| için JumpIfTrue)
<right> -> rR
Move rL, rR (rR == rL ise atlanır)
END: sonuç rL'de
Sol register sağ taraf derlenmeden önce serbest bırakılır (değeri sadece atlama yolunda lazım), böylece sağ taraf çoğunlukla aynı register'a düşer ve Move gerekmez. Sol operand Boolean olmak zorundadır (JumpIf* tip kontrolü yapar); sağ operandın değeri sonuç olarak geçer (true && 1 → 1).
If Statement (Koşullu Deyim)
1. Koşulu register'a derle
2. Else ve end için label oluştur
3. JumpIfFalse → else label
4. Then dalını derle
5. Jump → end label
6. Else label'ını set et, else dalını derle
7. End label'ını set et
İfade Derleme
Value (Sabit Değer)
- Register ayır →
LoadConstemit et
Variable (Değişken)
- Register ayır →
LoadGlobalemit et
BinaryOp (İkili Operasyon)
- Sol operandı register'a derle
- Sağ operandı register'a derle
- Sonuç register'ı ayır
- Uygun opcode'u emit et (Add, Sub, Mul, vs.)
- Operand register'ları serbest bırak
Not: String birleştirme derleme zamanında ayırt edilmez.
Op::Addher zamanOpCodeByte::Addemit eder; string birleştirme ve otomatik tip dönüşümü VM tarafından çalışma zamanında (runtime) ele alınır.
UnaryOp (Tekli Operasyon)
- Operandı register'a derle
- Sonuç register'ı ayır
NegveyaNotemit et
FunctionCall (Fonksiyon Çağrısı)
logbuilt-in fonksiyonu: Argümanları derle →Logemit et → Null register döndür- Diğer fonksiyonlar:
CallExternalopcode emit edilir (VM tarafından runtime'da çözümlenir)
ExprStmt (İfade Deyimi)
- İfadeyi derle →
SetResultemit et → Register'ı serbest bırak SetResult, VM'inexecute()dönüş değerini belirler (son ExprStmt kazanır)
MethodCall (Metod Çağrısı)
- Nesneyi register'a derle
- Argümanları derle
MethodCallemit et (sonuç, nesne, metod adı, argüman sayısı, argüman register'ları)
PropertyAccess (Özellik Erişimi)
- Nesneyi register'a derle
GetPropertyemit et (hedef register, nesne register, özellik adı string)
PropertyAssignment (Özellik Ataması)
- İç içe özellik zinciri (
a.b.c = expr) için:- Kök değişkeni
LoadGlobalile yükle - Ara özellikler için
GetPropertyzinciri emit et - Son özellik için
SetPropertyemit et - Değiştirilmiş kök nesneyi
StoreGlobalile geri yaz
- Kök değişkeni
Register Yönetimi
allocate_register() -> u8— İlk boş register'ı bul, yoksa hatafree_register(reg)— Register'ı kullanılabilir olarak işaretle- Toplam 8 register limiti var
Label ve Jump Yönetimi
| Metod | Açıklama |
|---|---|
create_label() -> usize |
Benzersiz label ID üret |
set_label(id) |
Label'ın bytecode pozisyonunu kaydet |
emit_jump_address(label) -> usize |
Placeholder yaz, çözümleme için kaydet |
emit_jump(label) |
Koşulsuz atlama emit et |
resolve_jumps() |
Tüm placeholder'ları gerçek adreslerle doldur |