144 lines
5.7 KiB
C++
144 lines
5.7 KiB
C++
// ============================================================================
|
||
// saQut IR — Instruction (Tek Talimat)
|
||
//
|
||
// Sanal makine bu talimatlara bakarak ne yapacağını anlar.
|
||
// Her talimatın bir "opcode"u (ne iş yapacağı) ve birkaç operandı vardır.
|
||
// Operandlar ya slot numarasıdır (fonksiyonun yerel değişken/geçici depoları)
|
||
// ya da doğrudan bir sayı/isim değeridir.
|
||
//
|
||
// SLOT NEDİR?
|
||
// Her fonksiyon çağrısı kendi "frame"ini açar.
|
||
// Frame içinde numaralı kutucuklar vardır: slot[0], slot[1], ...
|
||
// Parametreler slot 0'dan başlar. Sonrasında lokal değişkenler
|
||
// ve hesaplama sırasında oluşan geçici değerler gelir.
|
||
// "slots[5] = 42" demek "5 numaralı kutucuğa 42 değerini koy" demektir.
|
||
//
|
||
// HANGİ OPCODE HANGİ ALANI KULLANIR?
|
||
// LOAD_CONST : dest, intValue
|
||
// LOAD_SLOT : dest, src
|
||
// ADD/SUB/... : dest, left, right
|
||
// LESS/LEQ/... : dest, left, right (sonuç: 1=doğru, 0=yanlış)
|
||
// JMP : jumpTarget
|
||
// JIF_FALSE : cond, jumpTarget
|
||
// CALL : dest, functionName, argSlots
|
||
// RETURN : src
|
||
// CALLHOST : functionName, argSlots
|
||
// ============================================================================
|
||
|
||
#ifndef SAQUT_IR_INSTRUCTION
|
||
#define SAQUT_IR_INSTRUCTION
|
||
|
||
#include <string>
|
||
#include <vector>
|
||
|
||
// ----------------------------------------------------------------------------
|
||
// Opcode — Sanal Makinenin Anlayacağı İşlem Kodları
|
||
// ----------------------------------------------------------------------------
|
||
enum class Opcode {
|
||
|
||
// --- Değer yükleme ---
|
||
LOAD_CONST, // slots[dest] = intValue
|
||
// Örnek: LOAD_CONST dest=3 val=10 → slot[3] = 10
|
||
|
||
LOAD_SLOT, // slots[dest] = slots[src]
|
||
// Bir slotun değerini başka bir slota kopyalar.
|
||
// Atama işlemlerinde (x = y) kullanılır.
|
||
|
||
// --- Aritmetik (tümü: slots[dest] = slots[left] OP slots[right]) ---
|
||
ADD,
|
||
SUB,
|
||
MUL,
|
||
DIV, // UYARI: sıfıra bölme → runtime_error fırlatılır
|
||
MOD,
|
||
|
||
// --- Karşılaştırma (sonuç: 1 = doğru, 0 = yanlış) ---
|
||
LESS, // slots[left] < slots[right]
|
||
LESS_EQUAL, // slots[left] <= slots[right]
|
||
GREATER, // slots[left] > slots[right]
|
||
GREATER_EQUAL, // slots[left] >= slots[right]
|
||
EQUAL_EQUAL, // slots[left] == slots[right]
|
||
NOT_EQUAL, // slots[left] != slots[right]
|
||
|
||
// --- Kontrol akışı ---
|
||
JMP, // Koşulsuz atlama: ip = jumpTarget
|
||
JIF_FALSE, // Koşullu atlama: slots[cond] == 0 ise ip = jumpTarget
|
||
|
||
// --- Fonksiyon çağrısı ---
|
||
CALL, // Başka bir saQut fonksiyonunu çağır.
|
||
// Yeni frame açılır, argümanlar parametre slotlarına kopyalanır.
|
||
// Fonksiyon RETURN ile bitince sonuç slots[dest]'e yazılır.
|
||
|
||
RETURN, // Bu frame'i kapat, slots[src]'yi caller'a ilet.
|
||
|
||
// --- Dış dünya (FFI — Foreign Function Interface) ---
|
||
CALLHOST, // Host (C++) fonksiyonunu çağır. Şu an sadece "print" destekli.
|
||
// Dönüş değeri yok; sadece yan etki (stdout'a yazmak gibi).
|
||
};
|
||
|
||
// Hata ayıklama ve IR dump için okunabilir isim
|
||
inline const char* opcodeName(Opcode op) {
|
||
switch (op) {
|
||
case Opcode::LOAD_CONST: return "LOAD_CONST";
|
||
case Opcode::LOAD_SLOT: return "LOAD_SLOT";
|
||
case Opcode::ADD: return "ADD";
|
||
case Opcode::SUB: return "SUB";
|
||
case Opcode::MUL: return "MUL";
|
||
case Opcode::DIV: return "DIV";
|
||
case Opcode::MOD: return "MOD";
|
||
case Opcode::LESS: return "LESS";
|
||
case Opcode::LESS_EQUAL: return "LESS_EQUAL";
|
||
case Opcode::GREATER: return "GREATER";
|
||
case Opcode::GREATER_EQUAL: return "GREATER_EQUAL";
|
||
case Opcode::EQUAL_EQUAL: return "EQUAL_EQUAL";
|
||
case Opcode::NOT_EQUAL: return "NOT_EQUAL";
|
||
case Opcode::JMP: return "JMP";
|
||
case Opcode::JIF_FALSE: return "JIF_FALSE";
|
||
case Opcode::CALL: return "CALL";
|
||
case Opcode::RETURN: return "RETURN";
|
||
case Opcode::CALLHOST: return "CALLHOST";
|
||
}
|
||
return "UNKNOWN";
|
||
}
|
||
|
||
// ----------------------------------------------------------------------------
|
||
// Instruction — Tek bir IR talimatı
|
||
//
|
||
// Okunabilirlik öncelikli bir tasarım: her talimat TÜM alanları içerir,
|
||
// kullanılmayanlar varsayılan değerde (-1 veya boş) kalır.
|
||
// Bu yaklaşım bellek israfeder ama her talimatın hangi veriyle çalıştığı
|
||
// açıkça görünür — karmaşık union/variant yapısı gerekmez.
|
||
// ----------------------------------------------------------------------------
|
||
struct Instruction {
|
||
Opcode opcode;
|
||
|
||
// Hedef slot — sonucun yazılacağı yer (LOAD_CONST, ADD, CALL vb.)
|
||
int dest = -1;
|
||
|
||
// Kaynak slot — kopyalama veya döndürme için (LOAD_SLOT, RETURN)
|
||
int src = -1;
|
||
|
||
// Aritmetik/karşılaştırma operandları
|
||
int left = -1;
|
||
int right = -1;
|
||
|
||
// LOAD_CONST için yüklenecek sabit değer
|
||
int intValue = 0;
|
||
|
||
// JMP / JIF_FALSE için hedef instruction indeksi
|
||
// Üretim sırasında bilinmiyorsa -1 bırakılır, sonradan doldurulur (backpatch).
|
||
int jumpTarget = -1;
|
||
|
||
// JIF_FALSE için kontrol edilecek koşul slotu
|
||
int cond = -1;
|
||
|
||
// CALL / CALLHOST için çağrılacak fonksiyonun adı
|
||
std::string functionName;
|
||
|
||
// CALL / CALLHOST için argüman slot indeksleri (sırayla)
|
||
std::vector<int> argSlots;
|
||
|
||
explicit Instruction(Opcode op) : opcode(op) {}
|
||
};
|
||
|
||
#endif // SAQUT_IR_INSTRUCTION
|