diff --git a/build/.ninja_deps b/build/.ninja_deps index 455e7f9..00c402e 100644 Binary files a/build/.ninja_deps and b/build/.ninja_deps differ diff --git a/build/.ninja_log b/build/.ninja_log index d1b50d9..37816b2 100644 --- a/build/.ninja_log +++ b/build/.ninja_log @@ -10,14 +10,16 @@ 21 7502 1781796718449424977 CMakeFiles/saqut.dir/src/parser/nodes/statements.cpp.o 3c8869307381c930 14 6864 1781796718442362341 CMakeFiles/saqut.dir/src/parser/nodes/binary_expr.cpp.o 5cc8b697133bcf64 15 6733 1781796718442847556 CMakeFiles/saqut.dir/src/parser/nodes/declarations.cpp.o c3d262615ede4c95 -2 4655 1781799345769869911 CMakeFiles/saqut.dir/src/main.cpp.o 3cfef7a665d5bf87 -4655 4925 1781799350422111935 saqut f2e198803c4dbffb -0 22 1781799395548855747 build.ninja 1876a59d627a585 -0 22 1781799395548855747 /home/saqut/Masaüstü/saqutcompiler/build/cmake_install.cmake 1876a59d627a585 +2 4490 1781799598563879630 CMakeFiles/saqut.dir/src/main.cpp.o 3cfef7a665d5bf87 +4490 4758 1781799603051859470 saqut f2e198803c4dbffb +0 22 1781799611852960564 build.ninja 1876a59d627a585 +0 22 1781799611852960564 /home/saqut/Masaüstü/saqutcompiler/build/cmake_install.cmake 1876a59d627a585 6733 11112 1781796725160284765 CMakeFiles/saqut.dir/src/symbol/symbol_collector.cpp.o ec4e483b8ddb4007 4805 9685 1781796723232278341 CMakeFiles/saqut.dir/src/semantic/structural_validator.cpp.o 248faa3675024351 6700 10405 1781796725127284655 CMakeFiles/saqut.dir/src/semantic/type_checker.cpp.o b29c133293d988b0 2 795 1781799345769990010 CMakeFiles/saqut.dir/src/vm/interpreter.cpp.o b7dd80e002d68a1d -1 958 1781799106946635459 CMakeFiles/saqut.dir/src/ir/ir_function.cpp.o 10f5e8dfd1461d69 +1 668 1781799598562879634 CMakeFiles/saqut.dir/src/ir/ir_function.cpp.o 10f5e8dfd1461d69 1 1001 1781799106947865509 CMakeFiles/saqut.dir/src/ir/ir_program.cpp.o 9518231d970828da 2 3078 1781799345769137653 CMakeFiles/saqut.dir/src/ir/ir_generator.cpp.o 10a1ed4e1f52e530 +1 636 1781799663202595202 CMakeFiles/saqut.dir/src/ir/ir_function.cpp.o 10f5e8dfd1461d69 +636 892 1781799663837592468 saqut f2e198803c4dbffb diff --git a/src/cli/args.hpp b/src/cli/args.hpp index 123e1f1..e74b105 100644 --- a/src/cli/args.hpp +++ b/src/cli/args.hpp @@ -88,8 +88,9 @@ inline CliArgs parseArgs(int argc, char* argv[]) { // İlk argüman komut mu? if (args.command.empty() && i == 1) { if (arg == "run" || arg == "tokens" || arg == "ast" || - arg == "symbols" || arg == "check" || arg == "compile" || - arg == "parse" || arg == "transpile" || arg == "interpret") { + arg == "symbols" || arg == "check" || arg == "ir" || + arg == "compile" || arg == "parse" || arg == "transpile" || + arg == "interpret") { args.command = arg; continue; } diff --git a/src/cli/commands/ir.hpp b/src/cli/commands/ir.hpp new file mode 100644 index 0000000..640f576 --- /dev/null +++ b/src/cli/commands/ir.hpp @@ -0,0 +1,50 @@ +#ifndef SAQUT_CLI_IR +#define SAQUT_CLI_IR + +#include +#include "cli/args.hpp" +#include "tokenizer/tokenizer.hpp" +#include "parser/parser.hpp" +#include "symbol/symbol_table.hpp" +#include "symbol/symbol_collector.hpp" +#include "diagnostic/diagnostic_engine.hpp" +#include "ir/ir_generator.hpp" + +inline int cmdIr(const CliArgs& args) { + std::string filePath = inputFilePath(args); + std::string source = readSource(args); + if (source.empty()) return 1; + + Tokenizer tokenizer; + auto tokens = tokenizer.scan(source, filePath); + + Parser parser; + ASTNode* ast = parser.parse(tokens); + if (!ast) { + std::cerr << "Hata: AST üretilemedi\n"; + for (auto* t : tokens) delete t; + return 1; + } + + SymbolTable symbolTable; + DiagnosticEngine diag; + SymbolCollector(symbolTable, diag).collect(ast); + + if (diag.hasErrors()) { + diag.printAll(std::cerr); + delete ast; + for (auto* t : tokens) delete t; + return 1; + } + + IRGenerator irGenerator; + IRProgram program = irGenerator.generate(ast, symbolTable); + + program.dump(); + + delete ast; + for (auto* t : tokens) delete t; + return 0; +} + +#endif // SAQUT_CLI_IR diff --git a/src/ir/ir_function.cpp b/src/ir/ir_function.cpp index 9606822..33acf5e 100644 --- a/src/ir/ir_function.cpp +++ b/src/ir/ir_function.cpp @@ -1,62 +1,118 @@ #include "ir/ir_function.hpp" #include #include +#include + +// ───────────────────────────────────────────────────────────────────────────── +// Yardımcılar +// ───────────────────────────────────────────────────────────────────────────── + +// Slot adını kısa göster: s0, s1, ... +static std::string slot(int s) { + if (s == -1) return "?"; + return "s" + std::to_string(s); +} + +// İkili op sembolü: ADD → "+" +static const char* opSymbol(Opcode op) { + switch (op) { + case Opcode::ADD: return "+"; + case Opcode::SUB: return "-"; + case Opcode::MUL: return "*"; + case Opcode::DIV: return "/"; + case Opcode::MOD: return "%"; + case Opcode::LESS: return "<"; + case Opcode::LESS_EQUAL: return "<="; + case Opcode::GREATER: return ">"; + case Opcode::GREATER_EQUAL: return ">="; + case Opcode::EQUAL_EQUAL: return "=="; + case Opcode::NOT_EQUAL: return "!="; + default: return "?"; + } +} + +static bool isBinaryOp(Opcode op) { + switch (op) { + case Opcode::ADD: case Opcode::SUB: case Opcode::MUL: + case Opcode::DIV: case Opcode::MOD: + case Opcode::LESS: case Opcode::LESS_EQUAL: + case Opcode::GREATER: case Opcode::GREATER_EQUAL: + case Opcode::EQUAL_EQUAL: case Opcode::NOT_EQUAL: + return true; + default: return false; + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// IRFunction::dump +// ───────────────────────────────────────────────────────────────────────────── -// Her instruction'ı "indeks: OPCODE operandlar" formatında yazdır. -// Bu çıktı hem insanın okuduğu hem de birim testlerin karşılaştırdığı formattır. void IRFunction::dump() const { - std::cout << "=== " << name - << " (paramCount=" << paramCount - << ", slotCount=" << slotCount << ") ===\n"; + // Başlık: fonksiyon adı + slot bilgisi + std::string header = " " + name + "()"; + if (paramCount > 0) { + header = " " + name + "("; + for (int i = 0; i < paramCount; i++) { + if (i) header += ", "; + header += "s" + std::to_string(i); + } + header += ")"; + } + header += " [" + std::to_string(slotCount) + " slot]"; + // Üst çizgi + std::cout << "+-" << std::string(header.size(), '-') << "-+\n"; + std::cout << "|" << header << " |\n"; + std::cout << "+-" << std::string(header.size(), '-') << "-+\n"; + + // Talimatlar for (int i = 0; i < (int)instructions.size(); i++) { const Instruction& ins = instructions[i]; - std::cout << " " << std::setw(3) << i << ": " - << std::left << std::setw(14) << opcodeName(ins.opcode); - switch (ins.opcode) { - case Opcode::LOAD_CONST: - std::cout << "slot[" << ins.dest << "] = " << ins.intValue; - break; - case Opcode::LOAD_SLOT: - std::cout << "slot[" << ins.dest << "] = slot[" << ins.src << "]"; - break; - case Opcode::ADD: case Opcode::SUB: case Opcode::MUL: - case Opcode::DIV: case Opcode::MOD: - case Opcode::LESS: case Opcode::LESS_EQUAL: - case Opcode::GREATER: case Opcode::GREATER_EQUAL: - case Opcode::EQUAL_EQUAL: case Opcode::NOT_EQUAL: - std::cout << "slot[" << ins.dest << "] = " - << "slot[" << ins.left << "] op slot[" << ins.right << "]"; - break; - case Opcode::JMP: - std::cout << "→ " << ins.jumpTarget; - break; - case Opcode::JIF_FALSE: - std::cout << "if !slot[" << ins.cond << "] → " << ins.jumpTarget; - break; - case Opcode::CALL: { - std::cout << "slot[" << ins.dest << "] = " << ins.functionName << "("; - for (int j = 0; j < (int)ins.argSlots.size(); j++) { - if (j) std::cout << ", "; - std::cout << "slot[" << ins.argSlots[j] << "]"; - } - std::cout << ")"; - break; + // Satır numarası + std::cout << " " << std::setw(3) << std::right << i << "│ "; + + // Opcode sütunu (12 karakter genişlik) + std::cout << std::left << std::setw(12) << opcodeName(ins.opcode); + + // Operandlar — opcode'a göre farklı format + if (ins.opcode == Opcode::LOAD_CONST) { + std::cout << slot(ins.dest) << " = " << ins.intValue; + + } else if (ins.opcode == Opcode::LOAD_SLOT) { + std::cout << slot(ins.dest) << " = " << slot(ins.src); + + } else if (isBinaryOp(ins.opcode)) { + std::cout << slot(ins.dest) << " = " + << slot(ins.left) << " " << opSymbol(ins.opcode) + << " " << slot(ins.right); + + } else if (ins.opcode == Opcode::JMP) { + std::cout << "→ " << ins.jumpTarget; + + } else if (ins.opcode == Opcode::JIF_FALSE) { + std::cout << "!" << slot(ins.cond) << " → " << ins.jumpTarget; + + } else if (ins.opcode == Opcode::CALL) { + std::cout << slot(ins.dest) << " = " << ins.functionName << "("; + for (int j = 0; j < (int)ins.argSlots.size(); j++) { + if (j) std::cout << ", "; + std::cout << slot(ins.argSlots[j]); } - case Opcode::RETURN: - std::cout << "slot[" << ins.src << "]"; - break; - case Opcode::CALLHOST: { - std::cout << ins.functionName << "("; - for (int j = 0; j < (int)ins.argSlots.size(); j++) { - if (j) std::cout << ", "; - std::cout << "slot[" << ins.argSlots[j] << "]"; - } - std::cout << ")"; - break; + std::cout << ")"; + + } else if (ins.opcode == Opcode::CALLHOST) { + std::cout << ins.functionName << "("; + for (int j = 0; j < (int)ins.argSlots.size(); j++) { + if (j) std::cout << ", "; + std::cout << slot(ins.argSlots[j]); } + std::cout << ")"; + + } else if (ins.opcode == Opcode::RETURN) { + std::cout << slot(ins.src); } + std::cout << "\n"; } std::cout << "\n"; diff --git a/src/main.cpp b/src/main.cpp index 78609e3..66b8929 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,6 +28,7 @@ #include "cli/commands/ast.hpp" #include "cli/commands/symbols.hpp" #include "cli/commands/check.hpp" +#include "cli/commands/ir.hpp" int main(int argc, char* argv[]) { // Komutları kaydet @@ -53,6 +54,10 @@ int main(int argc, char* argv[]) { "Semantik analiz — tip denetimi + yapısal doğrulama", false, cmdCheck}); + cli.registerCommand({"ir", + "IR talimat listesini göster (ara temsil — bytecode öncesi)", + false, cmdIr}); + // --- Gelecek komutlar (TODO) --- cli.registerCommand({"compile", "TODO: Kaynak kodu derle",