#45 — BAND, BOR, SHL, SHR (binary) ve BNOT (unary ~) opcode'ları eklendi. Bileşik atama &=, |=, <<=, >>= destekleniyor. Sabit katlama güncellendi. ^ (XOR) CARET çakışması nedeniyle atlandı. #38 — LOAD_GLOBAL / STORE_GLOBAL opcode'ları eklendi (Seçenek A: gerçek global slot). IRProgram.globalCount + globalNames; Interpreter.globalSlots_. Global init ifadeleri main'in başında üretiliyor. Tüm fonksiyonlar global alana erişebilir. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2d641863d8
commit
808efc5b4a
|
|
@ -55,6 +55,13 @@ enum class Opcode {
|
||||||
DIV, // UYARI: sıfıra bölme → runtime_error fırlatılır
|
DIV, // UYARI: sıfıra bölme → runtime_error fırlatılır
|
||||||
MOD,
|
MOD,
|
||||||
|
|
||||||
|
// --- Bitsel (tümü: slots[dest] = slots[left] OP slots[right]) ---
|
||||||
|
BAND, // slots[left] & slots[right]
|
||||||
|
BOR, // slots[left] | slots[right]
|
||||||
|
SHL, // slots[left] << slots[right]
|
||||||
|
SHR, // slots[left] >> slots[right]
|
||||||
|
BNOT, // ~slots[src] → slots[dest] (tekli operatör; src kullanır, left/right değil)
|
||||||
|
|
||||||
// --- Karşılaştırma (sonuç: 1 = doğru, 0 = yanlış) ---
|
// --- Karşılaştırma (sonuç: 1 = doğru, 0 = yanlış) ---
|
||||||
LESS, // slots[left] < slots[right]
|
LESS, // slots[left] < slots[right]
|
||||||
LESS_EQUAL, // slots[left] <= slots[right]
|
LESS_EQUAL, // slots[left] <= slots[right]
|
||||||
|
|
@ -75,6 +82,10 @@ enum class Opcode {
|
||||||
|
|
||||||
RETURN, // Bu frame'i kapat, slots[src]'yi caller'a ilet.
|
RETURN, // Bu frame'i kapat, slots[src]'yi caller'a ilet.
|
||||||
|
|
||||||
|
// --- Global değişken erişimi ---
|
||||||
|
LOAD_GLOBAL, // slots[dest] = globalSlots[intValue]
|
||||||
|
STORE_GLOBAL, // globalSlots[intValue] = slots[src]
|
||||||
|
|
||||||
// --- Dış dünya (FFI — Foreign Function Interface) ---
|
// --- Dış dünya (FFI — Foreign Function Interface) ---
|
||||||
CALLHOST, // Host (C++) fonksiyonunu çağır. Şu an sadece "print" destekli.
|
CALLHOST, // Host (C++) fonksiyonunu çağır. Şu an sadece "print" destekli.
|
||||||
// Dönüş değeri yok; sadece yan etki (stdout'a yazmak gibi).
|
// Dönüş değeri yok; sadece yan etki (stdout'a yazmak gibi).
|
||||||
|
|
@ -91,6 +102,13 @@ inline const char* opcodeName(Opcode op) {
|
||||||
case Opcode::MUL: return "MUL";
|
case Opcode::MUL: return "MUL";
|
||||||
case Opcode::DIV: return "DIV";
|
case Opcode::DIV: return "DIV";
|
||||||
case Opcode::MOD: return "MOD";
|
case Opcode::MOD: return "MOD";
|
||||||
|
case Opcode::BAND: return "BAND";
|
||||||
|
case Opcode::BOR: return "BOR";
|
||||||
|
case Opcode::SHL: return "SHL";
|
||||||
|
case Opcode::SHR: return "SHR";
|
||||||
|
case Opcode::BNOT: return "BNOT";
|
||||||
|
case Opcode::LOAD_GLOBAL: return "LOAD_GLOBAL";
|
||||||
|
case Opcode::STORE_GLOBAL: return "STORE_GLOBAL";
|
||||||
case Opcode::LESS: return "LESS";
|
case Opcode::LESS: return "LESS";
|
||||||
case Opcode::LESS_EQUAL: return "LESS_EQUAL";
|
case Opcode::LESS_EQUAL: return "LESS_EQUAL";
|
||||||
case Opcode::GREATER: return "GREATER";
|
case Opcode::GREATER: return "GREATER";
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,10 @@ static const char* opSymbol(Opcode op) {
|
||||||
case Opcode::MUL: return "*";
|
case Opcode::MUL: return "*";
|
||||||
case Opcode::DIV: return "/";
|
case Opcode::DIV: return "/";
|
||||||
case Opcode::MOD: return "%";
|
case Opcode::MOD: return "%";
|
||||||
|
case Opcode::BAND: return "&";
|
||||||
|
case Opcode::BOR: return "|";
|
||||||
|
case Opcode::SHL: return "<<";
|
||||||
|
case Opcode::SHR: return ">>";
|
||||||
case Opcode::LESS: return "<";
|
case Opcode::LESS: return "<";
|
||||||
case Opcode::LESS_EQUAL: return "<=";
|
case Opcode::LESS_EQUAL: return "<=";
|
||||||
case Opcode::GREATER: return ">";
|
case Opcode::GREATER: return ">";
|
||||||
|
|
@ -35,6 +39,7 @@ static bool isBinaryOp(Opcode op) {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Opcode::ADD: case Opcode::SUB: case Opcode::MUL:
|
case Opcode::ADD: case Opcode::SUB: case Opcode::MUL:
|
||||||
case Opcode::DIV: case Opcode::MOD:
|
case Opcode::DIV: case Opcode::MOD:
|
||||||
|
case Opcode::BAND: case Opcode::BOR: case Opcode::SHL: case Opcode::SHR:
|
||||||
case Opcode::LESS: case Opcode::LESS_EQUAL:
|
case Opcode::LESS: case Opcode::LESS_EQUAL:
|
||||||
case Opcode::GREATER: case Opcode::GREATER_EQUAL:
|
case Opcode::GREATER: case Opcode::GREATER_EQUAL:
|
||||||
case Opcode::EQUAL_EQUAL: case Opcode::NOT_EQUAL:
|
case Opcode::EQUAL_EQUAL: case Opcode::NOT_EQUAL:
|
||||||
|
|
@ -113,6 +118,15 @@ void IRFunction::dump() const {
|
||||||
}
|
}
|
||||||
std::cout << ")";
|
std::cout << ")";
|
||||||
|
|
||||||
|
} else if (ins.opcode == Opcode::BNOT) {
|
||||||
|
std::cout << slot(ins.dest) << " = ~" << slot(ins.src);
|
||||||
|
|
||||||
|
} else if (ins.opcode == Opcode::LOAD_GLOBAL) {
|
||||||
|
std::cout << slot(ins.dest) << " = global[" << ins.intValue << "]";
|
||||||
|
|
||||||
|
} else if (ins.opcode == Opcode::STORE_GLOBAL) {
|
||||||
|
std::cout << "global[" << ins.intValue << "] = " << slot(ins.src);
|
||||||
|
|
||||||
} else if (ins.opcode == Opcode::RETURN) {
|
} else if (ins.opcode == Opcode::RETURN) {
|
||||||
std::cout << slot(ins.src);
|
std::cout << slot(ins.src);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,25 +17,40 @@
|
||||||
IRProgram IRGenerator::generate(ASTNode* programNode, SymbolTable& /*symbolTable*/) {
|
IRProgram IRGenerator::generate(ASTNode* programNode, SymbolTable& /*symbolTable*/) {
|
||||||
IRProgram program;
|
IRProgram program;
|
||||||
|
|
||||||
// ProgramNode'un her çocuğunu gez.
|
// 1. Geçiş: global VariableDecl'leri topla ve kayıt et
|
||||||
// Bizi ilgilendiren: FunctionDecl. StructDecl/GlobalVar → TODO.
|
std::vector<VariableDeclNode*> globalVars;
|
||||||
|
for (ASTNode* child : programNode->getChildren()) {
|
||||||
|
if (child->kind == ASTKind::VariableDecl) {
|
||||||
|
auto* vd = (VariableDeclNode*)child;
|
||||||
|
nameToGlobal_[vd->name] = globalCount_++;
|
||||||
|
program.globalCount++;
|
||||||
|
program.globalNames.push_back(vd->name);
|
||||||
|
globalVars.push_back(vd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Geçiş: fonksiyonları üret
|
||||||
for (ASTNode* child : programNode->getChildren()) {
|
for (ASTNode* child : programNode->getChildren()) {
|
||||||
if (child->kind == ASTKind::FunctionDecl) {
|
if (child->kind == ASTKind::FunctionDecl) {
|
||||||
// Her fonksiyon üretimi için sıfırla
|
|
||||||
nameToSlot_.clear();
|
nameToSlot_.clear();
|
||||||
nextSlot_ = 0;
|
nextSlot_ = 0;
|
||||||
|
|
||||||
// IRFunction oluştur, currentFunction_ olarak işaretle
|
|
||||||
auto* fnDecl = (FunctionDeclNode*)child;
|
auto* fnDecl = (FunctionDeclNode*)child;
|
||||||
IRFunction irFn(fnDecl->name, (int)fnDecl->params.size());
|
IRFunction irFn(fnDecl->name, (int)fnDecl->params.size());
|
||||||
program.addFunction(std::move(irFn));
|
program.addFunction(std::move(irFn));
|
||||||
|
|
||||||
// addFunction std::move yaptığı için pointer'ı haritadan alalım
|
|
||||||
currentFunction_ = program.findFunction(fnDecl->name);
|
currentFunction_ = program.findFunction(fnDecl->name);
|
||||||
|
|
||||||
generateFunction(child);
|
// main'in başında global değişkenlerin init ifadelerini üret
|
||||||
|
if (fnDecl->name == "main") {
|
||||||
|
for (VariableDeclNode* gv : globalVars) {
|
||||||
|
if (gv->initExpr) {
|
||||||
|
int initSlot = generateExpression(gv->initExpr);
|
||||||
|
emitStoreGlobal(initSlot, nameToGlobal_[gv->name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fonksiyon bitti — toplam slot sayısını kaydet
|
generateFunction(child);
|
||||||
currentFunction_->slotCount = nextSlot_;
|
currentFunction_->slotCount = nextSlot_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -344,13 +359,15 @@ int IRGenerator::generateExpression(ASTNode* node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Değişken ismi: n, first, second ... ──────────────────────────────
|
// ── Değişken ismi: n, first, second ... ──────────────────────────────
|
||||||
// Bu değişkenin değeri zaten bir slotta. O slotu döndür.
|
|
||||||
case ASTKind::Identifier: {
|
case ASTKind::Identifier: {
|
||||||
auto* id = (IdentifierNode*)node;
|
auto* id = (IdentifierNode*)node;
|
||||||
std::string name = id->parserToken.token ? id->parserToken.token->token : "";
|
std::string name = id->parserToken.token ? id->parserToken.token->token : "";
|
||||||
|
|
||||||
// Önce builtin mi? (print gibi) — identifier olarak gelen builtin fonksiyon
|
if (isGlobal(name)) {
|
||||||
// çağrıları CallExpression içinde yakalanıyor, burada sadece değişken kalır
|
int tempSlot = freshSlot();
|
||||||
|
emitLoadGlobal(tempSlot, getGlobalIndex(name));
|
||||||
|
return tempSlot;
|
||||||
|
}
|
||||||
return lookupVariable(name);
|
return lookupVariable(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -358,44 +375,59 @@ int IRGenerator::generateExpression(ASTNode* node) {
|
||||||
case ASTKind::BinaryExpression: {
|
case ASTKind::BinaryExpression: {
|
||||||
auto* bin = (BinaryExpressionNode*)node;
|
auto* bin = (BinaryExpressionNode*)node;
|
||||||
|
|
||||||
// Atama operatörleri: x = expr, x += expr ...
|
// Atama operatörleri: x = expr
|
||||||
// Sol taraf bir değişken, sağ taraf hesaplanır ve o değişkene yazılır.
|
|
||||||
if (bin->Operator == TokenType::EQUAL) {
|
if (bin->Operator == TokenType::EQUAL) {
|
||||||
// Sağ tarafı hesapla
|
|
||||||
int rhsSlot = generateExpression(bin->Right);
|
int rhsSlot = generateExpression(bin->Right);
|
||||||
|
|
||||||
// Sol taraf değişkenin slotunu bul
|
|
||||||
auto* lhsId = (IdentifierNode*)bin->Left;
|
auto* lhsId = (IdentifierNode*)bin->Left;
|
||||||
std::string varName = lhsId->parserToken.token->token;
|
std::string varName = lhsId->parserToken.token->token;
|
||||||
int varSlot = lookupVariable(varName);
|
|
||||||
|
|
||||||
// Sonucu değişkenin slotuna kopyala
|
if (isGlobal(varName)) {
|
||||||
if (rhsSlot != varSlot) {
|
emitStoreGlobal(rhsSlot, getGlobalIndex(varName));
|
||||||
emitLoadSlot(varSlot, rhsSlot);
|
return rhsSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int varSlot = lookupVariable(varName);
|
||||||
|
if (rhsSlot != varSlot) emitLoadSlot(varSlot, rhsSlot);
|
||||||
return varSlot;
|
return varSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Birleşik atama: += -= *= /= %=
|
// Birleşik atama: += -= *= /= %= &= |= <<= >>=
|
||||||
// x OP= y ≡ x = x OP y
|
// x OP= y ≡ x = x OP y
|
||||||
if (bin->Operator == TokenType::PLUS_EQUAL ||
|
if (bin->Operator == TokenType::PLUS_EQUAL ||
|
||||||
bin->Operator == TokenType::MINUS_EQUAL ||
|
bin->Operator == TokenType::MINUS_EQUAL ||
|
||||||
bin->Operator == TokenType::STAR_EQUAL ||
|
bin->Operator == TokenType::STAR_EQUAL ||
|
||||||
bin->Operator == TokenType::SLASH_EQUAL ||
|
bin->Operator == TokenType::SLASH_EQUAL ||
|
||||||
bin->Operator == TokenType::PERCENT_EQUAL) {
|
bin->Operator == TokenType::PERCENT_EQUAL ||
|
||||||
|
bin->Operator == TokenType::AMPERSAND_EQUAL ||
|
||||||
|
bin->Operator == TokenType::PIPE_EQUAL ||
|
||||||
|
bin->Operator == TokenType::LSHIFT_EQUAL ||
|
||||||
|
bin->Operator == TokenType::RSHIFT_EQUAL) {
|
||||||
|
|
||||||
auto* lhsId = (IdentifierNode*)bin->Left;
|
auto* lhsId = (IdentifierNode*)bin->Left;
|
||||||
std::string varName = lhsId->parserToken.token->token;
|
std::string varName = lhsId->parserToken.token->token;
|
||||||
int varSlot = lookupVariable(varName);
|
|
||||||
int rhsSlot = generateExpression(bin->Right);
|
int rhsSlot = generateExpression(bin->Right);
|
||||||
|
|
||||||
Opcode arithOp = Opcode::ADD;
|
Opcode arithOp = Opcode::ADD;
|
||||||
if (bin->Operator == TokenType::MINUS_EQUAL) arithOp = Opcode::SUB;
|
if (bin->Operator == TokenType::MINUS_EQUAL) arithOp = Opcode::SUB;
|
||||||
else if (bin->Operator == TokenType::STAR_EQUAL) arithOp = Opcode::MUL;
|
else if (bin->Operator == TokenType::STAR_EQUAL) arithOp = Opcode::MUL;
|
||||||
else if (bin->Operator == TokenType::SLASH_EQUAL) arithOp = Opcode::DIV;
|
else if (bin->Operator == TokenType::SLASH_EQUAL) arithOp = Opcode::DIV;
|
||||||
else if (bin->Operator == TokenType::PERCENT_EQUAL) arithOp = Opcode::MOD;
|
else if (bin->Operator == TokenType::PERCENT_EQUAL) arithOp = Opcode::MOD;
|
||||||
|
else if (bin->Operator == TokenType::AMPERSAND_EQUAL) arithOp = Opcode::BAND;
|
||||||
|
else if (bin->Operator == TokenType::PIPE_EQUAL) arithOp = Opcode::BOR;
|
||||||
|
else if (bin->Operator == TokenType::LSHIFT_EQUAL) arithOp = Opcode::SHL;
|
||||||
|
else if (bin->Operator == TokenType::RSHIFT_EQUAL) arithOp = Opcode::SHR;
|
||||||
|
|
||||||
int resultSlot = freshSlot();
|
int resultSlot = freshSlot();
|
||||||
|
|
||||||
|
if (isGlobal(varName)) {
|
||||||
|
int currentSlot = freshSlot();
|
||||||
|
emitLoadGlobal(currentSlot, getGlobalIndex(varName));
|
||||||
|
emitBinaryOp(arithOp, resultSlot, currentSlot, rhsSlot);
|
||||||
|
emitStoreGlobal(resultSlot, getGlobalIndex(varName));
|
||||||
|
return resultSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
int varSlot = lookupVariable(varName);
|
||||||
emitBinaryOp(arithOp, resultSlot, varSlot, rhsSlot);
|
emitBinaryOp(arithOp, resultSlot, varSlot, rhsSlot);
|
||||||
emitLoadSlot(varSlot, resultSlot);
|
emitLoadSlot(varSlot, resultSlot);
|
||||||
return varSlot;
|
return varSlot;
|
||||||
|
|
@ -412,12 +444,17 @@ int IRGenerator::generateExpression(ASTNode* node) {
|
||||||
emitLoadConst(zeroSlot, 0);
|
emitLoadConst(zeroSlot, 0);
|
||||||
emitBinaryOp(Opcode::SUB, resultSlot, zeroSlot, operandSlot);
|
emitBinaryOp(Opcode::SUB, resultSlot, zeroSlot, operandSlot);
|
||||||
} else if (bin->Operator == TokenType::BANG) {
|
} else if (bin->Operator == TokenType::BANG) {
|
||||||
// !x → (x == 0): sıfırsa 1, değilse 0 — her zaman 0 ya da 1
|
// !x → (x == 0): sıfırsa 1, değilse 0
|
||||||
int zeroSlot = freshSlot();
|
int zeroSlot = freshSlot();
|
||||||
emitLoadConst(zeroSlot, 0);
|
emitLoadConst(zeroSlot, 0);
|
||||||
emitBinaryOp(Opcode::EQUAL_EQUAL, resultSlot, operandSlot, zeroSlot);
|
emitBinaryOp(Opcode::EQUAL_EQUAL, resultSlot, operandSlot, zeroSlot);
|
||||||
|
} else if (bin->Operator == TokenType::TILDE) {
|
||||||
|
// ~x — bitsel değil
|
||||||
|
Instruction ins(Opcode::BNOT);
|
||||||
|
ins.dest = resultSlot;
|
||||||
|
ins.src = operandSlot;
|
||||||
|
currentFunction_->instructions.push_back(std::move(ins));
|
||||||
} else {
|
} else {
|
||||||
// Diğer unary operatörler (ör. ~) → TODO
|
|
||||||
emitLoadSlot(resultSlot, operandSlot);
|
emitLoadSlot(resultSlot, operandSlot);
|
||||||
}
|
}
|
||||||
return resultSlot;
|
return resultSlot;
|
||||||
|
|
@ -438,6 +475,12 @@ int IRGenerator::generateExpression(ASTNode* node) {
|
||||||
case TokenType::EQUAL_EQUAL: return generateBinaryArithmetic(Opcode::EQUAL_EQUAL, bin->Left, bin->Right);
|
case TokenType::EQUAL_EQUAL: return generateBinaryArithmetic(Opcode::EQUAL_EQUAL, bin->Left, bin->Right);
|
||||||
case TokenType::BANG_EQUAL: return generateBinaryArithmetic(Opcode::NOT_EQUAL, bin->Left, bin->Right);
|
case TokenType::BANG_EQUAL: return generateBinaryArithmetic(Opcode::NOT_EQUAL, bin->Left, bin->Right);
|
||||||
|
|
||||||
|
// Bitsel operatörler
|
||||||
|
case TokenType::AMPERSAND: return generateBinaryArithmetic(Opcode::BAND, bin->Left, bin->Right);
|
||||||
|
case TokenType::PIPE: return generateBinaryArithmetic(Opcode::BOR, bin->Left, bin->Right);
|
||||||
|
case TokenType::LSHIFT: return generateBinaryArithmetic(Opcode::SHL, bin->Left, bin->Right);
|
||||||
|
case TokenType::RSHIFT: return generateBinaryArithmetic(Opcode::SHR, bin->Left, bin->Right);
|
||||||
|
|
||||||
// Mantıksal operatörler: kısa devre dallanmasıyla üretilir (ADR-008).
|
// Mantıksal operatörler: kısa devre dallanmasıyla üretilir (ADR-008).
|
||||||
// NOT: sıradan ikili işlem değil — b, a'nın değerine göre atlanabilir.
|
// NOT: sıradan ikili işlem değil — b, a'nın değerine göre atlanabilir.
|
||||||
case TokenType::AMPERSAND_AMPERSAND: {
|
case TokenType::AMPERSAND_AMPERSAND: {
|
||||||
|
|
@ -593,6 +636,29 @@ void IRGenerator::emitLoadSlot(int destSlot, int srcSlot) {
|
||||||
currentFunction_->instructions.push_back(std::move(ins));
|
currentFunction_->instructions.push_back(std::move(ins));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IRGenerator::emitLoadGlobal(int destSlot, int globalIndex) {
|
||||||
|
Instruction ins(Opcode::LOAD_GLOBAL);
|
||||||
|
ins.dest = destSlot;
|
||||||
|
ins.intValue = globalIndex;
|
||||||
|
currentFunction_->instructions.push_back(std::move(ins));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRGenerator::emitStoreGlobal(int srcSlot, int globalIndex) {
|
||||||
|
Instruction ins(Opcode::STORE_GLOBAL);
|
||||||
|
ins.src = srcSlot;
|
||||||
|
ins.intValue = globalIndex;
|
||||||
|
currentFunction_->instructions.push_back(std::move(ins));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRGenerator::isGlobal(const std::string& name) const {
|
||||||
|
return nameToGlobal_.count(name) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int IRGenerator::getGlobalIndex(const std::string& name) const {
|
||||||
|
auto it = nameToGlobal_.find(name);
|
||||||
|
return (it != nameToGlobal_.end()) ? it->second : -1;
|
||||||
|
}
|
||||||
|
|
||||||
void IRGenerator::emitBinaryOp(Opcode op, int destSlot, int leftSlot, int rightSlot) {
|
void IRGenerator::emitBinaryOp(Opcode op, int destSlot, int leftSlot, int rightSlot) {
|
||||||
Instruction ins(op);
|
Instruction ins(op);
|
||||||
ins.dest = destSlot;
|
ins.dest = destSlot;
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,8 @@ private:
|
||||||
|
|
||||||
void emitLoadConst(int destSlot, int value);
|
void emitLoadConst(int destSlot, int value);
|
||||||
void emitLoadSlot(int destSlot, int srcSlot);
|
void emitLoadSlot(int destSlot, int srcSlot);
|
||||||
|
void emitLoadGlobal(int destSlot, int globalIndex);
|
||||||
|
void emitStoreGlobal(int srcSlot, int globalIndex);
|
||||||
void emitBinaryOp(Opcode op, int destSlot, int leftSlot, int rightSlot);
|
void emitBinaryOp(Opcode op, int destSlot, int leftSlot, int rightSlot);
|
||||||
void emitReturn(int srcSlot);
|
void emitReturn(int srcSlot);
|
||||||
// Koşulsuz atlama yazar; instruction indeksini döndürür (backpatch için).
|
// Koşulsuz atlama yazar; instruction indeksini döndürür (backpatch için).
|
||||||
|
|
@ -88,9 +90,15 @@ private:
|
||||||
IRFunction* currentFunction_ = nullptr; // şu an üretilen fonksiyon
|
IRFunction* currentFunction_ = nullptr; // şu an üretilen fonksiyon
|
||||||
int nextSlot_ = 0; // sıradaki boş slot numarası
|
int nextSlot_ = 0; // sıradaki boş slot numarası
|
||||||
|
|
||||||
// Değişken ismi → slot numarası.
|
// Değişken ismi → slot numarası (lokal).
|
||||||
// Sınırlama: aynı isimdeki farklı scope değişkenleri çakışır (TODO).
|
|
||||||
std::unordered_map<std::string, int> nameToSlot_;
|
std::unordered_map<std::string, int> nameToSlot_;
|
||||||
|
|
||||||
|
// Global değişken ismi → global index
|
||||||
|
std::unordered_map<std::string, int> nameToGlobal_;
|
||||||
|
int globalCount_ = 0;
|
||||||
|
|
||||||
|
bool isGlobal(const std::string& name) const;
|
||||||
|
int getGlobalIndex(const std::string& name) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SAQUT_IR_GENERATOR
|
#endif // SAQUT_IR_GENERATOR
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,14 @@
|
||||||
|
|
||||||
void IRProgram::dump() const {
|
void IRProgram::dump() const {
|
||||||
std::cout << "IR DUMP\n\n";
|
std::cout << "IR DUMP\n\n";
|
||||||
|
|
||||||
|
if (globalCount > 0) {
|
||||||
|
std::cout << "GLOBALS (" << globalCount << ")\n";
|
||||||
|
for (int i = 0; i < (int)globalNames.size(); i++)
|
||||||
|
std::cout << " global[" << i << "] = " << globalNames[i] << "\n";
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& name : functionOrder) {
|
for (const auto& name : functionOrder) {
|
||||||
auto it = functions.find(name);
|
auto it = functions.find(name);
|
||||||
if (it != functions.end()) it->second.dump();
|
if (it != functions.end()) it->second.dump();
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,10 @@ struct IRProgram {
|
||||||
// Ekleme sırası (dump'ta orijinal sırayla göstermek için)
|
// Ekleme sırası (dump'ta orijinal sırayla göstermek için)
|
||||||
std::vector<std::string> functionOrder;
|
std::vector<std::string> functionOrder;
|
||||||
|
|
||||||
|
// Global değişkenler (LOAD_GLOBAL / STORE_GLOBAL için)
|
||||||
|
int globalCount = 0;
|
||||||
|
std::vector<std::string> globalNames; // index → isim (dump için)
|
||||||
|
|
||||||
// Yeni fonksiyon ekle
|
// Yeni fonksiyon ekle
|
||||||
void addFunction(IRFunction fn) {
|
void addFunction(IRFunction fn) {
|
||||||
functionOrder.push_back(fn.name);
|
functionOrder.push_back(fn.name);
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,10 @@ private:
|
||||||
case TokenType::GREATER:
|
case TokenType::GREATER:
|
||||||
case TokenType::LESS_EQUAL:
|
case TokenType::LESS_EQUAL:
|
||||||
case TokenType::GREATER_EQUAL:
|
case TokenType::GREATER_EQUAL:
|
||||||
|
case TokenType::AMPERSAND:
|
||||||
|
case TokenType::PIPE:
|
||||||
|
case TokenType::LSHIFT:
|
||||||
|
case TokenType::RSHIFT:
|
||||||
case TokenType::AMPERSAND_AMPERSAND:
|
case TokenType::AMPERSAND_AMPERSAND:
|
||||||
case TokenType::PIPE_PIPE:
|
case TokenType::PIPE_PIPE:
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -125,6 +129,10 @@ private:
|
||||||
case TokenType::GREATER: return l > r ? 1 : 0;
|
case TokenType::GREATER: return l > r ? 1 : 0;
|
||||||
case TokenType::LESS_EQUAL: return l <= r ? 1 : 0;
|
case TokenType::LESS_EQUAL: return l <= r ? 1 : 0;
|
||||||
case TokenType::GREATER_EQUAL: return l >= r ? 1 : 0;
|
case TokenType::GREATER_EQUAL: return l >= r ? 1 : 0;
|
||||||
|
case TokenType::AMPERSAND: return l & r;
|
||||||
|
case TokenType::PIPE: return l | r;
|
||||||
|
case TokenType::LSHIFT: return l << r;
|
||||||
|
case TokenType::RSHIFT: return l >> r;
|
||||||
case TokenType::AMPERSAND_AMPERSAND: return (l && r) ? 1 : 0;
|
case TokenType::AMPERSAND_AMPERSAND: return (l && r) ? 1 : 0;
|
||||||
case TokenType::PIPE_PIPE: return (l || r) ? 1 : 0;
|
case TokenType::PIPE_PIPE: return (l || r) ? 1 : 0;
|
||||||
default: return 0;
|
default: return 0;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
int Interpreter::run() {
|
int Interpreter::run() {
|
||||||
|
// Global slot'ları sıfırla
|
||||||
|
globalSlots_.assign(program_.globalCount, Value::fromInt(0));
|
||||||
|
|
||||||
IRFunction* mainFunction = program_.findFunction("main");
|
IRFunction* mainFunction = program_.findFunction("main");
|
||||||
if (!mainFunction)
|
if (!mainFunction)
|
||||||
throw std::runtime_error("Çalışma hatası: 'main' fonksiyonu bulunamadı");
|
throw std::runtime_error("Çalışma hatası: 'main' fonksiyonu bulunamadı");
|
||||||
|
|
@ -70,6 +73,35 @@ int Interpreter::run() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Bitsel ────────────────────────────────────────────────────────
|
||||||
|
case Opcode::BAND:
|
||||||
|
frame.slots[instr.dest] = Value::fromInt(
|
||||||
|
frame.slots[instr.left].intValue & frame.slots[instr.right].intValue);
|
||||||
|
break;
|
||||||
|
case Opcode::BOR:
|
||||||
|
frame.slots[instr.dest] = Value::fromInt(
|
||||||
|
frame.slots[instr.left].intValue | frame.slots[instr.right].intValue);
|
||||||
|
break;
|
||||||
|
case Opcode::SHL:
|
||||||
|
frame.slots[instr.dest] = Value::fromInt(
|
||||||
|
frame.slots[instr.left].intValue << frame.slots[instr.right].intValue);
|
||||||
|
break;
|
||||||
|
case Opcode::SHR:
|
||||||
|
frame.slots[instr.dest] = Value::fromInt(
|
||||||
|
frame.slots[instr.left].intValue >> frame.slots[instr.right].intValue);
|
||||||
|
break;
|
||||||
|
case Opcode::BNOT:
|
||||||
|
frame.slots[instr.dest] = Value::fromInt(~frame.slots[instr.src].intValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// ── Global değişken erişimi ────────────────────────────────────────
|
||||||
|
case Opcode::LOAD_GLOBAL:
|
||||||
|
frame.slots[instr.dest] = globalSlots_[instr.intValue];
|
||||||
|
break;
|
||||||
|
case Opcode::STORE_GLOBAL:
|
||||||
|
globalSlots_[instr.intValue] = frame.slots[instr.src];
|
||||||
|
break;
|
||||||
|
|
||||||
// ── Karşılaştırma ─────────────────────────────────────────────────
|
// ── Karşılaştırma ─────────────────────────────────────────────────
|
||||||
case Opcode::LESS:
|
case Opcode::LESS:
|
||||||
frame.slots[instr.dest] = Value::fromInt(
|
frame.slots[instr.dest] = Value::fromInt(
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ public:
|
||||||
private:
|
private:
|
||||||
IRProgram& program_;
|
IRProgram& program_;
|
||||||
std::vector<CallFrame> callStack_;
|
std::vector<CallFrame> callStack_;
|
||||||
|
std::vector<Value> globalSlots_;
|
||||||
|
|
||||||
// Host (C++) fonksiyon çağrısı — şu an sadece "print" destekli
|
// Host (C++) fonksiyon çağrısı — şu an sadece "print" destekli
|
||||||
void executeHostFunction(const std::string& name,
|
void executeHostFunction(const std::string& name,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue