saqut-compiler/src/vm/interpreter.cpp

174 lines
7.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "vm/interpreter.hpp"
#include <iostream>
#include <stdexcept>
int Interpreter::run() {
IRFunction* mainFunction = program_.findFunction("main");
if (!mainFunction)
throw std::runtime_error("Çalışma hatası: 'main' fonksiyonu bulunamadı");
CallFrame mainFrame;
mainFrame.function = mainFunction;
mainFrame.instructionPointer = 0;
mainFrame.slots.resize(mainFunction->slotCount, Value::fromInt(0));
mainFrame.returnDestSlot = -1;
callStack_.push_back(std::move(mainFrame));
while (!callStack_.empty()) {
CallFrame& frame = callStack_.back();
if (frame.instructionPointer >= (int)frame.function->instructions.size()) {
int destSlot = frame.returnDestSlot;
callStack_.pop_back();
if (!callStack_.empty() && destSlot != -1)
callStack_.back().slots[destSlot] = Value::fromInt(0);
continue;
}
const Instruction& instr = frame.function->instructions[frame.instructionPointer];
frame.instructionPointer++;
switch (instr.opcode) {
case Opcode::LOAD_CONST:
frame.slots[instr.dest] = Value::fromInt(instr.intValue);
break;
case Opcode::LOAD_STRING:
frame.slots[instr.dest] = Value::fromString(instr.stringValue);
break;
case Opcode::LOAD_SLOT:
frame.slots[instr.dest] = frame.slots[instr.src];
break;
// ── Aritmetik ─────────────────────────────────────────────────────
// TypeChecker derleme zamanında tipleri doğruladı — burada sadece hesap yapılır.
// İstisna: sıfıra bölme gerçek bir çalışma zamanı koşuludur, kontrol edilir.
case Opcode::ADD:
frame.slots[instr.dest] = Value::fromInt(
frame.slots[instr.left].intValue + frame.slots[instr.right].intValue);
break;
case Opcode::SUB:
frame.slots[instr.dest] = Value::fromInt(
frame.slots[instr.left].intValue - frame.slots[instr.right].intValue);
break;
case Opcode::MUL:
frame.slots[instr.dest] = Value::fromInt(
frame.slots[instr.left].intValue * frame.slots[instr.right].intValue);
break;
case Opcode::DIV: {
int d = frame.slots[instr.right].intValue;
if (d == 0) throw std::runtime_error("Çalışma hatası: sıfıra bölme");
frame.slots[instr.dest] = Value::fromInt(frame.slots[instr.left].intValue / d);
break;
}
case Opcode::MOD: {
int d = frame.slots[instr.right].intValue;
if (d == 0) throw std::runtime_error("Çalışma hatası: sıfıra bölme (mod)");
frame.slots[instr.dest] = Value::fromInt(frame.slots[instr.left].intValue % d);
break;
}
// ── Karşılaştırma ─────────────────────────────────────────────────
case Opcode::LESS:
frame.slots[instr.dest] = Value::fromInt(
frame.slots[instr.left].intValue < frame.slots[instr.right].intValue ? 1 : 0);
break;
case Opcode::LESS_EQUAL:
frame.slots[instr.dest] = Value::fromInt(
frame.slots[instr.left].intValue <= frame.slots[instr.right].intValue ? 1 : 0);
break;
case Opcode::GREATER:
frame.slots[instr.dest] = Value::fromInt(
frame.slots[instr.left].intValue > frame.slots[instr.right].intValue ? 1 : 0);
break;
case Opcode::GREATER_EQUAL:
frame.slots[instr.dest] = Value::fromInt(
frame.slots[instr.left].intValue >= frame.slots[instr.right].intValue ? 1 : 0);
break;
case Opcode::EQUAL_EQUAL: {
auto& lv = frame.slots[instr.left]; auto& rv = frame.slots[instr.right];
int r = (lv.kind == ValueKind::String)
? (lv.stringValue == rv.stringValue ? 1 : 0)
: (lv.intValue == rv.intValue ? 1 : 0);
frame.slots[instr.dest] = Value::fromInt(r);
break;
}
case Opcode::NOT_EQUAL: {
auto& lv = frame.slots[instr.left]; auto& rv = frame.slots[instr.right];
int r = (lv.kind == ValueKind::String)
? (lv.stringValue != rv.stringValue ? 1 : 0)
: (lv.intValue != rv.intValue ? 1 : 0);
frame.slots[instr.dest] = Value::fromInt(r);
break;
}
// ── Kontrol akışı ─────────────────────────────────────────────────
case Opcode::JMP:
frame.instructionPointer = instr.jumpTarget;
break;
case Opcode::JIF_FALSE:
if (!frame.slots[instr.cond].isTruthy())
frame.instructionPointer = instr.jumpTarget;
break;
// ── Fonksiyon çağrısı ─────────────────────────────────────────────
case Opcode::CALL: {
IRFunction* callee = program_.findFunction(instr.functionName);
if (!callee)
throw std::runtime_error(
"Çalışma hatası: '" + instr.functionName + "' fonksiyonu bulunamadı");
CallFrame newFrame;
newFrame.function = callee;
newFrame.instructionPointer = 0;
newFrame.slots.resize(callee->slotCount, Value::fromInt(0));
newFrame.returnDestSlot = instr.dest;
for (int i = 0; i < (int)instr.argSlots.size(); i++)
newFrame.slots[i] = frame.slots[instr.argSlots[i]];
callStack_.push_back(std::move(newFrame));
continue;
}
// ── Dönüş ─────────────────────────────────────────────────────────
case Opcode::RETURN: {
Value returnValue = frame.slots[instr.src];
int returnDestSlot = frame.returnDestSlot;
callStack_.pop_back();
if (!callStack_.empty() && returnDestSlot != -1)
callStack_.back().slots[returnDestSlot] = returnValue;
if (callStack_.empty())
return returnValue.intValue;
continue;
}
// ── FFI ───────────────────────────────────────────────────────────
case Opcode::CALLHOST:
executeHostFunction(instr.functionName, frame.slots, instr.argSlots);
break;
}
}
return 0;
}
void Interpreter::executeHostFunction(const std::string& name,
const std::vector<Value>& slots,
const std::vector<int>& argSlots) {
if (name == "print") {
if (!argSlots.empty()) {
const Value& val = slots[argSlots[0]];
if (val.kind == ValueKind::String) std::cout << val.stringValue << "\n";
else std::cout << val.intValue << "\n";
}
return;
}
throw std::runtime_error("Çalışma hatası: bilinmeyen host fonksiyonu '" + name + "'");
}