#include "fiko/zeka/pipeline.hpp" #include "simdjson.h" #include #include #include #include namespace fiko::zeka { namespace { namespace sj = simdjson; // ---- JSON yazım (graf.cpp'deki biçimin ikizi — orası anonim ns, paylaşılamıyor) ---- void jsonKac(std::string& c, const std::string& s) { c += '"'; for (char ch : s) { if (ch == '"' || ch == '\\') { c += '\\'; c += ch; } else if (ch == '\n') c += "\\n"; else c += ch; } c += '"'; } void jsonDeger(std::string& c, const Deger& d) { if (std::holds_alternative(d)) c += "null"; else if (std::holds_alternative(d)) c += std::get(d) ? "true" : "false"; else if (std::holds_alternative(d)) c += std::to_string(std::get(d)); else if (std::holds_alternative(d)) c += std::to_string(std::get(d)); else if (std::holds_alternative(d)) { const auto& v = std::get(d); c += '['; c += std::to_string(v.x); c += ','; c += std::to_string(v.y); c += ','; c += std::to_string(v.z); c += ']'; } else if (std::holds_alternative(d)) { jsonKac(c, std::get(d)); } else if (std::holds_alternative>(d)) { c += '['; const auto& v = std::get>(d); for (size_t i = 0; i < v.size(); ++i) { if (i) c += ','; c += std::to_string(v[i]); } c += ']'; } else if (std::holds_alternative>(d)) { c += '['; const auto& v = std::get>(d); for (size_t i = 0; i < v.size(); ++i) { if (i) c += ','; c += std::to_string(v[i]); } c += ']'; } } // ---- Stage registry --------------------------------------------------------- struct KayitDefteri { std::unordered_map indeks; // ad → 1-tabanlı kimlik (intern) std::vector adlar; std::vector fabrikalar; std::mutex kilit; }; KayitDefteri& defterHam() { static KayitDefteri d; return d; } u32 stageKaydetIc(KayitDefteri& d, std::string_view ad, AsamaFabrika f) { std::lock_guard kilit(d.kilit); auto it = d.indeks.find(std::string(ad)); if (it != d.indeks.end()) { d.fabrikalar[it->second - 1] = std::move(f); return it->second; } d.adlar.emplace_back(ad); d.fabrikalar.push_back(std::move(f)); u32 kimlik = (u32)d.adlar.size(); d.indeks.emplace(d.adlar.back(), kimlik); return kimlik; } // ---- Parametre yardımcıları ------------------------------------------------- const Deger* paramBul(const PipelineAsama& a, const char* ad) { auto it = a.param.find(ad); return it == a.param.end() ? nullptr : &it->second; } bool paramMetin(const PipelineAsama& a, const char* ad, std::string& c) { const Deger* v = paramBul(a, ad); if (!v || !std::holds_alternative(*v)) return false; c = std::get(*v); return true; } bool paramSayi(const PipelineAsama& a, const char* ad, f64& c) { const Deger* v = paramBul(a, ad); return v && degerSayi(*v, c); } // ---- Koşul değerlendirme (Sorgu::uyar semantiği) ---------------------------- bool kosulUyar(const GrafDeposu& g, u64 id, const AsamaKosul& k) { switch (k.tur) { case AsamaKosul::Tur::Var: return g.oz(id, k.anahtar) != nullptr; case AsamaKosul::Tur::Esit: { const Deger* v = g.oz(id, k.anahtar); return v && degerEsit(*v, k.deger); } case AsamaKosul::Tur::EsitDegil: { const Deger* v = g.oz(id, k.anahtar); return v && !degerEsit(*v, k.deger); } case AsamaKosul::Tur::Buyuk: case AsamaKosul::Tur::BuyukEsit: case AsamaKosul::Tur::Kucuk: case AsamaKosul::Tur::KucukEsit: { const Deger* v = g.oz(id, k.anahtar); f64 x, y; if (!v || !degerSayi(*v, x) || !degerSayi(k.deger, y)) return false; switch (k.tur) { case AsamaKosul::Tur::Buyuk: return x > y; case AsamaKosul::Tur::BuyukEsit: return x >= y; case AsamaKosul::Tur::Kucuk: return x < y; default: return x <= y; } } case AsamaKosul::Tur::Aralik: { const Deger* v = g.oz(id, k.anahtar); f64 s; return v && degerSayi(*v, s) && s >= k.enAz && s <= k.enCok; } case AsamaKosul::Tur::Iliskili: { u32 hedefTip = k.hedefTip.empty() ? 0 : g.adBul(k.hedefTip); if (!k.hedefTip.empty() && !hedefTip) return false; for (u64 komsu : g.komsular(id, k.anahtar, k.yon)) { const ZDugum* h = g.dugum(komsu); if (h && (!hedefTip || h->tip == hedefTip)) return true; } return false; } } return false; } bool islecCoz(std::string_view islec, AsamaKosul::Tur& tur) { if (islec == "==") tur = AsamaKosul::Tur::Esit; else if (islec == "!=") tur = AsamaKosul::Tur::EsitDegil; else if (islec == ">") tur = AsamaKosul::Tur::Buyuk; else if (islec == ">=") tur = AsamaKosul::Tur::BuyukEsit; else if (islec == "<") tur = AsamaKosul::Tur::Kucuk; else if (islec == "<=") tur = AsamaKosul::Tur::KucukEsit; else return false; return true; } // Kimlik listesi ve (paralelse) satırları birlikte süzer. template void ciftFiltre(AsamaBaglam& b, F&& uygun) { auto& ids = b.sonuc.kimlikler; auto& sat = b.sonuc.satirlar; const bool paralel = sat.size() == ids.size() && !sat.empty(); std::vector yeniId; std::vector>> yeniSat; for (size_t i = 0; i < ids.size(); ++i) { if (!uygun(ids[i])) continue; yeniId.push_back(ids[i]); if (paralel) yeniSat.push_back(std::move(sat[i])); } ids = std::move(yeniId); if (paralel) sat = std::move(yeniSat); else sat.clear(); } // ---- Çekirdek stage fabrikaları (aynı registry — plugin-first kanıtı) ------- void cekirdekKaydet(KayitDefteri& d) { stageKaydetIc(d, "kaynak", [](const PipelineAsama& a, std::string& hata) -> AsamaYurutucu { std::string tip; if (!paramMetin(a, "tip", tip)) { hata = "kaynak: 'tip' (metin) gerekli"; return {}; } return [tip](AsamaBaglam& b) { b.sonuc.kimlikler = b.graf.tipteki(tip); b.sonuc.satirlar.clear(); b.baslatildi = true; }; }); stageKaydetIc(d, "govdede", [](const PipelineAsama& a, std::string& hata) -> AsamaYurutucu { f64 g = 0; if (!paramSayi(a, "govde", g)) { hata = "govdede: 'govde' (sayı) gerekli"; return {}; } const u64 govde = (u64)g; return [govde](AsamaBaglam& b) { if (!b.baslatildi) { b.sonuc.kimlikler = b.graf.govdeDugumleri(govde); b.sonuc.satirlar.clear(); b.baslatildi = true; return; } ciftFiltre(b, [&](u64 id) { const ZDugum* dn = b.graf.dugum(id); return dn && dn->brep.govde == govde; }); }; }); stageKaydetIc(d, "suz", [](const PipelineAsama& a, std::string&) -> AsamaYurutucu { return [kosullar = a.kosullar](AsamaBaglam& b) { asamaBaslat(b); ciftFiltre(b, [&](u64 id) { for (const auto& k : kosullar) if (!kosulUyar(b.graf, id, k)) return false; return true; }); }; }); stageKaydetIc(d, "genislet", [](const PipelineAsama& a, std::string& hata) -> AsamaYurutucu { std::string iliski, hedef; if (!paramMetin(a, "iliski", iliski)) { hata = "genislet: 'iliski' (metin) gerekli"; return {}; } paramMetin(a, "hedef", hedef); f64 yonF = 0; paramSayi(a, "yon", yonF); const int yon = (int)yonF; return [iliski, hedef, yon](AsamaBaglam& b) { asamaBaslat(b); u32 hedefTip = hedef.empty() ? 0 : b.graf.adBul(hedef); std::vector yeni; if (hedef.empty() || hedefTip) { std::unordered_set gorulen; for (u64 id : b.sonuc.kimlikler) { for (u64 komsu : b.graf.komsular(id, iliski, yon)) { const ZDugum* h = b.graf.dugum(komsu); if (!h || (hedefTip && h->tip != hedefTip)) continue; if (gorulen.insert(komsu).second) yeni.push_back(komsu); } } } b.sonuc.kimlikler = std::move(yeni); b.sonuc.satirlar.clear(); }; }); stageKaydetIc(d, "sec", [](const PipelineAsama& a, std::string& hata) -> AsamaYurutucu { if (a.anahtarlar.empty()) { hata = "sec: anahtar listesi boş"; return {}; } return [anahtarlar = a.anahtarlar](AsamaBaglam& b) { asamaBaslat(b); b.sonuc.satirlar.clear(); b.sonuc.satirlar.reserve(b.sonuc.kimlikler.size()); for (u64 id : b.sonuc.kimlikler) { std::vector> satir; satir.reserve(anahtarlar.size()); for (const auto& k : anahtarlar) { const Deger* v = b.graf.oz(id, k); satir.emplace_back(k, v ? *v : Deger{}); } b.sonuc.satirlar.push_back(std::move(satir)); } }; }); stageKaydetIc(d, "sirala", [](const PipelineAsama& a, std::string& hata) -> AsamaYurutucu { std::string anahtar; if (!paramMetin(a, "anahtar", anahtar)) { hata = "sirala: 'anahtar' (metin) gerekli"; return {}; } f64 artanF = 1; paramSayi(a, "artan", artanF); const bool artan = artanF != 0; return [anahtar, artan](AsamaBaglam& b) { asamaBaslat(b); auto& ids = b.sonuc.kimlikler; auto& sat = b.sonuc.satirlar; const bool paralel = sat.size() == ids.size() && !sat.empty(); std::vector idx(ids.size()); std::iota(idx.begin(), idx.end(), size_t{0}); // derece: 0 sayısal, 1 metin, 2 eksik/diğer — eksikler her yönde sonda auto derece = [&](u64 id, f64& s, const std::string*& m) -> int { const Deger* v = b.graf.oz(id, anahtar); if (!v) return 2; if (degerSayi(*v, s)) return 0; if (std::holds_alternative(*v)) { m = &std::get(*v); return 1; } return 2; }; std::stable_sort(idx.begin(), idx.end(), [&](size_t x, size_t y) { f64 sx = 0, sy = 0; const std::string* mx = nullptr; const std::string* my = nullptr; int dx = derece(ids[x], sx, mx), dy = derece(ids[y], sy, my); if (dx != dy) return dx < dy; if (dx == 0) return artan ? sx < sy : sx > sy; if (dx == 1) return artan ? *mx < *my : *my < *mx; return false; }); std::vector yeniId(ids.size()); std::vector>> yeniSat; if (paralel) yeniSat.resize(sat.size()); for (size_t i = 0; i < idx.size(); ++i) { yeniId[i] = ids[idx[i]]; if (paralel) yeniSat[i] = std::move(sat[idx[i]]); } ids = std::move(yeniId); if (paralel) sat = std::move(yeniSat); }; }); stageKaydetIc(d, "limit", [](const PipelineAsama& a, std::string& hata) -> AsamaYurutucu { f64 nF = 0; if (!paramSayi(a, "n", nF)) { hata = "limit: 'n' (sayı) gerekli"; return {}; } const u64 n = nF < 0 ? 0 : (u64)nF; return [n](AsamaBaglam& b) { asamaBaslat(b); if (b.sonuc.kimlikler.size() > n) b.sonuc.kimlikler.resize(n); if (b.sonuc.satirlar.size() > n) b.sonuc.satirlar.resize(n); }; }); stageKaydetIc(d, "say", [](const PipelineAsama&, std::string&) -> AsamaYurutucu { return [](AsamaBaglam& b) { asamaBaslat(b); b.sonuc.skaler = (i64)b.sonuc.kimlikler.size(); b.sonuc.skalerVar = true; b.sonuc.kimlikler.clear(); b.sonuc.satirlar.clear(); }; }); stageKaydetIc(d, "topla", [](const PipelineAsama& a, std::string& hata) -> AsamaYurutucu { std::string anahtar; if (!paramMetin(a, "anahtar", anahtar)) { hata = "topla: 'anahtar' (metin) gerekli"; return {}; } std::string islem = "sum"; paramMetin(a, "islem", islem); int kod; // 0 sum, 1 min, 2 max, 3 ort if (islem == "sum") kod = 0; else if (islem == "min") kod = 1; else if (islem == "max") kod = 2; else if (islem == "ort") kod = 3; else { hata = "topla: bilinmeyen işlem '" + islem + "' (sum/min/max/ort)"; return {}; } return [anahtar, kod](AsamaBaglam& b) { asamaBaslat(b); f64 top = 0, enAz = 0, enCok = 0; u64 adet = 0; // sayısal olmayan/eksik özellikler hesaba katılmaz for (u64 id : b.sonuc.kimlikler) { const Deger* v = b.graf.oz(id, anahtar); f64 s; if (!v || !degerSayi(*v, s)) continue; if (adet == 0) { enAz = s; enCok = s; } else { enAz = std::min(enAz, s); enCok = std::max(enCok, s); } top += s; ++adet; } f64 r = 0; // boş küme → 0 (belirlenmiş davranış) if (kod == 0) r = top; else if (kod == 1) r = enAz; else if (kod == 2) r = enCok; else if (adet) r = top / (f64)adet; b.sonuc.skaler = r; b.sonuc.skalerVar = true; b.sonuc.kimlikler.clear(); b.sonuc.satirlar.clear(); }; }); } KayitDefteri& defter() { static bool ilk = [] { cekirdekKaydet(defterHam()); return true; }(); (void)ilk; return defterHam(); } // ---- Optimizer tohumu ------------------------------------------------------- // Kural (gelecek geçişler için sabit): `limit`, `sirala` üzerinden geriye // TAŞINMAZ — sıralamadan önce kesmek sonucu değiştirir. Şu an taşıma geçişi yok. void tohumGecis(std::vector& asamalar) { std::vector yeni; yeni.reserve(asamalar.size()); for (auto& a : asamalar) { if (!yeni.empty()) { if (a.adMetin == "suz" && yeni.back().adMetin == "suz") { for (auto& k : a.kosullar) yeni.back().kosullar.push_back(std::move(k)); continue; } if (a.adMetin == "limit" && yeni.back().adMetin == "limit") { f64 x = 0, y = 0; if (paramSayi(a, "n", x) && paramSayi(yeni.back(), "n", y)) { yeni.back().param["n"] = (i64)std::min(x, y); continue; } } } yeni.push_back(std::move(a)); } asamalar = std::move(yeni); } std::vector& disGecisler() { static std::vector g; return g; } // ---- Sonuç önbelleği (LRU-vari, doğrusal tarama — sıcak yol değil) ---------- struct OnbellekGirdi { const void* graf = nullptr; u64 surum = 0, dugumUst = 0, imza = 0, tik = 0; PipelineSonuc sonuc; }; std::mutex& onbellekKilit() { static std::mutex m; return m; } std::vector& onbellek() { static std::vector v; return v; } u64 onbellekTik = 0; u64 karmaFnv(const std::string& s) { u64 h = 1469598103934665603ULL; for (unsigned char ch : s) { h ^= ch; h *= 1099511628211ULL; } return h; } // ---- JSON okuma (simdjson On-Demand — alanlar sırayla tüketilir) ------------ Deger degerOku(sj::ondemand::value v) { switch (v.type().value()) { case sj::ondemand::json_type::number: { i64 t; if (!v.get_int64().get(t)) return Deger(t); return Deger(v.get_double().value()); } case sj::ondemand::json_type::string: return Deger(std::string(v.get_string().value())); case sj::ondemand::json_type::boolean: return Deger(v.get_bool().value()); default: return Deger{}; // obje/dizi/null desteklenmiyor — çağıran hata verir } } // simdjson_result sarmalı sürüm: hata → monostate (implicit dönüşüm exception'sız // derlemede yok, MSVC C2664). Deger degerOku(sj::simdjson_result v) { sj::ondemand::value g; if (v.get(g)) return Deger{}; return degerOku(g); } std::string suzJsonOku(Pipeline& p, sj::ondemand::object nesne) { for (auto alan : nesne) { std::string k(alan.unescaped_key().value()); if (k == "iliskili") { std::string iliski, hedef; i64 yon = 0; for (auto f : alan.value().get_object()) { std::string_view fk = f.unescaped_key().value(); if (fk == "iliski") iliski = std::string(f.value().get_string().value()); else if (fk == "hedef") hedef = std::string(f.value().get_string().value()); else if (fk == "yon") yon = f.value().get_int64().value(); } if (iliski.empty()) return "suz.iliskili: 'iliski' gerekli"; p.suzIliskili(iliski, hedef, (int)yon); continue; } auto v = alan.value(); if (v.type().value() == sj::ondemand::json_type::object) { for (auto op : v.get_object()) { std::string islec(op.unescaped_key().value()); if (islec == "var") { if (op.value().get_bool().value()) p.suzVar(k); } else if (islec == "aralik") { f64 sinir[2] = {0, 0}; size_t i = 0; for (auto e : op.value().get_array()) { if (i < 2) sinir[i] = e.get_double().value(); ++i; } if (i != 2) return "suz.aralik: [enAz, enCok] bekleniyor"; p.suzAralik(k, sinir[0], sinir[1]); } else { Deger dv = degerOku(op.value()); if (std::holds_alternative(dv)) return "suz: '" + k + "' için değer okunamadı"; p.suz(k, islec, std::move(dv)); if (!p.hata().empty()) return {}; // bilinmeyen işleç — hata zaten yazıldı } } } else { Deger dv = degerOku(v); if (std::holds_alternative(dv)) return "suz: '" + k + "' için değer okunamadı"; p.suz(k, "==", std::move(dv)); } } return {}; } std::string stageJsonOku(Pipeline& p, sj::ondemand::object nesne) { for (auto alan : nesne) { std::string ad(alan.unescaped_key().value()); auto v = alan.value(); if (ad == "kaynak") { p.kaynak(std::string_view(v.get_string().value())); } else if (ad == "govdede") { p.govdede(v.get_uint64().value()); } else if (ad == "suz") { std::string h = suzJsonOku(p, v.get_object().value()); if (!h.empty()) return h; } else if (ad == "genislet") { std::string iliski, hedef; i64 yon = 0; for (auto f : v.get_object()) { std::string_view fk = f.unescaped_key().value(); if (fk == "iliski") iliski = std::string(f.value().get_string().value()); else if (fk == "hedef") hedef = std::string(f.value().get_string().value()); else if (fk == "yon") yon = f.value().get_int64().value(); } if (iliski.empty()) return "genislet: 'iliski' gerekli"; p.genislet(iliski, hedef, (int)yon); } else if (ad == "sec") { std::vector anahtarlar; for (auto e : v.get_array()) anahtarlar.emplace_back(std::string_view(e.get_string().value())); p.sec(std::move(anahtarlar)); } else if (ad == "sirala") { std::string anahtar; bool artan = true; for (auto f : v.get_object()) { std::string_view fk = f.unescaped_key().value(); if (fk == "anahtar") anahtar = std::string(f.value().get_string().value()); else if (fk == "artan") artan = f.value().get_bool().value(); } if (anahtar.empty()) return "sirala: 'anahtar' gerekli"; p.sirala(anahtar, artan); } else if (ad == "limit") { p.limit((u32)v.get_uint64().value()); } else if (ad == "say") { p.say(); // değeri ({} vb.) yok sayılır } else if (ad == "topla") { std::string anahtar, islem = "sum"; for (auto f : v.get_object()) { std::string_view fk = f.unescaped_key().value(); if (fk == "anahtar") anahtar = std::string(f.value().get_string().value()); else if (fk == "islem") islem = std::string(f.value().get_string().value()); } if (anahtar.empty()) return "topla: 'anahtar' gerekli"; p.topla(anahtar, islem); } else { // Registry'de kayıtlı plugin stage: parametreler genel çanta olarak okunur if (!stageVar(ad)) return "Bilinmeyen pipeline stage: '" + ad + "'"; std::unordered_map prm; if (v.type().value() == sj::ondemand::json_type::object) { for (auto f : v.get_object()) { std::string fk(f.unescaped_key().value()); Deger dv = degerOku(f.value()); if (std::holds_alternative(dv)) return "'" + ad + "': parametre '" + fk + "' skaler olmalı"; prm.emplace(std::move(fk), std::move(dv)); } } else { Deger dv = degerOku(v); if (!std::holds_alternative(dv)) prm.emplace("deger", std::move(dv)); } p.asama(ad, std::move(prm)); } if (!p.hata().empty()) return {}; } return {}; } } // namespace // ---- Serbest API ------------------------------------------------------------ void asamaBaslat(AsamaBaglam& b) { if (b.baslatildi) return; b.baslatildi = true; b.sonuc.kimlikler.clear(); for (u64 k = 1; k <= b.graf.dugumUst(); ++k) if (b.graf.dugum(k)) b.sonuc.kimlikler.push_back(k); } void stageKaydet(std::string_view ad, AsamaFabrika fabrika) { stageKaydetIc(defter(), ad, std::move(fabrika)); } bool stageVar(std::string_view ad) { auto& d = defter(); std::lock_guard kilit(d.kilit); return d.indeks.count(std::string(ad)) > 0; } void optimizasyonGecisiEkle(OptimizasyonGecisi gecis) { disGecisler().push_back(std::move(gecis)); } // ---- PipelineSonuc ---------------------------------------------------------- std::string PipelineSonuc::jsonYaz() const { std::string c = "{"; if (!hata.empty()) { c += "\"hata\":"; jsonKac(c, hata); c += '}'; return c; } c += "\"kimlikler\":["; for (size_t i = 0; i < kimlikler.size(); ++i) { if (i) c += ','; c += std::to_string(kimlikler[i]); } c += ']'; if (!satirlar.empty()) { c += ",\"satirlar\":["; for (size_t i = 0; i < satirlar.size(); ++i) { if (i) c += ','; c += '{'; for (size_t j = 0; j < satirlar[i].size(); ++j) { if (j) c += ','; jsonKac(c, satirlar[i][j].first); c += ':'; jsonDeger(c, satirlar[i][j].second); } c += '}'; } c += ']'; } if (skalerVar) { c += ",\"skaler\":"; jsonDeger(c, skaler); } c += '}'; return c; } // ---- Pipeline: fluent kurulum ----------------------------------------------- PipelineAsama& Pipeline::asamaEkle(std::string_view ad) { if (derlendi_ && hata_.empty()) hata_ = "Pipeline derlendikten sonra değiştirilemez"; asamalar_.emplace_back(); PipelineAsama& a = asamalar_.back(); a.adMetin = std::string(ad); return a; } Pipeline& Pipeline::kaynak(std::string_view tip) { asamaEkle("kaynak").param.emplace("tip", std::string(tip)); return *this; } Pipeline& Pipeline::govdede(u64 govdeVarlik) { asamaEkle("govdede").param.emplace("govde", (i64)govdeVarlik); return *this; } Pipeline& Pipeline::suz(std::string_view anahtar, std::string_view islec, Deger v) { AsamaKosul k; if (!islecCoz(islec, k.tur)) { if (hata_.empty()) hata_ = "suz: bilinmeyen işleç '" + std::string(islec) + "'"; return *this; } k.anahtar = std::string(anahtar); k.deger = std::move(v); asamaEkle("suz").kosullar.push_back(std::move(k)); return *this; } Pipeline& Pipeline::suzVar(std::string_view anahtar) { AsamaKosul k; k.tur = AsamaKosul::Tur::Var; k.anahtar = std::string(anahtar); asamaEkle("suz").kosullar.push_back(std::move(k)); return *this; } Pipeline& Pipeline::suzAralik(std::string_view anahtar, f64 enAz, f64 enCok) { AsamaKosul k; k.tur = AsamaKosul::Tur::Aralik; k.anahtar = std::string(anahtar); k.enAz = enAz; k.enCok = enCok; asamaEkle("suz").kosullar.push_back(std::move(k)); return *this; } Pipeline& Pipeline::suzIliskili(std::string_view iliskiTip, std::string_view hedefTip, int yon) { AsamaKosul k; k.tur = AsamaKosul::Tur::Iliskili; k.anahtar = std::string(iliskiTip); k.hedefTip = std::string(hedefTip); k.yon = yon; asamaEkle("suz").kosullar.push_back(std::move(k)); return *this; } Pipeline& Pipeline::genislet(std::string_view iliskiTip, std::string_view hedefTip, int yon) { PipelineAsama& a = asamaEkle("genislet"); a.param.emplace("iliski", std::string(iliskiTip)); if (!hedefTip.empty()) a.param.emplace("hedef", std::string(hedefTip)); if (yon) a.param.emplace("yon", (i64)yon); return *this; } Pipeline& Pipeline::sec(std::vector anahtarlar) { asamaEkle("sec").anahtarlar = std::move(anahtarlar); return *this; } Pipeline& Pipeline::sirala(std::string_view anahtar, bool artan) { PipelineAsama& a = asamaEkle("sirala"); a.param.emplace("anahtar", std::string(anahtar)); a.param.emplace("artan", artan); return *this; } Pipeline& Pipeline::limit(u32 n) { asamaEkle("limit").param.emplace("n", (i64)n); return *this; } Pipeline& Pipeline::say() { asamaEkle("say"); return *this; } Pipeline& Pipeline::topla(std::string_view anahtar, std::string_view islem) { PipelineAsama& a = asamaEkle("topla"); a.param.emplace("anahtar", std::string(anahtar)); a.param.emplace("islem", std::string(islem)); return *this; } Pipeline& Pipeline::asama(std::string_view ad, std::unordered_map param) { asamaEkle(ad).param = std::move(param); return *this; } // ---- Pipeline: JSON --------------------------------------------------------- Pipeline Pipeline::jsonDanKur(const std::string& json) { Pipeline p; std::string metin = json; metin.reserve(metin.size() + sj::SIMDJSON_PADDING); try { sj::ondemand::parser ayristirici; sj::padded_string_view pv(metin.data(), metin.size(), metin.capacity()); sj::ondemand::document belge; auto err = ayristirici.iterate(pv).get(belge); if (err) { p.hata_ = std::string("Pipeline JSON hatası: ") + sj::error_message(err); return p; } bool pipelineVar = false; for (auto alan : belge.get_object()) { std::string_view ad = alan.unescaped_key().value(); if (ad == "surum") { i64 s = alan.value().get_int64().value(); if (s != 1) { p.hata_ = "Pipeline JSON: desteklenmeyen sürüm " + std::to_string(s); return p; } } else if (ad == "pipeline") { pipelineVar = true; for (auto eleman : alan.value().get_array()) { std::string h = stageJsonOku(p, eleman.get_object().value()); if (!h.empty()) { p.hata_ = h; return p; } if (!p.hata_.empty()) return p; } } // bilinmeyen kök alanlar ileri uyumluluk için yok sayılır } if (!pipelineVar && p.hata_.empty()) p.hata_ = "Pipeline JSON: 'pipeline' dizisi yok"; } catch (const sj::simdjson_error& e) { p.hata_ = std::string("Pipeline JSON hatası: ") + e.what(); } return p; } // ---- Pipeline: derleme + yürütme -------------------------------------------- std::string Pipeline::imza() const { std::string c; for (const auto& a : asamalar_) { c += a.adMetin; c += '('; std::vector> ps; ps.reserve(a.param.size()); for (const auto& [k, v] : a.param) ps.emplace_back(k, &v); std::sort(ps.begin(), ps.end(), [](const auto& x, const auto& y) { return x.first < y.first; }); for (const auto& [k, v] : ps) { c += k; c += '='; jsonDeger(c, *v); c += ';'; } for (const auto& k : a.kosullar) { c += 'k'; c += std::to_string((int)k.tur); c += ':'; c += k.anahtar; c += ':'; c += k.hedefTip; c += ':'; jsonDeger(c, k.deger); c += ':'; c += std::to_string(k.enAz); c += ':'; c += std::to_string(k.enCok); c += ':'; c += std::to_string(k.yon); c += ';'; } for (const auto& s : a.anahtarlar) { c += s; c += ','; } c += ')'; } return c; } bool Pipeline::derle() { if (derlendi_) return hata_.empty(); if (!hata_.empty()) return false; tohumGecis(asamalar_); for (const auto& g : disGecisler()) g(asamalar_); yurutucular_.clear(); yurutucular_.reserve(asamalar_.size()); auto& d = defter(); for (auto& a : asamalar_) { AsamaFabrika fabrika; { std::lock_guard kilit(d.kilit); auto it = d.indeks.find(a.adMetin); if (it != d.indeks.end()) { a.ad = it->second; fabrika = d.fabrikalar[it->second - 1]; } } if (!fabrika) { hata_ = "Bilinmeyen pipeline stage: '" + a.adMetin + "'"; return false; } std::string fabrikaHata; AsamaYurutucu y = fabrika(a, fabrikaHata); if (!fabrikaHata.empty() || !y) { hata_ = fabrikaHata.empty() ? ("Stage kurulamadı: '" + a.adMetin + "'") : fabrikaHata; return false; } yurutucular_.push_back(std::move(y)); } imzaKarma_ = karmaFnv(imza()); derlendi_ = true; return true; } PipelineSonuc Pipeline::calistir(const GrafDeposu& graf) { PipelineSonuc s; if (!derle()) { s.hata = hata_; return s; } const void* adres = &graf; const u64 surum = graf.surum(); const u64 dugumUst = graf.dugumUst(); { std::lock_guard kilit(onbellekKilit()); for (auto& g : onbellek()) { if (g.graf == adres && g.surum == surum && g.dugumUst == dugumUst && g.imza == imzaKarma_) { g.tik = ++onbellekTik; PipelineSonuc kopya = g.sonuc; kopya.onbellekten = true; return kopya; } } } AsamaBaglam b{graf, s}; for (auto& y : yurutucular_) { y(b); if (!s.hata.empty()) return s; // hatalı sonuç önbelleğe girmez } { std::lock_guard kilit(onbellekKilit()); auto& v = onbellek(); if (v.size() >= onbellekKapasite && !v.empty()) { size_t enEski = 0; for (size_t i = 1; i < v.size(); ++i) if (v[i].tik < v[enEski].tik) enEski = i; v.erase(v.begin() + (ptrdiff_t)enEski); } v.push_back({adres, surum, dugumUst, imzaKarma_, ++onbellekTik, s}); } return s; } void Pipeline::onbellekTemizle() { std::lock_guard kilit(onbellekKilit()); onbellek().clear(); } } // namespace fiko::zeka