From d51e48dbb2541f463ed41b1b4b0b6521a095b1ce Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Thu, 18 Jun 2026 21:21:28 +0300 Subject: [PATCH] =?UTF-8?q?feat(opt):=20sabit=20katlama'ya=20unary=20opera?= =?UTF-8?q?t=C3=B6rler=20ekle=20(!,=20~,=20-,=20+)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parser unary'yi BinaryExpressionNode(Left=nullptr) olarak temsil eder. isScalarLit/getScalarVal/canFoldUnary/computeUnary eklendi. Katlanan ifadeler: !0→1, !1→0, !42→0, ~0→-1, ~1→-2, -5→-5, +7→7, !true→0, !false→1. Zincirli: !(!0)→0 (fixpoint ile). Boolean literal (true/false) da !operatörü için desteklenir. Co-Authored-By: Claude Opus 4.8 --- src/opt/constant_folding.hpp | 57 +++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/opt/constant_folding.hpp b/src/opt/constant_folding.hpp index 44c5577..f09426a 100644 --- a/src/opt/constant_folding.hpp +++ b/src/opt/constant_folding.hpp @@ -45,12 +45,51 @@ private: return lit && lit->literalType == LiteralType::INTEGER; } + // Boolean veya integer literal — unary ! için her ikisi de geçerli + static bool isScalarLit(ASTNode* node) { + auto* lit = dynamic_cast(node); + return lit && (lit->literalType == LiteralType::INTEGER || + lit->literalType == LiteralType::BOOLEAN); + } + static int getIntVal(LiteralNode* lit) { if (lit->hasDirectValue) return lit->directIntValue; if (lit->parserToken.token) return std::stoi(lit->parserToken.token->token); return 0; } + // Boolean literali int'e çevir: "true"→1, "false"→0 + static int getScalarVal(LiteralNode* lit) { + if (lit->literalType == LiteralType::BOOLEAN) { + if (!lit->parserToken.token) return 0; + return (lit->parserToken.token->token == "true") ? 1 : 0; + } + return getIntVal(lit); + } + + // Unary operatör katlama + static bool canFoldUnary(TokenType op) { + switch (op) { + case TokenType::BANG: // ! + case TokenType::TILDE: // ~ + case TokenType::MINUS: // - (negatif) + case TokenType::PLUS: // + (pozitif, no-op) + return true; + default: + return false; + } + } + + static int computeUnary(TokenType op, int v) { + switch (op) { + case TokenType::BANG: return !v ? 1 : 0; + case TokenType::TILDE: return ~v; + case TokenType::MINUS: return -v; + case TokenType::PLUS: return v; + default: return v; + } + } + // ── Operatör hesaplama ─────────────────────────────────────────────────── static bool canFoldOp(TokenType op) { switch (op) { @@ -123,7 +162,23 @@ private: ASTNode* newRight = fold(bin->Right); if (newRight != bin->Right) { bin->Right = newRight; if (newRight) newRight->parent = bin; } - // İki taraf da tam sayı sabiti ve operatör kesilebilir mi? + // ── Unary dal: Left==nullptr → !x, ~x, -x, +x ────────────────── + if (bin->Left == nullptr) { + if (!isScalarLit(bin->Right)) return bin; + if (!canFoldUnary(bin->Operator)) return bin; + + auto* rlit = static_cast(bin->Right); + int rv = getScalarVal(rlit); + int result = computeUnary(bin->Operator, rv); + + LiteralNode* lit = makeFoldedLit(result, bin->loc, bin->resolvedType); + delete bin->Right; + delete bin; + changed_ = true; + return lit; + } + + // ── Binary dal: iki taraf da tam sayı sabiti ──────────────────── if (!isIntLit(bin->Left) || !isIntLit(bin->Right)) return bin; if (!canFoldOp(bin->Operator)) return bin;