Files
dexpr/docs/vm.md
2026-04-07 15:16:19 +03:00

8.6 KiB
Raw Permalink Blame History

VM (Virtual Machine) Modülü

Konum: src/vm/

Register tabanlı sanal makine. Bytecode'u çalıştırır, 8 register ve global değişken deposu içerir.


Alt Modüller

Dosya İçerik
vm/mod.rs Modül export'ları
vm/vm.rs Ana VM implementasyonu (core çalıştırma döngüsü)
vm/methods.rs Metod dispatch (String, StringList, NumberList, Object metodları)
vm/builtins.rs Built-in fonksiyon implementasyonları (abs, min, max, floor, ceil, round, sqrt, len, toString, toNumber)
vm/error.rs Hata türleri (VMError)
vm/debug_info.rs Bytecode offset → kaynak konum eşleştirme

VMError (Hata Türleri)

Dosya: src/vm/error.rs

Hata ıklama
TypeMismatch { expected, got } Tip uyuşmazlığı
UndefinedVariable(SmolStr) Tanımlanmamış değişken
DivisionByZero Sıfıra bölme
BytecodeError(String) Bozuk bytecode
MethodNotFound { type_name, method } Metod bulunamadı
RuntimeError(String) Genel çalışma zamanı hatası
InvalidOperation { operation, left_type, right_type } Desteklenmeyen operasyon
WithLocation { span, message } Kaynak konum bilgili hata

with_span(span) metodu hatayı kaynak konum bilgisi ile sarar (çift sarmalamayı önler).


DebugInfo

Dosya: src/vm/debug_info.rs

Bytecode offset'lerini kaynak kod konumlarına (Span) eşleştirir. Run-length encoded yapıda: her girdi bir sonraki girdiye kadar geçerlidir.

struct DebugInfo {
    entries: Vec<(u32, Span)>,  // sıralı (offset, span) çiftleri
}

Metodlar:

  • add_entry(offset, span) — Eşleştirme ekle (artan offset sırasında)
  • get_span(offset) -> Option<Span> — Binary search ile konum bul

VM Yapısı

struct VM<'a> {
    // Bytecode durumu
    bytecode: &'a [u8],
    reader: BytecodeReader<'a>,
    pc: usize,

    // Hesaplama
    registers: [Value; 8],      // 8 register

    // Değişkenler
    globals: Map<SmolStr, Value, 64>, // Global kapsam (max 64 giriş)

    // Kaynaklar
    heap: Bump,                 // Bump allocator

    // Debug
    debug_info: Option<DebugInfo>,
    debug: bool,                // Debug çıktısı (debug build'lerde)
    opcode_counts: [usize; 256], // Profiling (debug build'lerde)
}

Başlatma ve API

Metod ıklama
new(bytecode) VM oluştur
set_debug_info(debug_info) Kaynak konum eşleştirmesi sağla
set_global(name, value) Global değişken ata
get_global(name) -> Option<&Value> Global değişken oku
register_function(name, fn) Harici (host) fonksiyon kaydet
register_method(type_name, method_name, fn) Tipe özel harici metod kaydet
reset() Durumu sıfırla, yeniden çalıştırmaya hazırla

Çalıştırma Döngüsü

execute() -> Result<Value, VMError> (son expression'ın değerini döndürür):

  1. VM durumunu sıfırla
  2. Bytecode kaldığı sürece döngüde çalış:
    • Opcode byte'ını oku
    • İlgili handler'a yönlendir
    • Hataları kaynak konum bilgisi ile sar
    • Profiling verilerini güncelle (debug build)
    • End opcode'unda dur

Opcode Handler'ları

Register ve Bellek

  • handle_load_const() — Bytecode'dan değer oku, register'a koy
  • handle_move() — Register → register kopyala
  • handle_load_global() — Global map → register
  • handle_store_global() — Register → global map

Aritmetik

  • binary_op(f, name) — Genel handler: iki operand register'ı oku, fonksiyonu uygula, sonucu kaydet
  • Sıfıra bölme kontrolü yapılır
  • Add opcode: Sayısal toplama yanında string birleştirmeyi de destekler. Otomatik tip dönüşümü (auto-coercion) yapılır: String+String, String+Number, Number+String, String+Boolean kombinasyonları birleştirme olarak çalışır
  • handle_neg() — Sadece Number tipinde tekli negatif

Karşılaştırma

  • compare_op(f, name) — Decimal değerler üzerinde karşılaştırma, Boolean döndürür

Boolean

  • handle_and(), handle_or(), handle_not() — Boolean register'lar üzerinde mantık operasyonları

Kontrol Akışı

  • handle_jump() — 4-byte adres oku, reader pozisyonunu ayarla
  • handle_jump_if_false() — Register Boolean(false) ise atla

String, Nesne ve Metodlar

  • handle_concat() — İki register'ı birleştir (karışık tip dönüşümü destekler: String, Number, Boolean otomatik olarak String'e dönüştürülür)
  • handle_get_property() — Object register'ından alan oku, alan yoksa Null döndür. List register'ında property projection yapar: her Object elemanından ilgili alanı çıkarıp NumberList/StringList/List döndürür
  • handle_set_property() — Object register'ında alan değerini ayarla
  • handle_method_call() — Nesne register'ı, metod adı, argümanlar
    • String metodları: upper, lower, trim, trimStart, trimEnd, split(delimiter), replace(old, new), startsWith(prefix), endsWith(suffix), contains(substr), length, charAt(index), substring(start, end?)
    • StringList metodları: length/len, isEmpty, first, last, get(index), contains(value), indexOf(value), slice(start, end?), reverse(), sort(), join(delimiter?)
    • NumberList metodları: length/len, isEmpty, first, last, get(index), contains(value), indexOf(value), slice(start, end?), reverse(), sort(), sum, avg, min, max
    • Object metodları: keys(), values(), length/len(), contains(key), get(key)
    • List metodları: length/len, isEmpty, first, last, get(index), contains(value), indexOf(value), slice(start, end?), reverse(), join(delim?), map(field), filter(field, value?), find(field, value?), sort(field)
    • Harici metodlar: Yukarıdaki built-in metodlar bulunamazsa external_methods HashMap'inde aranır

Üyelik Testi

  • handle_contains()in operatörü: String in StringList, Number in NumberList, String in String (substring), String in Object (anahtar varlığı kontrolü), Value in List

Harici Fonksiyonlar ve Sonuç

  • handle_call_external() — İsimle harici fonksiyon çağır (HashMap lookup)
  • handle_set_result() — ExprStmt sonucunu last_result'a kaydet

Built-in

  • handle_log() — Register değerini stdout'a yazdır
  • rand(min, max) — min ile max arasında rastgele tamsayı üret (varsayılan harici fonksiyon)
  • abs(n) — Mutlak değer
  • min(a, b, ...) — Verilen değerlerin minimumu
  • max(a, b, ...) — Verilen değerlerin maksimumu
  • floor(n) — Aşağı yuvarlama
  • ceil(n) — Yukarı yuvarlama
  • round(n[, places]) — Yuvarlama (opsiyonel ondalık basamak sayısı)
  • sqrt(n) — Karekök
  • len(v) — Değerin uzunluğu (String, List, Object)
  • toString(v) — Değeri String'e dönüştür
  • toNumber(v) — Değeri Number'a dönüştür

Not: Built-in fonksiyon implementasyonları vm/builtins.rs dosyasında, sabit ID tanımları src/opcodes.rs içindeki default_fn modülündedir.


Yardımcı Metodlar

Metod ıklama
read_register_checked() Register oku ve doğrula
validate_register() Register indeks sınır kontrolü
read_jump_address() 4-byte adres oku ve sınır kontrolü yap
set_position(addr) Reader pozisyonunu doğrulayarak ayarla
wrap_error(err) Hataya kaynak konum bilgisi ekle
debug_print_state() Debug çıktısı (debug build)
print_profile_summary() Opcode çalışma sayıları (debug build)

Harici Fonksiyon ve Metod Kaydı

// Harici fonksiyon
vm.register_function("getRate", |args| {
    match &args[0] {
        Value::String(currency) => Ok(Value::Number(dec!(34.5))),
        _ => Err("expected string".to_string()),
    }
});

// Tipe özel harici metod
vm.register_method("Number", "format", |this, args| {
    // this: &Value, args: &[Value]
    Ok(Value::String("formatted".into()))
});

Tip isimleri: "Number", "String", "Boolean", "NumberList", "StringList", "Object", "List", "Null"


Çalışma Modeli Özeti

  • Register tabanlı: 8 register ile hesaplama
  • Global depo: SmolStr → Value map'i
  • Harici fonksiyonlar: İsimle çözümlenen host fonksiyonları (HashMap lookup)
  • Harici metodlar: Tipe özel host metodları
  • Expression return: Son ExprStmt'ın değeri execute() dönüş değeri olarak verilir
  • Dinamik tip sistemi: Tip uyuşmazlıklarında çalışma zamanı hatası