- #38: Üst düzey VariableDecl'lar main'in başına inject ediliyor (Seçenek B) - #45: BIT_AND / BIT_OR / BIT_SHL / BIT_SHR / BIT_NOT / NOT_UNARY opcode'ları - IR üretici: AMPERSAND, PIPE, LSHIFT, RSHIFT → binary bitsel - IR üretici: TILDE (unary ~) → BIT_NOT, BANG (unary !) → NOT_UNARY - VM: tüm yeni opcode'lar için handler eklendi Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d51e48dbb2
commit
04465afaef
|
|
@ -0,0 +1,25 @@
|
|||
int global_x = 10;
|
||||
int global_y = 3;
|
||||
|
||||
int main() {
|
||||
// global değişken testi (#38)
|
||||
print(global_x);
|
||||
print(global_y);
|
||||
|
||||
// bitsel AND, OR, SHL, SHR (#45)
|
||||
int a = 12;
|
||||
int b = 10;
|
||||
print(a & b);
|
||||
print(a | b);
|
||||
print(1 << 3);
|
||||
print(16 >> 2);
|
||||
|
||||
// unary ~ ve !
|
||||
int c = 0;
|
||||
print(!c);
|
||||
int d = 5;
|
||||
print(!d);
|
||||
print(~0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -73,6 +73,14 @@ enum class Opcode {
|
|||
|
||||
RETURN, // Bu frame'i kapat, slots[src]'yi caller'a ilet.
|
||||
|
||||
// --- Bitsel (tümü: slots[dest] = slots[left] OP slots[right]) ---
|
||||
BIT_AND, // a & b
|
||||
BIT_OR, // a | b
|
||||
BIT_SHL, // a << b
|
||||
BIT_SHR, // a >> b
|
||||
BIT_NOT, // ~a (unary: slots[dest] = ~slots[src])
|
||||
NOT_UNARY, // !a (unary: slots[dest] = slots[src] == 0 ? 1 : 0)
|
||||
|
||||
// --- 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).
|
||||
|
|
@ -99,6 +107,12 @@ inline const char* opcodeName(Opcode op) {
|
|||
case Opcode::JIF_FALSE: return "JIF_FALSE";
|
||||
case Opcode::CALL: return "CALL";
|
||||
case Opcode::RETURN: return "RETURN";
|
||||
case Opcode::BIT_AND: return "BIT_AND";
|
||||
case Opcode::BIT_OR: return "BIT_OR";
|
||||
case Opcode::BIT_SHL: return "BIT_SHL";
|
||||
case Opcode::BIT_SHR: return "BIT_SHR";
|
||||
case Opcode::BIT_NOT: return "BIT_NOT";
|
||||
case Opcode::NOT_UNARY: return "NOT_UNARY";
|
||||
case Opcode::CALLHOST: return "CALLHOST";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
|
|
|
|||
|
|
@ -17,25 +17,30 @@
|
|||
IRProgram IRGenerator::generate(ASTNode* programNode, SymbolTable& /*symbolTable*/) {
|
||||
IRProgram program;
|
||||
|
||||
// ProgramNode'un her çocuğunu gez.
|
||||
// Bizi ilgilendiren: FunctionDecl. StructDecl/GlobalVar → TODO.
|
||||
// Üst düzey global değişken bildirimlerini topla (#38)
|
||||
std::vector<ASTNode*> globalVars;
|
||||
for (ASTNode* child : programNode->getChildren()) {
|
||||
if (child->kind == ASTKind::VariableDecl)
|
||||
globalVars.push_back(child);
|
||||
}
|
||||
|
||||
for (ASTNode* child : programNode->getChildren()) {
|
||||
if (child->kind == ASTKind::FunctionDecl) {
|
||||
// Her fonksiyon üretimi için sıfırla
|
||||
nameToSlot_.clear();
|
||||
nextSlot_ = 0;
|
||||
|
||||
// IRFunction oluştur, currentFunction_ olarak işaretle
|
||||
auto* fnDecl = (FunctionDeclNode*)child;
|
||||
IRFunction irFn(fnDecl->name, (int)fnDecl->params.size());
|
||||
program.addFunction(std::move(irFn));
|
||||
|
||||
// addFunction std::move yaptığı için pointer'ı haritadan alalım
|
||||
currentFunction_ = program.findFunction(fnDecl->name);
|
||||
|
||||
generateFunction(child);
|
||||
// Global değişkenleri main'in başına ekle (Seçenek B)
|
||||
if (fnDecl->name == "main") {
|
||||
for (ASTNode* gv : globalVars)
|
||||
generateStatement(gv);
|
||||
}
|
||||
|
||||
// Fonksiyon bitti — toplam slot sayısını kaydet
|
||||
generateFunction(child);
|
||||
currentFunction_->slotCount = nextSlot_;
|
||||
}
|
||||
}
|
||||
|
|
@ -374,12 +379,18 @@ int IRGenerator::generateExpression(ASTNode* node) {
|
|||
int resultSlot = freshSlot();
|
||||
|
||||
if (bin->Operator == TokenType::MINUS) {
|
||||
// -x → 0 - x
|
||||
int zeroSlot = freshSlot();
|
||||
emitLoadConst(zeroSlot, 0);
|
||||
emitBinaryOp(Opcode::SUB, resultSlot, zeroSlot, operandSlot);
|
||||
} else if (bin->Operator == TokenType::BANG) {
|
||||
Instruction ins(Opcode::NOT_UNARY);
|
||||
ins.dest = resultSlot; ins.src = operandSlot;
|
||||
currentFunction_->instructions.push_back(std::move(ins));
|
||||
} else if (bin->Operator == TokenType::TILDE) {
|
||||
Instruction ins(Opcode::BIT_NOT);
|
||||
ins.dest = resultSlot; ins.src = operandSlot;
|
||||
currentFunction_->instructions.push_back(std::move(ins));
|
||||
} else {
|
||||
// Diğer unary operatörler → TODO
|
||||
emitLoadSlot(resultSlot, operandSlot);
|
||||
}
|
||||
return resultSlot;
|
||||
|
|
@ -399,6 +410,11 @@ int IRGenerator::generateExpression(ASTNode* node) {
|
|||
case TokenType::GREATER_EQUAL: return generateBinaryArithmetic(Opcode::GREATER_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);
|
||||
// Bitsel
|
||||
case TokenType::AMPERSAND: return generateBinaryArithmetic(Opcode::BIT_AND, bin->Left, bin->Right);
|
||||
case TokenType::PIPE: return generateBinaryArithmetic(Opcode::BIT_OR, bin->Left, bin->Right);
|
||||
case TokenType::LSHIFT: return generateBinaryArithmetic(Opcode::BIT_SHL, bin->Left, bin->Right);
|
||||
case TokenType::RSHIFT: return generateBinaryArithmetic(Opcode::BIT_SHR, bin->Left, bin->Right);
|
||||
default: {
|
||||
// Bilinmeyen operatör — boş slot döndür
|
||||
int slot = freshSlot();
|
||||
|
|
|
|||
|
|
@ -148,6 +148,31 @@ int Interpreter::run() {
|
|||
continue;
|
||||
}
|
||||
|
||||
// ── Bitsel ────────────────────────────────────────────────────────
|
||||
case Opcode::BIT_AND:
|
||||
frame.slots[instr.dest] = Value::fromInt(
|
||||
frame.slots[instr.left].intValue & frame.slots[instr.right].intValue);
|
||||
break;
|
||||
case Opcode::BIT_OR:
|
||||
frame.slots[instr.dest] = Value::fromInt(
|
||||
frame.slots[instr.left].intValue | frame.slots[instr.right].intValue);
|
||||
break;
|
||||
case Opcode::BIT_SHL:
|
||||
frame.slots[instr.dest] = Value::fromInt(
|
||||
frame.slots[instr.left].intValue << frame.slots[instr.right].intValue);
|
||||
break;
|
||||
case Opcode::BIT_SHR:
|
||||
frame.slots[instr.dest] = Value::fromInt(
|
||||
frame.slots[instr.left].intValue >> frame.slots[instr.right].intValue);
|
||||
break;
|
||||
case Opcode::BIT_NOT:
|
||||
frame.slots[instr.dest] = Value::fromInt(~frame.slots[instr.src].intValue);
|
||||
break;
|
||||
case Opcode::NOT_UNARY:
|
||||
frame.slots[instr.dest] = Value::fromInt(
|
||||
frame.slots[instr.src].intValue == 0 ? 1 : 0);
|
||||
break;
|
||||
|
||||
// ── FFI ───────────────────────────────────────────────────────────
|
||||
case Opcode::CALLHOST:
|
||||
executeHostFunction(instr.functionName, frame.slots, instr.argSlots);
|
||||
|
|
|
|||
Loading…
Reference in New Issue