From 7c7f886e9c7a824dc740f359bb9a8a32123592a9 Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Thu, 18 Jun 2026 19:21:12 +0300 Subject: [PATCH] =?UTF-8?q?feat(cli):=20saqut=20ir=20komutu=20=E2=80=94=20?= =?UTF-8?q?IR=20talimat=20dump'u?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - IRFunction::dump() yenilendi: ASCII kutu, sn slot notasyonu, ikili op'larda sembol (+/-/*/<= vb.), hizalı sütunlar - src/cli/commands/ir.hpp: tokenize→parse→collect→ir→dump pipeline - main.cpp + args.hpp: "ir" komutu kayıtlı Co-Authored-By: Claude Opus 4.8 --- build/.ninja_deps | Bin 53112 -> 50124 bytes build/.ninja_log | 12 ++-- src/cli/args.hpp | 5 +- src/cli/commands/ir.hpp | 50 ++++++++++++++ src/ir/ir_function.cpp | 150 +++++++++++++++++++++++++++------------- src/main.cpp | 5 ++ 6 files changed, 168 insertions(+), 54 deletions(-) create mode 100644 src/cli/commands/ir.hpp diff --git a/build/.ninja_deps b/build/.ninja_deps index 455e7f938f55a8607b14289d2fdef4e5956af4e0..00c402ed8bd06562219f198c9f8e180c1e5ac486 100644 GIT binary patch delta 655 zcmew{kNHeH^9GR#lUaOqC-e66if0z-WfT-7{QLi3hmE13iIIU}B|~+A&*rTsB5YWlVhhlGe%5aINh2teDdAt_KaabMGBK`XNWU~P7a+R&l&<$E;4!I z3}MFL$-OhA8G|OToFUH`IQirZY1ROsoXq62GsGv&WMTCOa!e*a6xQa<$xKR5PS#8G zn`}E%oz)kt$Z@9V89gW8ovF^~0d%bqS885L zFwp4?4DLX0i0irmH7sCYXjlOBs`1R`1|Q2^5(|OsML@h5h(TZpkX{PJ%O?Llr_H+@ z$XWr!D}gwE^1)g5j5{YQZgduP1)8*jnV|usI}bKkH_TQXSqGrh z5ug;vvH8qwX&|ZnKsFQ5TYZ}ww{|ma=2(@&ENTx_w*hGPDxloVjJ-PqfKEHGxpD1c kW_lpOk$w1>;&2b0RF%BxBvhE delta 724 zcmbV~O=uHQ5Xawh-328LS<)q;6;r4seqe%%ZKQ(hNBn4wTI089YD=pDY5I{Ig&-6W zg~krLy9r5S+tlVzo3aQoF*Z^Q3XzJpUPSaR^i&10&P&X}s|&+>Gr#}Ln;EurkNc6} zGPM!oR)K`?QbI~~556zE^xnv3p~*l98M-kL3gX%Mdu^>2PiJUo(0SY6<@9zB26s6E zKA3r8q1V9^-Mz7^=cd2U>j;o*K$VtJ#ST72q*q};*~4GKeEE^M2^N(`{xUi)=4?>w z`Ag{RXO3I7(TkYb0K=+nox&qD$Ib0BJF_^7Vu9nFMzk=p24jMdYQvQpLz z^bB~k7XCCA+yZl&1PRSZPnBsAsRur27J9N==ZjXU(+)J+NZX((YNsb~h*tM;%>HLk zoU;#SI)?EiA>lDx(x>q|zm{D&YZC8I(ZEUNNtnr;Q>&)g=A8AVK9l~&OKwE(5V7oG?rSSUIXyMY3DOZnZxOMg z0Z!;;D6bb@tn$)fL>Z2R(}?0ras%t|mHs|I!9g&;6GAbwbOlB&hTq}E~Qi|_#c|A*t(3W61Ko5HI|AorkdB|WAnUNeO|j& t$eQ+5pBJm@rNuY0h~bL5ruxry{v1t+dQZeAY)k&#aGR8S&XoVL;Xl!Z4r~Ab 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",