// ============================================================================ // saQut Compiler — Tanılama (Diagnostic) Veri Yapıları + Hata Kataloğu // ============================================================================ // // DİZİN: src/diagnostic/diagnostic.hpp // KATMAN: Katman 0 — Tüm analiz katmanları tarafından kullanılır // BAĞIMLI: src/core/location.hpp // KULLANAN: DiagnosticEngine, sembol toplayıcı (Faz 2), tip denetleyici (Faz 3) // // AMAÇ: // Derleme sırasında bulunan hata/uyarıları YAPISAL veri olarak temsil eder. // "Veri birincil, insan-okur metin bir görünümdür" (readme → Tasarım felsefesi): // bir Diagnostic; seviye + kod + konum + mesaj taşır; ekrana basılan satır // bunun yalnızca bir render'ıdır. Bu sayede aynı tanı LSP, AI veya `saqut // explain` tarafından da tüketilebilir. // // HATA KATALOĞU (baştan sabitlenir — yeni kodlar buraya eklenir): // E001 Tanımsız değişken/isim (declare-before-use ihlali dâhil) Faz 2/3 // E002 Aynı scope'ta çift tanım Faz 2 // E003 Tip uyuşmazlığı (gizli dönüşüm yok, ADR-010) Faz 3 // E004 Döngü/switch dışı break/continue Faz 3 // E005 Fonksiyon dışı return Faz 3 // E006 Return tipi imzaya uymuyor Faz 3 // E007 Tanımsız tip (bilinmeyen tip adı) Faz 2/3 // E008 Fonksiyon çağrısı argüman sayısı/tipi uyuşmuyor Faz 3 // E009 Array boyutu sabit değil / geçersiz Faz 3 // E010 Özyinelemeli/döngüsel struct (by-value çevrim → sonsuz boyut) Faz 2/3 // W001 Kullanılmayan değişken Faz 4 // W002 Sıfıra bölme (sabit folding) Faz 4 // W003 Erişilemez (ölü) kod Faz 4 // // ============================================================================ #ifndef SAQUT_DIAGNOSTIC_DIAGNOSTIC #define SAQUT_DIAGNOSTIC_DIAGNOSTIC #include #include #include "core/location.hpp" // ============================================================================ // DiagLevel — Tanı seviyesi // ============================================================================ enum class DiagLevel { Error, Warning, Note, Hint }; inline const char* diagLevelName(DiagLevel l) { switch (l) { case DiagLevel::Error: return "error"; case DiagLevel::Warning: return "warning"; case DiagLevel::Note: return "note"; case DiagLevel::Hint: return "hint"; } return "?"; } // İnsan-okur çıktı için Türkçe karşılık inline const char* diagLevelNameTr(DiagLevel l) { switch (l) { case DiagLevel::Error: return "hata"; case DiagLevel::Warning: return "uyarı"; case DiagLevel::Note: return "not"; case DiagLevel::Hint: return "ipucu"; } return "?"; } // JSON string kaçışı (mesaj/ipucu tırnak veya satır sonu içerebilir) inline std::string jsonEscape(const std::string& s) { std::string out; out.reserve(s.size() + 8); for (char c : s) { switch (c) { case '"': out += "\\\""; break; case '\\': out += "\\\\"; break; case '\n': out += "\\n"; break; case '\r': out += "\\r"; break; case '\t': out += "\\t"; break; default: out += c; break; } } return out; } // ============================================================================ // Diagnostic — Tek bir tanı (hata/uyarı/not/ipucu) // ============================================================================ // // KULLANIM: // Diagnostic d{DiagLevel::Error, "E003", loc, "int'e string atanamaz"}; // d.hint = "açık dönüşüm gerekiyor"; // std::cout << d.toJson(); // ============================================================================ struct Diagnostic { DiagLevel level = DiagLevel::Error; std::string code; // "E003" (katalog kodu; boş olabilir) SourceLocation loc; // hatanın kaynak koddaki yeri std::string message; // bağlama özel açıklama std::string hint; // opsiyonel "şunu dene" önerisi std::string toJson() const { std::string s = "{"; s += "\"level\":\""; s += diagLevelName(level); s += "\","; s += "\"code\":\""; s += jsonEscape(code); s += "\","; s += "\"location\":"; s += loc.toJson(); s += ","; s += "\"message\":\""; s += jsonEscape(message); s += "\""; if (!hint.empty()) { s += ",\"hint\":\""; s += jsonEscape(hint); s += "\""; } s += "}"; return s; } }; // ============================================================================ // Hata Kataloğu — kod → (seviye, kanonik başlık) // ============================================================================ // // Bağlama özel mesaj report sırasında verilir; buradaki başlık, kodun GENEL // anlamıdır (ileride `saqut explain E003` bunu kullanabilir, #107/#98). // ============================================================================ struct DiagInfo { const char* code; DiagLevel level; const char* title; }; inline const std::vector& diagnosticCatalog() { static const std::vector catalog = { {"E001", DiagLevel::Error, "Tanımsız değişken/isim"}, {"E002", DiagLevel::Error, "Aynı scope'ta çift tanım"}, {"E003", DiagLevel::Error, "Tip uyuşmazlığı"}, {"E004", DiagLevel::Error, "Döngü/switch dışı break/continue"}, {"E005", DiagLevel::Error, "Fonksiyon dışı return"}, {"E006", DiagLevel::Error, "Return tipi imzaya uymuyor"}, {"E007", DiagLevel::Error, "Tanımsız tip"}, {"E008", DiagLevel::Error, "Fonksiyon çağrısı argümanı uyuşmuyor"}, {"E009", DiagLevel::Error, "Array boyutu sabit değil / geçersiz"}, {"E010", DiagLevel::Error, "Özyinelemeli/döngüsel struct tanımı"}, {"W001", DiagLevel::Warning, "Kullanılmayan değişken"}, {"W002", DiagLevel::Warning, "Sıfıra bölme (sabit ifade)"}, {"W003", DiagLevel::Warning, "Erişilemez (ölü) kod"}, }; return catalog; } // Kod kataloğda var mı? (yoksa nullptr) inline const DiagInfo* findDiag(const std::string& code) { for (const auto& d : diagnosticCatalog()) if (code == d.code) return &d; return nullptr; } // Bir koddan Diagnostic üretir; seviye kataloğdan çözülür (yoksa: E→Error, // W→Warning, diğer→Note). Bağlama özel mesajı çağıran verir. inline Diagnostic makeDiagnostic(const std::string& code, const SourceLocation& loc, const std::string& message, const std::string& hint = "") { DiagLevel level = DiagLevel::Note; if (const DiagInfo* info = findDiag(code)) { level = info->level; } else if (!code.empty()) { if (code[0] == 'E') level = DiagLevel::Error; else if (code[0] == 'W') level = DiagLevel::Warning; } Diagnostic d; d.level = level; d.code = code; d.loc = loc; d.message = message; d.hint = hint; return d; } #endif // SAQUT_DIAGNOSTIC_DIAGNOSTIC