From f7467f18b3d826a0be83ba9dd3e053f19e1252e8 Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Sun, 14 Jun 2026 17:56:42 +0300 Subject: [PATCH 01/28] docs: frontend tasarim kararlari, transkript ve yol haritasi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Symbol table + semantic analiz + optimizasyon framework tasarim oturumunun ciktilari: - adr-frontend-analiz.md: ADR-006..014 (cok-asamali frontend, analiz/ optimizasyon ayrimi, optimizasyon konumu, fixpoint, tip sistemi, scope/forward-reference, ExpressionNode/StatementNode, analiz verisi yeri, dil kapsami) — her karar gerekcesiyle. - transkript-frontend-tasarim.md: oturum akiscinin sadik transkripti. - roadmap-frontend.md: dosya-dosya uygulama plani (Faz 0..4). --- docs/adr-frontend-analiz.md | 389 ++++++++++++++++++++++++++++ docs/roadmap-frontend.md | 179 +++++++++++++ docs/transkript-frontend-tasarim.md | 214 +++++++++++++++ 3 files changed, 782 insertions(+) create mode 100644 docs/adr-frontend-analiz.md create mode 100644 docs/roadmap-frontend.md create mode 100644 docs/transkript-frontend-tasarim.md diff --git a/docs/adr-frontend-analiz.md b/docs/adr-frontend-analiz.md new file mode 100644 index 0000000..f0194fb --- /dev/null +++ b/docs/adr-frontend-analiz.md @@ -0,0 +1,389 @@ +# saQut Derleyici — Frontend & Semantic Analiz Karar Kaydı (ADR-006 …) + +> Bu belge, `docs/fikirler.md`'deki ADR-001…005'in **devamıdır**. Orada backend +> stratejisi, parser mimarisi, header-only tercihi, token sistemi ve IR tasarımı +> kararlaştırılmıştı. Bu belge ise **frontend'in tamamlanması** — symbol table, +> semantic analiz ve optimizasyon framework'ü — etrafında alınan kararları, +> **neden** alındıklarını, elenen alternatifleri ve gelecekteki sonuçlarını kaydeder. +> +> Bu kararlar bir tasarım oturumunda (kullanıcı + asistan) tartışılarak alındı. +> Tartışmanın tam akışı için bkz. `docs/transkript-frontend-tasarim.md`. +> Uygulama planı için bkz. `docs/roadmap-frontend.md`. + +--- + +## ADR-006: Çok-Aşamalı (Multi-Pass) Frontend Mimarisi + +### Bağlam + +Derleyici tek bir monolitik geçişle çalışmaz; lexing, parsing, analiz, +optimizasyon, kod üretimi gibi **birbirinden bağımsız aşamalardan** oluşur. +saQut'un "alet çantası" (toolbox) felsefesi gereği bu aşamaların her biri: +- bağımsız çalışabilmeli, +- net bir girdi/çıktı sözleşmesine sahip olmalı, +- gerektiğinde çoğaltılabilmeli (projenin amacına sadık kalarak). + +CLI komutları (`tokens`, `ast`, `symbols`, …) zaten bu aşama-modülü +yapısının dışa vurumudur — her komut bir aşamanın çıktısını gösterir. + +### Değerlendirilen Yaklaşımlar + +#### Tek geçişli (single-pass) parser+analiz +- **+** Basit, hızlı. +- **−** Forward reference (ileri başvuru) imkânsızlaşır; her şey tanımdan + önce bilinmek zorunda kalır. +- **−** Analiz ve syntax iç içe girer, test edilemez, bakımı zor. + +#### Çok geçişli (multi-pass) — net aşamalar +- **+** Her aşama tek bir iş yapar, ayrı ayrı test edilir. +- **+** Forward reference mümkün olur. +- **+** Aşamalar incelenebilir (`saqut ast`, `saqut symbols` …). +- **−** Daha fazla kod ve veri yapısı; aşamalar arası sözleşme tasarımı gerekir. + +### Karar + +✅ **Çok-aşamalı frontend.** Aşamalar şu üç katmana ayrılır (klasik derleyici +mimarisi): + +``` +FRONTEND MIDDLE-END BACKEND +lexer → token → optimizasyon IR lowering → +parser → AST → (opsiyonel, iteratif, kod üretimi +symbol table → toggle'lı, ortak (C transpile / +semantic analiz gösterim üstünde) QBE / JIT) +(annotated AST) +``` + +- **Pass 1 (Syntax):** token → ham AST. (Büyük ölçüde mevcut.) +- **Pass 2 (Symbol):** AST → SymbolTable (scope'lu, iki-geçişli — bkz. ADR-011). +- **Pass 3 (Semantic / "ASTyi derinleştir"):** symbol table + AST kullanılarak + her node zenginleştirilir (tip, symbol bağı, erişilebilirlik, reference sayısı). + +"Parser ve symbol hikayesini bitirmek" = **frontend'i bitirmek.** Optimizasyon +ayrı bir katmandır (middle-end), backend'ler bu ortak çıktıdan beslenir. + +**Neden bu katmanlama?** Birden çok backend (C transpile, QBE, JIT) planlandığı +için, ortak işler (analiz, optimizasyon) **bir kez** ortak katmanda yapılmalı; +yoksa her backend aynı optimizasyonu yeniden yazar. + +--- + +## ADR-007: Analiz (Annotation) ile Optimizasyon (Transformation) Ayrımı + +### Bağlam + +`docs/fikirler.md` ve `docs/todo.md`'nin temel prensibi: **"AST bellek canavarı. +Hiçbir bilgi atılmaz."** Aynı zamanda constant folding (`1+2` → `3`), dead code +elimination gibi optimizasyonlar isteniyor. Bu ikisi doğrudan çelişir gibi +görünür: optimizasyon AST'yi bozarsa, kaynak kodun izdüşümü kaybolur ve +`saqut ast` artık kullanıcının yazdığını değil, optimize edilmiş hali gösterir. + +Ayrıca kritik bir kullanıcı gereksinimi belirlendi: **kullanıcı, AST'nin veya +sembol tablosunun optimizasyondan önceki ve sonraki halini ayrı ayrı görebilmeli.** + +### İki Kavram + +- **Analiz (annotation) = programın gerçekleri.** "Bu node sabit, değeri 3", + "bu kod erişilemez", "bu ifadenin tipi int", "bu değişken 2 kez kullanıldı". + Bunlar **değişiklik değil, tespittir.** Backend'den bağımsızdır. +- **Optimizasyon (transformation) = ağacı/IR'ı gerçekten değiştirmek.** + `1+2`'yi `3` ile değiştirmek, ölü kodu silmek. + +### Karar + +✅ **İki kavram net ayrılır:** + +1. **Analiz, orijinal AST'nin üstüne yerinde işaretleme yapar** (node'lara tip, + symbol bağı, erişilebilirlik, constness ekler). Ağacı **bozmaz**, zenginleştirir. + Orijinal AST hâlâ kaynak kodun tam izdüşümüdür. + +2. **Optimizasyon dönüşümü, ağacın bir KOPYASI (klon) üzerinde yapılır.** + Orijinal analizli AST = "öncesi"; klon + dönüştürülmüş AST = "sonrası". + Ağaç klonlamak ucuz ve basittir, yalnızca `--optimized` istendiğinde yapılır. + +**Sonuç:** Hem "bellek canavarı" felsefesi korunur (orijinal AST her şeyi tutar), +hem optimizasyon yapılır, hem de öncesi/sonrası ayrı ayrı incelenebilir. + +``` +saqut ast file.sqt → ham + annotate edilmiş AST (1+2 burada durur) +saqut ast file.sqt --optimized → klon, folding uygulanmış (3 var) +``` + +--- + +## ADR-008: Optimizasyon Konumu — AST mı, IR mı? + +### Bağlam + +"Optimizasyonu IR/derleme zamanında mı yapmalıyız, yoksa AST aşamasında mı?" +sorusu tartışıldı. İki uç yaklaşım var: + +- **AST seviyesi:** kaynak-seviyesi, dile yakın, incelenebilir. +- **IR seviyesi:** açık kontrol-akış grafiği (CFG), dataflow analizi için uygun + (LLVM modeli). + +### Karar + +✅ **Hibrit, optimizasyon türüne göre bölünür:** + +- **Kaynak-seviyesi, ağaç-yerel optimizasyonlar** (constant folding, ölü kod + işaretleme, unused variable) → **AST'de** yapılır. Çünkü: + 1. Dil JS gibi basit; ağır optimizasyona ihtiyaç yok. + 2. Backend-bağımsız → C transpile, QBE, JIT üçü birden faydalanır. + 3. İncelenebilir kalır (`saqut ast --optimized`) — projenin varlık sebebi. + +- **CFG/dataflow gerektiren optimizasyonlar** ("bir kez atanıp bir kez + kullanılan değişken" = copy propagation, common subexpression elimination, + loop optimizasyonları) → **IR'de** yapılır, IR olgunlaşınca ertelenir. + Çünkü bunlar açık kontrol akışı ister, ağaçta yapmak işkencedir. + +**Neden backend'e bırakmıyoruz?** 3 backend varsa, optimizasyon backend'e +konulursa 3 kez yazılır. Ortak katmanda (middle-end) bir kez yazılır. + +--- + +## ADR-009: Optimizasyon Pass Yönetimi — Sabit Sayı Değil, Fixpoint + +### Bağlam + +Optimizasyon adımları birbirini tetikler: constant folding yeni ölü kod doğurur, +dead code elimination yeni kullanılmayan değişken doğurur. Tek geçişte zincirleme +fırsatlar kaçırılır. "5 pass mı, 10 pass mı çalıştıralım?" sorusu yanlış kurgu. + +> **Not:** Buradaki "pass", ADR-006'daki derleyici aşamalarından (lexing/parsing +> gibi makro-aşamalar) farklıdır. Burada "pass" = tek bir optimizasyon adımının +> AST üzerindeki bir gezisidir. + +### Karar + +✅ **Fixpoint döngüsü.** Önceden belirlenmiş sayıda değil; bir pass havuzu, +**hiçbir pass değişiklik yapmayana kadar** döngüde çalışır. Belki 2 tur sürer, +belki 7 — kodun kendisi belirler. + +- Her **tur** bir öncekinden daha az iş yapar (giderek azalan değişiklik), ta ki + sıfır değişiklikle stabilize olana kadar. +- Pass'ler `CompilerConfig` ile tek tek açılıp kapatılabilir. +- `OptimizationManager` pass listesini tutar, sırayı ve fixpoint döngüsünü yönetir. + +> Düzeltme notu: "Her pass bir öncekinden daha kolay" sezgisi yanlıştır. Doğrusu: +> her **tur** daha az değişiklik yapar. Analiz pass'leri (symbol table, type check) +> "kolaylaşmaz"; onlar bir kez çalışır. + +--- + +## ADR-010: Tip Sistemi Tasarımı + +### Bağlam + +Dil **tipli** olacak. Şu anda `varType`/`returnType` AST'de yalnızca +`std::string`. Tip kontrolünü string karşılaştırmasıyla yazmak kırılgandır ve +`int[]`, `struct Point`, fonksiyon tipi gelince baştan yazmayı gerektirir. + +### Alınan Kararlar + +✅ **Minimal ama genişletilebilir `Type` sınıfı** (`src/core/type.hpp`): +- `kind`: `Primitive / Array / Struct / Function / Error`. +- Primitifler: `int, float, double, char, string, bool, void`. +- `Array` → eleman tipi (boyut tipin parçası DEĞİL — bkz. aşağı). +- `Function` → dönüş tipi + parametre tipleri. +- İleride `Pointer`, `Generic` eklenebilir. + +✅ **`Error` tipi şart.** Tip hatası olduğunda node'a `Error` atanır; böylece +ardışık sahte hatalar üretilmez (tek hata, tek mesaj). + +✅ **Gizli (implicit) dönüşüm YOK.** `int → float` otomatik olmaz; her şey açık. +- **Tek istisna:** sabit ifadelerde (constant folding) — `int a = 5 / 2;` → `2`. + Sabitler üzerinde küçük analiz/hesap yapılır. + +✅ **Tip çıkarımı (auto/var) YOK.** Her şey açıkça tiplenir. `auto` keyword'ü +yok sayılır. Sebep: basitlik, öngörülebilirlik, kafa karışıklığını önlemek. + +✅ **Array tip temsili: `int[]` (boyut tipte yok).** `int[]` sadece "int dizisi"; +boyut tip eşitliğine girmez (JS gibi). Tip kontrolü basit kalır. + +**Neden genişletilebilir?** "Bu dilin geleceğini bilmiyoruz; beklenenden popüler +de olabilir, yıllarca repolarda tozlanabilir de." Temel sağlam ve büyümeye açık +olmalı. + +--- + +## ADR-011: Scope ve Forward Reference Kuralları + +### Bağlam + +Dil "Java gibi forward reference, C gibi syntax, başta OOP yok" olarak +tasarlandı (JS yalnızca **syntax basitliği** örneği olarak verildi; JS'in kötü +yanları — null/undefined ikiliği, var hoisting — **alınmıyor**). + +### "Hoisting" nedir? + +Bir tanımın, yazıldığı satırdan **önce de** görünür olması (scope'un tepesine +"kaldırılmış" gibi). + +### Karar + +✅ **Asimetrik kurallar (tam olarak Java'nın davranışı):** + +- **Üst seviye (global): tam forward reference (hoisting var).** Fonksiyonlar, + global değişkenler, struct'lar sırasından bağımsız her yerde görünür. + ``` + int main() { return kare(5); } // kare aşağıda ama görünür → OK + int kare(int n) { return n * n; } + ``` + **Neden güvenli?** `main`'in gövdesi tanımlandığı anda çalışmaz; çağrılınca + çalışır, o ana kadar `kare` zaten vardır. Tanımların çalışma sırası yoktur. + +- **Lokal (fonksiyon içi): declare-before-use (hoisting YOK).** + ``` + int main() { + int x = y + 1; // HATA: y henüz tanımlı değil + int y = 5; + } + ``` + **Neden?** Lokal değişkenin bir çalışma sırası ve değeri vardır; tanımdan önce + kullanmak, var olmayan/değeri olmayan bir şeyi kullanmaktır. Local hoisting + olsaydı isim olur ama değeri çöp/undefined olurdu (JS `var` derdi) — kaçınılan + durum. + +**Asimetri tutarsızlık değildir:** global tanımlar yerinde çalışmaz (forward ref +güvenli), lokal değişkenlerin sırası ve değeri vardır (declare-before-use güvenli). +Bu, Java/C#'ın da davranışıdır. + +✅ **Duplicate kesinlikle yasak.** Aynı scope'ta aynı isimli iki +değişken/fonksiyon tanımlanamaz → diagnostic. (Overloading yok.) + +✅ **Shadowing serbest.** İç scope, dış scope'u gölgeleyebilir (hata değil). + +✅ **Scope oluşturan node'lar:** `Program` (global), `FunctionDecl` (parametreler), +`Block`, `for`/`while` (init değişkeni döngüye ait; döngü dışında görünmez). +Her katman bir namespace tutar; değişken bulunamazsa bir üst katmanda aranır. + +### Symbol Table'ın İki Geçişi + +✅ **Sadece üst seviyede iki geçiş gerekir:** +- **Geçiş 1:** tüm üst-seviye tanımları (fonksiyon imzaları, struct isim+alanları, + global değişkenler) global scope'a hoist et. +- **Geçiş 2:** gövdelere in; lokal'leri declare-before-use ile topla, her + `Identifier`'ı çöz, reference ekle. +- **Fonksiyon içi tek geçiş yeter** (lokal'de forward ref yok). "Öncesi/sonrası" + derdi yalnızca global'ler içindir, onu da Geçiş 1 çözer (global'ler en baştan + tamamen doludur). + +--- + +## ADR-012: ExpressionNode / StatementNode Ara Tabanları + +### Bağlam + +Şu anda tüm AST node'ları doğrudan `ASTNode`'dan türüyor; "ifade" (değer üreten) +ve "deyim" (iş yapan ama değer olmayan) ayrımı yok. Tipli bir dilde yalnızca +**ifadelerin** tipi vardır: `5 + 3` → int; `if (...) {...}` → tipi yok. + +`resolvedType` alanını nereye koyacağımız bir tasarım kararı. Seçenekler: +- (a) `ASTNode` tabanına koy → her node'da olur, `if`/`while`'da boşa durur. +- (b) `ExpressionNode`/`StatementNode` ara tabanları → alanlar doğru yere oturur. +- (c) Yan-tablo `map` → AST temiz ama dolaylı/karmaşık. + +### Karar + +✅ **(b) İki ara taban eklenir:** +- `ExpressionNode : ASTNode` → `resolvedType`, `isConstant`, `foldedValue`. +- `StatementNode : ASTNode` → `isReachable` (ölü kod analizi için). + +``` +ASTNode + ├─ ExpressionNode (resolvedType, isConstant, foldedValue) + │ ├─ LiteralNode / BinaryExpressionNode / IdentifierNode / CallExpressionNode … + └─ StatementNode (isReachable) + ├─ IfStatementNode / WhileStatementNode / ReturnStatementNode / BlockNode … +``` + +**Kazanımlar:** +1. `resolvedType` yalnızca tip taşıyabilen node'larda olur. +2. Parser/analiz "burası ifade olmalı" diyebilir (örn. `if` koşulu bir + `ExpressionNode` olmalı, fonksiyon argümanı `ExpressionNode` olmalı). + +**Önemli:** Bu karar, "her şey AST'de" felsefesini bozmaz (bkz. ADR-013); yalnızca +analiz alanlarını doğru node sınıflarına dağıtır. Node cpp dosyaları zaten boştu; +bu tabanlar onları doldururken ekleniyor. Maliyeti şimdi düşük, sonra yüksek +olurdu. + +--- + +## ADR-013: Analiz Verisi Nerede Yaşar — Her Şey AST'de + +### Bağlam + +İki model: (1) her şey AST node'larının üstünde; (2) AST temiz, analiz sonuçları +ayrı yan-tablolarda. + +- **Her şey AST'de:** tek doğruluk kaynağı, gezinmesi kolay (`node->type`), + kullanıcının zihinsel modeli, boş node class'larını doldurur. Ancak öncesi/ + sonrası için ağacı klonlamak gerekir. +- **Temiz AST + yan-tablolar:** AST sade kalır, çoklu bağımsız analiz mümkün; + ancak dolaylılık ve karmaşıklık artar, "node class'larını doldur" isteğine ters. + +### Karar + +✅ **Her şey AST node'larının üstünde** (kullanıcının modeli): +- **Analiz (tip, constness, erişilebilirlik) = node'lara yerinde işaretlenir.** +- **Optimizasyon dönüşümü = ağacın klonunda yapılır** (ADR-007), böylece + öncesi/sonrası korunur. + +✅ **Önemli ayrım — "kaç kez kullanıldı" bilgisi node'da değil, Symbol'da:** +- `IdentifierNode` → işaret ettiği `Symbol`'a pointer tutar. +- `Symbol` → o değişkenin tüm referanslarının listesini + sayısını tutar. +- `ExpressionNode` → kendi sonuç tipini, sabit olup olmadığını tutar. + +Sebep: kullanım sayısı **değişkene** aittir, tek bir kullanım node'una değil. + +> **Pointer notu:** Burada ve genel olarak derleyici **içinde** pointer serbestçe +> kullanılır (Symbol bağları, parent pointer'lar vb.). Kullanıcıya sunulan +> **dilde** pointer syntax'ı (`*`, `&`) yoktur — bkz. ADR-014. + +--- + +## ADR-014: Dil Kapsamı ve Özellik Kararları + +### Karar — Başlangıç Dili (v0) + +| Özellik | Karar | Not | +|---|---|---| +| Pointer (kullanıcı syntax'ı `*`/`&`) | ❌ Yok | Ama derleyici/runtime **içeride** pointer'ı sonuna kadar kullanır | +| Tuple / Generic (``) | ❌ Yok | | +| Class / OOP | ❌ Yok (başta) | `class` keyword'ü yok sayılır | +| Struct | ✅ Var | `struct A { B bVar }` olur (B başka yerde tanımlı); recursive define yok | +| Array | ✅ `int[]` | Dinamik yönde; runtime bellek modeli ertelendi | +| Fonksiyonlar | ✅ Tipli | Dönüş + parametre tipleri zorunlu | +| `auto` / tip çıkarımı | ❌ Yok | Her şey açık tipli | +| Gizli int↔float dönüşümü | ❌ Yok | Sadece sabit folding'de istisna | + +### Dinamik Array'in Bellek Yükümlülüğü (Gelecek Notu) + +`int[]` büyüyebilen array = heap + bir yönetim stratejisi gerektirir. Bu gerçek +bir yükümlülüktür ama **frontend'i bloklamaz** ve kolay yolu vardır: + +- **Frontend:** yalnızca "bu int dizisi" bilgisini ister; bellek modelinden habersiz. +- **C transpile backend (ilk backend):** `int[]` → C'de `struct {int* data; size_t len, cap;}`, + `malloc/realloc/free` ile yönetilir. Bellek yönetimi C'den hazır gelir. +- **JIT backend:** bellek yönetimini kendi yapmaz; minik bir runtime kütüphanesi + (`array_new`, `array_push`, `array_free`) olur, JIT bunlara **call** emit eder. +- **Yönetim stratejisi (ne zaman free):** en basiti scope-tabanlı ownership + (array'i tutan değişken scope'tan çıkınca free). GC gerekmez. Runtime'a + gelince kararlaştırılır. + +--- + +## Kararların Özet Tablosu + +| ADR | Konu | Karar | +|---|---|---| +| 006 | Frontend mimarisi | Çok-aşamalı; frontend/middle-end/backend katmanları | +| 007 | Analiz vs optimizasyon | Analiz yerinde işaretler; optimizasyon klonda dönüştürür | +| 008 | Optimizasyon konumu | Basitler AST'de, dataflow gerektirenler IR'de | +| 009 | Pass yönetimi | Fixpoint döngüsü, toggle'lı | +| 010 | Tip sistemi | Minimal+genişletilebilir Type; gizli dönüşüm yok; Error tipi | +| 011 | Scope/forward ref | Global'de forward ref, lokal'de declare-before-use (Java gibi) | +| 012 | Node hiyerarşisi | ExpressionNode / StatementNode ara tabanları | +| 013 | Analiz verisi yeri | Her şey AST'de; ref-count Symbol'da | +| 014 | Dil kapsamı | Pointer/class/generic yok; struct+array+tipli fonksiyon var | diff --git a/docs/roadmap-frontend.md b/docs/roadmap-frontend.md new file mode 100644 index 0000000..05479ca --- /dev/null +++ b/docs/roadmap-frontend.md @@ -0,0 +1,179 @@ +# saQut Frontend Yol Haritası — Symbol Table + Semantic Analiz + Optimizasyon + +> Bu belge, frontend'i tamamlamaya yönelik dosya-dosya uygulama planıdır. +> Kararların gerekçeleri: `docs/adr-frontend-analiz.md` (ADR-006…014). +> Tartışma akışı: `docs/transkript-frontend-tasarim.md`. +> +> **İlke:** Sıralama katıdır — her faz bir öncekine dayanır. Her faz sonunda +> mevcut örneklerle (`examples/Final.sqt`, `examples/source.sqt`) ve CLI +> komutlarıyla doğrulama yapılır; regresyon olmamalıdır. Kod temiz, anlaşılır ve +> yorum satırlarıyla takip edilebilir olmalıdır (header-only tarzı korunur, +> bkz. ADR-003). + +--- + +## Genel Bakış + +``` +Faz 0 Temeller Type sınıfı + Diagnostic modülü + Hata kataloğu +Faz 1 AST Refactor ExpressionNode/StatementNode + analiz alanları +Faz 2 Symbol Table Symbol + Scope + SymbolTable + iki-geçişli toplama +Faz 3 Semantic Analiz Tip kontrolü + yapısal doğrulama (diagnostic'e basar) +Faz 4 Optimizasyon Pass manager (fixpoint) + constant folding + dead code +``` + +Katman eşlemesi (ADR-006): +- **Frontend:** Faz 0–3 +- **Middle-end:** Faz 4 +- **Backend:** bu yol haritasının dışında (C transpile → QBE → JIT, ADR-001) + +--- + +## Faz 0 — Temeller (Type + Diagnostic + Hata Kataloğu) + +**Bağımlılık:** yok. **Hedef:** her şeyin üstüne kurulacağı temel veri yapıları. +İlgili ADR: 010 (Type), 013 (Diagnostic). + +### Dosyalar + +| Dosya | İçerik | +|---|---| +| `src/core/type.hpp` | `Type` sınıfı. `enum class TypeKind { Primitive, Array, Struct, Function, Error }`. Primitif alt-tipleri: `int, float, double, char, string, bool, void`. Alanlar: array için `elementType`, function için `returnType`+`paramTypes`, struct için `structName`. Metotlar: `equals(const Type&)`, `toString()`, `toJson()`, factory'ler (`Type::primitive(...)`, `Type::array(...)`, `Type::error()`). | +| `src/diagnostic/diagnostic.hpp` | `enum class DiagLevel { Error, Warning, Note, Hint }`. `struct Diagnostic { DiagLevel level; std::string code; SourceLocation loc; std::string message; std::string hint; }`. **Hata kataloğu** (sabitler/enum): bkz. aşağı. | +| `src/diagnostic/diagnostic_engine.hpp` | `DiagnosticEngine`: `report(Diagnostic)`, `hasErrors()`, `errorCount()`, `printAll(std::ostream&)`, `toJson()`. Diagnostic'leri biriktirir; durdurma kararını pipeline verir (tüm hatalar toplanır, sonra raporlanır — ADR-013). | + +### Hata Kataloğu (baştan belirlenir) + +| Kod | Anlam | Hangi fazda üretilir | +|---|---|---| +| `E001` | Tanımsız değişken/isim | Faz 2/3 | +| `E002` | Aynı scope'ta çift tanım | Faz 2 | +| `E003` | Tip uyuşmazlığı | 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 | +| `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 | + +*(Liste uygulamada genişleyebilir; yeni hatalar buraya eklenir.)* + +### Doğrulama +- `Type::equals` / `toString` birim testleri. +- `DiagnosticEngine` topla → `printAll` çıktısı doğru sıralı. + +--- + +## Faz 1 — AST Refactor (ExpressionNode / StatementNode + analiz alanları) + +**Bağımlılık:** Faz 0 (Type). **Hedef:** node hiyerarşisini ifade/deyim olarak +ayır, analiz alanlarını ekle. İlgili ADR: 012, 013. + +### Dosyalar + +| Dosya | Değişiklik | +|---|---| +| `src/parser/ast_node.hpp` | İki ara taban ekle: `class ExpressionNode : public ASTNode { Type resolvedType; bool isConstant=false; /* foldedValue */ }` ve `class StatementNode : public ASTNode { bool isReachable=true; }`. | +| `src/parser/nodes/literal.hpp` · `binary_expr.hpp` · `identifier.hpp` · `expressions.hpp` (Call/Member/Index/Postfix) | Bu node'ları `ExpressionNode`'dan türet. | +| `src/parser/nodes/statements.hpp` (Block/If/While/For/DoWhile/Return/Break/Continue/ExpressionStatement) · `declarations.hpp`? | Statement'ları `StatementNode`'dan türet. (VariableDecl/FunctionDecl/StructDecl tartışmalı — declaration; şimdilik `StatementNode` veya doğrudan `ASTNode` altında değerlendirilir.) | +| `src/parser/nodes/identifier.hpp` | `IdentifierNode`'a `Symbol* resolvedSymbol = nullptr;` (Faz 2'de bağlanır). | +| `src/parser/nodes/*.cpp` | `toJson()`/`log()`'a yeni alanları (tip, isReachable) ekle — boş cpp'ler doluyor. | + +### Doğrulama +- `saqut ast examples/Final.sqt` hâlâ geçerli JSON (regresyon yok, `python3 -m json.tool` ile). +- Derleme uyarısız (`-Wall -Wextra`). + +--- + +## Faz 2 — Symbol Table (scope'lu, iki-geçişli toplama) + +**Bağımlılık:** Faz 0, 1. **Hedef:** isim çözümleme + scope + referans toplama. +İlgili ADR: 011, 013. + +### Dosyalar + +| Dosya | İçerik | +|---|---| +| `src/symbol/symbol.hpp` | `enum class SymbolKind { Variable, Function, Parameter, Struct, Field }`. `struct Symbol { std::string name; SymbolKind kind; Type type; SourceLocation definitionLoc; std::vector references; Scope* scope; }`. | +| `src/symbol/scope.hpp` | `class Scope { Scope* parent; std::unordered_map symbols; ... }`. `defineLocal()`, `lookupLocal()`. Her katman bir namespace. | +| `src/symbol/symbol_table.hpp` | Scope yığını yönetimi: `enterScope()`, `exitScope()`, `define(Symbol)` (aynı scope'ta duplicate → false + `E002`), `resolve(name)` (içten dışa), `addReference(name, loc)`, `getAllSymbols()`, `toJson()`. | +| `src/symbol/symbol_collector.hpp/.cpp` | **İki geçiş** (ADR-011): **Geçiş 1** → tüm üst-seviye tanımlarını (fonksiyon imzaları, struct isim+alan tipleri, global değişkenler) global scope'a hoist et. **Geçiş 2** → fonksiyon gövdelerine in; lokal'leri declare-before-use ile topla; her `IdentifierNode`'u `resolve()` edip `resolvedSymbol`'a bağla + `addReference`. | + +### Notlar +- Scope oluşturan node'lar: Program, FunctionDecl (parametreler), Block, for/while. +- `src/json.hpp`'deki eski `collectSymbolsRecursive` bu sistemle değiştirilir. +- Tanımsız isim → `E001`; bilinmeyen tip → `E007`. + +### Doğrulama +- `saqut symbols examples/Final.sqt` → zengin tablo (her sembolün tipi, tanım yeri, + referansları). Forward reference çalışır (sonra tanımlı fonksiyon çağrılabilir). +- Hatalı örnekler → `E001`/`E002`/`E007` diagnostic'leri. + +--- + +## Faz 3 — Semantic Analiz (Tip Kontrolü + Yapısal Doğrulama) + +**Bağımlılık:** Faz 2. **Hedef:** tipleri ata/kontrol et, yapısal kuralları +doğrula. İlgili ADR: 010, 013. + +### Dosyalar + +| Dosya | İçerik | +|---|---| +| `src/sema/type_checker.hpp/.cpp` | İfadeleri alttan üste gez, her `ExpressionNode`'a `resolvedType` ata. Gizli dönüşüm yok (ADR-010) → uyuşmazlıkta `E003`. Kontrol noktaları: atama (`=`), binary op operand tipleri, fonksiyon çağrısı argümanları (`E008`), array index, return değeri (`E006`), variable init tip uyumu. Hata olunca node'a `Type::error()` → ardışık sahte hata yok. | +| `src/sema/structural_validator.hpp/.cpp` | Parent pointer ile ağaç-tırmanma kontrolleri: `break`/`continue` döngü/switch içinde mi (`E004`), `return` fonksiyon içinde mi (`E005`), array boyutu sabit mi (`E009`). | + +### Notlar +- Bu iki modül + Faz 2'nin collector'ı birlikte "semantic analiz" fazını oluşturur. +- Tüm hatalar toplanır, ilk hatada durulmaz; faz sonunda `DiagnosticEngine` + hepsini raporlar, pipeline durur (ADR-013). + +### Doğrulama +- Doğru `.sqt` → temiz geçer, her expression node'unun tipi JSON'da görünür. +- Hatalı `.sqt` örnekleri → tüm semantik hatalar tek seferde listelenir. + +--- + +## Faz 4 — Optimizasyon Framework + +**Bağımlılık:** Faz 3. **Hedef:** opsiyonel, iteratif, toggle'lı kaynak-seviyesi +optimizasyon. **Orijinali bozmaz — klon üstünde** (ADR-007). İlgili ADR: 007, 008, 009. + +### Dosyalar + +| Dosya | İçerik | +|---|---| +| `src/core/config.hpp` | `CompilerConfig`: pass toggle'ları (`optConstantFolding`, `optDeadCodeElim`, …), `outputFormat`, `mode`, `optimized` bayrağı. | +| `src/opt/optimization_pass.hpp` | Soyut `OptimizationPass`: `virtual bool run(ASTNode* root, SymbolTable* table) = 0;` (değişiklik yaptıysa true). `name()`. | +| `src/opt/optimization_manager.hpp` | Pass listesi; `CompilerConfig`'e göre seçim; **fixpoint döngüsü** (hiçbir pass değişiklik yapmayana kadar). Çalışmadan önce AST'yi **klonlar** (`ASTNode::clone()` gerekebilir). | +| `src/opt/constant_folding.hpp/.cpp` | `BinaryExpression` operandları sabitse hesapla, sonucu sabit `Literal` ile değiştir (klonda). Tipe saygılı (`5/2`→int `2`, ADR-010). Sıfıra bölme → `W002`, katlama yapma. | +| `src/opt/dead_code_elim.hpp/.cpp` | `isReachable` (Faz 3) işaretine göre: `return`/`break`/`continue` sonrası statement'lar, `if(false)`, sıfır-referanslı değişken (`W001`/`W003`). | + +### CLI Entegrasyonu + +| Dosya | Değişiklik | +|---|---| +| `src/cli/args.hpp` | `--optimized` ve `--opt-all`/`--opt-none`/`--skip-*` bayrakları → `CompilerConfig`. | +| `src/cli/commands/ast.hpp` · `symbols.hpp` | `--optimized` verilince klon+optimize edilmiş hali göster; verilmezse orijinal. | + +### Doğrulama +- `saqut ast file --optimized` → `1+2` katlanmış, ölü kod elenmiş. +- `saqut ast file` (bayraksız) → orijinal, **değişmemiş** (öncesi/sonrası ayrımı). +- Fixpoint: zincirleme optimizasyon (folding → yeni dead code → DCE) yakalanır. + +--- + +## Tamamlanınca + +Bu yol haritası bittiğinde frontend tamamlanmış olur: +- Parser → analizli, tipli, sembol-çözümlü AST + zengin symbol table. +- Tam hata raporlama (toplu, kataloglu). +- Opsiyonel, incelenebilir optimizasyon. + +Sonraki adım (ayrı yol haritası): **IR güçlendirme** (kontrol akışı/fonksiyon/ +bellek opcode'ları, ADR-005/Issue 5.1) → **C transpile backend** → QBE → JIT +(ADR-001 sırası). Dinamik array'in runtime bellek modeli (ADR-014) backend +fazında kararlaştırılır. diff --git a/docs/transkript-frontend-tasarim.md b/docs/transkript-frontend-tasarim.md new file mode 100644 index 0000000..dade0dd --- /dev/null +++ b/docs/transkript-frontend-tasarim.md @@ -0,0 +1,214 @@ +# saQut Frontend Tasarım Oturumu — Transkript + +> Bu belge, frontend (symbol table + semantic analiz + optimizasyon) mimarisinin +> kararlaştırıldığı tasarım oturumunun **sadık bir transkriptidir.** Alınan +> kararların gerekçeleri ADR formatında `docs/adr-frontend-analiz.md`'de, +> uygulama planı `docs/roadmap-frontend.md`'de yer alır. Bu belge ise tartışmanın +> **akışını ve düşünce sürecini** korur — bir kararın nasıl olgunlaştığı, hangi +> itirazların nasıl çözüldüğü buradadır. + +--- + +## 0. Başlangıç durumu + +Oturum öncesi tamamlananlar: +- Aşama 0 (SourceLocation / konum takibi) bitirildi: her token ve AST node'u + dosya/satır/sütun/offset taşıyor. +- İki bug giderildi: (1) `location.file` boş geliyordu → `Tokenizer::scan` artık + dosya yolu alıyor; (2) `"kind": true` bug'ı → `JsonObject::add`'a `const char*` + overload'u eklendi. +- AST JSON çıktısındaki fazla boşluk/girinti hataları temizlendi. +- Bu işler commit'lendi, master'a merge edildi ve push edildi. + +--- + +## 1. "Rotamız ne? IR/JIT'e geçebilir miyiz?" + +**Kullanıcı:** AST ve parser hazır mı? IR ve JIT adımına geçebilir miyiz? + +**Asistan (özet):** Henüz değil, doğrudan atlamak riskli. Roadmap durumu: +- Aşama 0 (konum) ✅ +- Aşama 1 (CLI/REPL) 🟡 yarım +- Aşama 2 (AST bellek canavarı) 🟡 yarım +- Aşama 3 (Symbol Table) ❌ yok (`src/symbol/` klasörü bile yok) +- Aşama 4 (Feature Toggle) ❌ yok +- Aşama 5 (IR + Backend) ❌ embriyonik (IR'de sadece 5 opcode: mathadd/sub/mul/div, + declare; backend yok) + +JIT'e atlamamak için iki engel: (1) Symbol table yok — IR üretimi değişken +çözümlemesi ister; (2) IR'de kontrol akışı/fonksiyon/bellek opcode'ları yok, yani +if/while/fonksiyon derlenemez. Ayrıca ADR-001'e göre strateji: C transpile → +QBE → custom/JIT. JIT "uzun vade". + +Önerilen sıra: Symbol Table → IR güçlendirme → C transpile → sonra JIT/QBE. + +--- + +## 2. Kullanıcının vizyonu: 2-pass parser ve AST'yi derinleştirme + +**Kullanıcı (özet):** Parser 2 aşamalı olacak. İlk pass syntax'ı çözüp basit +AST'yi bırakacak (tokenler, yerleri, türleri). İkinci pass'te symbol table +kurulacak (değişkenler, türleri, yerleri, kapsamları, kaç kez/nerede kullanıldıkları). +Sonraki tüm operasyonlar AST üzerinden döneceği için AST'de çok fazla ham/işlenmiş +veri olmalı; optimizasyon ve analizler tamamen burada olacak. 2. pass'te ilk AST +ve symbol table kullanılarak: kullanılmayan değişkenler, return sonrası kod, +bir kez atanıp bir kez kullanılan değişkenler, literal-operatör-literal (`1+2`) +kapatılacak (constant folding). Yorumlar/eleştiriler isteniyor. + +**Asistan — 4 itiraz/uyarı:** + +1. **"AST'yi derinleştirmek" felsefeyle çelişebilir.** "Hiçbir bilgi atılmaz" + prensibi var. `1+2`'yi yıkıcı şekilde `3` yaparsan orijinali silersin → + `saqut ast` artık kullanıcının yazdığını göstermez. Çözüm: **annotation** + (node'a `foldedValue:3` ekle, ağacı bozma) vs **transformation** (asıl silmeyi + AST→IR indirmede yap). + +2. **"2. pass" tek pass değil, içine 3 iş tıkıyorsun:** (a) sembol toplama/isim + çözümleme, (b) semantik doğrulama, (c) optimizasyon. Bunlar farklı bağımlılık + sırasına sahip; optimizasyon semantik analiz bitince anlamlı; optimizasyonlar + birbirini tetikler (fixpoint gerekir); ayrı test edilmeli. + +3. **"Bir kez atanıp bir kez kullanılan" optimizasyonu ağır.** Def-use chain / + dataflow ister; basit tree-walk değil. Ertele, IR'de yap. + +4. **Tip kontrolünü atlamamış ol.** Symbol table tip tutacaksa, `int x = "..."` + hatasını kim yakalar? Her expression node'una sonuç tipi annotate etmek değerli. + +İki soru soruldu: constant folding yıkıcı mı annotation mı? Scope kuralı +(forward reference) ne? + +--- + +## 3. Kullanıcının netleştirmesi: pass = derleyici aşaması; optimizasyon nerede? + +**Kullanıcı (özet):** "2-pass" sadece parser içindi, optimizasyonu kastetmedim. +Sıralama: 1. pass AST kur, 2. pass symbol table, 3. pass AST'yi derinleştir. +Ölü kodu 3'te sadece işaretleyelim demiştim ama haklısın, optimizasyon kendi +içinde tekrar çalışmalı — belki 5, belki 10 pass; her pass öncekinden rahat. + +**Önemli soru:** Optimizasyonları tam derleme/IR üretme zamanından önce +yapmamız gerekmiyor mu? Neden AST aşamasında optimize edeceğimizi düşündün? +Parametre olarak AST isteniyorsa optimizasyon halini isteğe bağlı vermeliyiz; +kullanıcı AST'nin/symbol table'ın optimizasyon öncesi/sonrası halini görmek +isteyebilir. + +**Scope:** Bunu JIT veya compiler frontend olarak düşünüyorum; arka planda Java +gibi forward reference olan ama C syntax'lı bir dil. Başta OOP yok, JS gibi düşün. + +**Asistan:** +- "Pass" düzeltmesi kabul: "5-10 pass" değil **fixpoint** (değişiklik durana + kadar). Her **tur** daha az iş yapar; analiz pass'leri bir kez çalışır. +- "Neden AST'de optimize?" sorusuna dürüst cevap: Ben "optimize" değil + "annotate" demiştim. **Analiz (gerçekler) vs optimizasyon (değişiklik)** ayrımı. + Frontend/middle-end/backend katmanlaması tanıtıldı. Basit kaynak-seviyesi + optimizasyonlar AST'de (backend-bağımsız, incelenebilir); ağır dataflow + optimizasyonları IR'de. Backend'e koyarsak 3 backend'de 3 kez yazarız. +- **Kullanıcının "öncesi/sonrası görebilmeli" gereksinimi mimariyi belirledi:** + optimizasyon orijinali ASLA bozmamalı → klon üret. `saqut ast` öncesi, + `saqut ast --optimized` sonrası. +- Scope kararı önerildi: üst seviye tam forward reference (2 alt-geçiş), lokal + declare-before-use. "Local hoisting istiyor musun?" sorusu soruldu. + +--- + +## 4. Tipli dil, hoisting yok; kalan tasarım sorunları + +**Kullanıcı (özet):** JS'i sadece syntax basitliği için örnek verdim, kötü +yanlarını almıyoruz — null/undefined karmaşası yok. Lokal'de hoisting olmasın, +tipli dil olacak. Pass = derleyicinin kendi aşamaları (lexing/parsing/optimizing/ +compiling), bunları çoğaltabiliriz. Scope: tam forward reference olsun. +Başka sorun var mı? + +**Asistan — "pass = aşama" doğrulandı,** her aşama bağımsız çalışan modül; CLI +komutları bunun yansıması. Sonra **3 gerçek mesele + küçük kararlar:** + +1. **Tip sistemi hiç tanımlanmadı.** `varType` şu an sadece string. Minimal ama + genişletilebilir `Type` sınıfı gerek. Tip çıkarımı (auto)? Implicit conversion? +2. **Diagnostic altyapısı şimdi gelmeli.** Semantik analiz hata üretecek ama + koyacak yer yok. Aşama 6'nın tamamı değil ama minimal `Diagnostic` toplayıcı + bu işle birlikte gelmeli. +3. **Annotation'lar node'larda nerede yaşayacak?** `ExpressionNode`/`StatementNode` + ara tabanları önerisi. + +Küçük kararlar: overloading yok; scope granülerliği (Program/FunctionDecl/Block/ +for-while); recursive struct → pointer gelince; aritmetik semantiği (5/2 int mi). + +--- + +## 5. Kullanıcının kapsam kararları + sorular + +**Kullanıcı (özet):** En baştan: pointer sistemi yok, tipleme basit, tuple +(``) yok, class yok struct var, array'ler define sırasında `[]` ile — +ama dinamik mi statik bellek mi karar veremedim. Fonksiyonlar tipli. `class` +gibi keyword'leri dikkate alma, `auto` yok. Otomatik float↔int dönüşümü yok, +her şey açık; gizli dönüşüm istemiyorum, sadece constant'larda (`5/2`→`2`). +Minimal Type sınıfına katılıyorum ama ileride geliştirilebilir olmalı — bu dilin +geleceğini bilmiyorum, popüler de olabilir, tozlanabilir de. Diagnostic için tüm +hataları baştan belirlemeliyiz; sistemi durdurup tüm hataları kullanıcıya +söylemeliyiz; hata raporlama fonksiyonları ayrı bir yerde olsun. Recursive struct +define yok ama `struct StructA { StructB BVar }` olabilir. Scope granülerliği +onaylandı. Duplicate'i tamamen yok et. For döngüsü içindeki objeler dışında +silinebilir — ama symbol table'ı karmaşıklaştırır, her katmanda namespace +tutmalıyız; üst katmanda hem öncesi hem sonrası aranacak — symbol table da mı 2 +geçiş olacak? AST'nin temiz kalması neyi zorlaştırır bilmiyorum, sen karar ver. +AST node cpp dosyaları neredeyse boş, oraları kullanalım, o class'ları dolduralım. + +**ExpressionNode konusunu tam anlamadım, açar mısın?** Ben tüm analizi AST'de +yapar, her node'da anlamlı veri tutar, ref'leri kendi içimde pointer olarak +tutarım diye düşünüyordum. + +**Asistan cevapları:** +- **Array:** Pointer yoksa dinamik array kuramazsın (heap+gizli pointer ister). + Öneri: statik sabit boyut. *(Bu karar bir sonraki turda revize edildi — bkz. §6.)* +- **ExpressionNode = aslında aynı fikirdeyiz.** Sorum felsefi değil, C++ detayı: + `resolvedType`'ı hangi node'a koyacağız? Tipli dilde sadece ifadelerin tipi var + (`5+3`→int; `if`→tipsiz). İki ara taban (`ExpressionNode`/`StatementNode`) + alanları doğru yere koyar + "burası ifade olmalı" kontrolü sağlar. Analiz yine + AST'de yaşar; bu sadece alanları doğru sınıflara dağıtmak. +- **Symbol table 2 geçiş?** Evet ama sadece üst seviyede. Geçiş 1: global'leri + hoist et. Geçiş 2: gövdelere in, çöz. Fonksiyon içi tek geçiş (lokal'de forward + ref yok). Öncesi/sonrası derdi sadece global'ler için, onu Geçiş 1 çözer. +- **AST temiz vs her şey AST'de → karar: her şey AST'de** (senin modelin). + Optimizasyon klonda dönüştürür. **Önemli:** "kaç kez kullanıldı" Symbol'da + yaşar (değişkene ait), node'da değil; IdentifierNode Symbol'a pointer tutar. +- **Hoisting açıklaması** (kullanıcı "local hoisting ne demek, global=local değil + mi?" diye sordu): Hoisting = tanımın yazıldığı satırdan önce de görünmesi. + Global'de forward ref güvenli (gövde tanımda çalışmaz, çağrılınca çalışır). + Lokal'de declare-before-use (değişkenin sırası/değeri var). Asimetri = + tutarsızlık değil, tam olarak Java'nın davranışı. + +--- + +## 6. Pointer netleştirmesi + son onaylar + +**Kullanıcı (özet):** Yanlış anlama düzeltmesi: pointer derleyici **içinde** tabii +ki var; programlama **dilinde** `*`/`&` yok. Pointer sadece derleyicinin içinde. +Bu, değişken listelerini destekler — JS'te pointer syntax'ı yok ama array var. +Kullanıcıya pointer yok, arka planda A'dan Z'ye pointer var. Ayrıca: local +hoisting senin dediğin gibi (declare-before-use). Array'ler `int[]` olsun. +**Ama bu backend'de dinamik bellek zorunluluğu getirmez mi? JIT'te?** +ExpressionNode → evet ekle. Her şey temiz, anlaşılır, yorum satırlarıyla +takip edilebilir olsun yeter. + +**Asistan:** +- **Array kararı revize edildi:** Pointer arka planda olduğuna göre dinamik + array mümkün. Frontend için `Type` sadece "array of T" temsil etsin, boyut + tipte olmasın. Runtime bellek modeli (statik/heap/free) backend kararı, ertelendi. +- **Dinamik bellek/JIT yükümlülüğü cevabı:** Evet ileride yükümlülük getirir ama + frontend'i bloklamaz. C transpile'da malloc/realloc/free ile neredeyse bedava; + JIT'te minik runtime kütüphanesine call emit edilir; yönetim stratejisi en + basiti scope-tabanlı ownership, GC gerekmez. +- Tüm kararlar kilitlendi; dosya-dosya yol haritası sunuldu (Faz 0…4). + +--- + +## 7. Belgeleme talebi + +**Kullanıcı:** Konuştuklarımızı ve kararları ADR formatında, neden öyle yaptığımızı +da belgele; hiçbir şey boş geçmesin; transkript de yazabilirsin; en son yol +haritasını oluştur; her şeyden önce yeni bir branch çık. + +**Asistan:** `feature/frontend-analysis` branch'i açıldı. Üç belge üretildi: +- `docs/adr-frontend-analiz.md` (ADR-006…014) +- `docs/transkript-frontend-tasarim.md` (bu belge) +- `docs/roadmap-frontend.md` (uygulama planı) From cf6f70644945ebab6505b31038b703ac6f87eaf8 Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Sun, 14 Jun 2026 19:53:12 +0300 Subject: [PATCH 02/28] docs: belgeleri yeniden hizala (IR+VM modeli, kilitli kararlar) - Calistirma modeli: "JIT" terimi birakildi -> IR + bytecode VM birincil; makine-kodu JIT kapsam disi (ADR-015). C-transpile ikinci backend. - readme.md bastan yazildi: toolbox cercevesi, yapilan vs planlanan ayrimi. - ADR amend: 007 (klon yuk tasir), 009 (fixpoint degismezi + analiz yeniden hesabi), 010 (literal baglama-gore tipleme), 011 (global baslatici uc-parcali kural + dongusel struct E010), 014 (bellek gerekcesi). - Yeni ADR: 015 (IR+VM), 016 (FFI seam), 017 (batteries=sinir), 018 (interface ertelendi), 019 (frontend<->runtime ayrimi). - roadmap: bu hafta sembol tablosu->fibonacci; once dikey dilim; E010. - examples: Final.sqt -> parser-stress/ (gecersiz fixture); yeni gecerli fibonacci.sqt eklendi. Co-Authored-By: Claude Opus 4.8 --- docs/adr-frontend-analiz.md | 339 +++++++++++++++++++++++-- docs/fikirler.md | 17 ++ docs/roadmap-frontend.md | 77 ++++-- examples/fibonacci.sqt | 33 +++ examples/{ => parser-stress}/Final.sqt | 0 examples/parser-stress/README.md | 21 ++ readme.md | 268 +++++++++++-------- 7 files changed, 612 insertions(+), 143 deletions(-) create mode 100644 examples/fibonacci.sqt rename examples/{ => parser-stress}/Final.sqt (100%) create mode 100644 examples/parser-stress/README.md diff --git a/docs/adr-frontend-analiz.md b/docs/adr-frontend-analiz.md index f0194fb..17ece89 100644 --- a/docs/adr-frontend-analiz.md +++ b/docs/adr-frontend-analiz.md @@ -9,6 +9,13 @@ > Bu kararlar bir tasarım oturumunda (kullanıcı + asistan) tartışılarak alındı. > Tartışmanın tam akışı için bkz. `docs/transkript-frontend-tasarim.md`. > Uygulama planı için bkz. `docs/roadmap-frontend.md`. +> +> ⚠️ **Yapılan vs planlanan:** Bu belgedeki ADR-006…019 **tasarım kararlarıdır**; +> tarif edilen makine (sembol tablosu, semantik analiz, tip sistemi, diagnostic, +> optimizasyon, IR+VM) **henüz kodlanmamıştır.** Bugün çalışan: lexer, tokenizer, +> Pratt parser, AST, AST'nin JSON serileştirmesi, CLI iskeleti, konum takibi ve +> basit aritmetiği düşüren minimal bir IR deneyi. Hiçbir ADR, var olmayan bir +> mekanizmayı varmış gibi anlatmaz. --- @@ -48,10 +55,10 @@ mimarisi): ``` FRONTEND MIDDLE-END BACKEND lexer → token → optimizasyon IR lowering → -parser → AST → (opsiyonel, iteratif, kod üretimi -symbol table → toggle'lı, ortak (C transpile / -semantic analiz gösterim üstünde) QBE / JIT) -(annotated AST) +parser → AST → (opsiyonel, iteratif, bytecode VM (birincil) +symbol table → toggle'lı, ortak + ileride C transpile +semantic analiz gösterim üstünde) (makine kodu = uzak +(annotated AST) gelecek; ADR-015) ``` - **Pass 1 (Syntax):** token → ham AST. (Büyük ölçüde mevcut.) @@ -62,9 +69,10 @@ semantic analiz gösterim üstünde) QBE / JIT) "Parser ve symbol hikayesini bitirmek" = **frontend'i bitirmek.** Optimizasyon ayrı bir katmandır (middle-end), backend'ler bu ortak çıktıdan beslenir. -**Neden bu katmanlama?** Birden çok backend (C transpile, QBE, JIT) planlandığı -için, ortak işler (analiz, optimizasyon) **bir kez** ortak katmanda yapılmalı; -yoksa her backend aynı optimizasyonu yeniden yazar. +**Neden bu katmanlama?** Birden çok backend (birincil: IR+bytecode VM, ADR-015; +ileride: C transpile; çok uzak: makine kodu) hedeflendiği için, ortak işler +(analiz, optimizasyon) **bir kez** ortak katmanda yapılmalı; yoksa her backend +aynı optimizasyonu yeniden yazar. --- @@ -109,6 +117,35 @@ saqut ast file.sqt → ham + annotate edilmiş AST (1+2 burada duru saqut ast file.sqt --optimized → klon, folding uygulanmış (3 var) ``` +### Güncelleme — Klon maliyeti yük taşır (load-bearing) + +İlk metin "ağaç klonlamak ucuz ve basittir" diyordu; bu **klon maliyetini hafife +alıyor** ve bir **tutarlılık (coherence) problemini** atlıyordu. Düzeltme: + +`ASTNode::clone()` "belki gerekir" değil, **merkezi ve spesifiye edilmesi +zorunlu** bir bileşendir; tüm öncesi/sonrası hikâyesi ona dayanır (bkz. roadmap +Faz 4'te clone() yükseltildi). + +**Klonlanırken karar verilmesi gereken iki nokta (açıkça belgele):** + +1. **Parent pointer'lar yeniden bağlanmalı.** Klon node'larının `parent`'ı + orijinali değil, klonu göstermeli; yoksa yapısal doğrulama ve dönüşümler + yanlış ağaçta gezinir. + +2. **`IdentifierNode → Symbol` bağları: paylaş mı, yeniden eşle mi?** + - **Paylaş** (klon ve orijinal aynı sembol tablosuna işaret eder): ucuz, ama + klonu optimize etmek orijinalin **referans sayımlarını bozar** (DCE klonda + bir kullanımı silince orijinalin Symbol ref-count'u da düşer). + - **Yeniden eşle** (klona ait bir sembol tablosu kopyası): doğru, ama ucuz + değil. + - **Karar:** `--optimized` istendiğinde sembol tablosu da **klonlanır ve + yeniden eşlenir** (remap). Doğruluk, ucuzluğa tercih edilir; klon zaten + yalnızca optimizasyon istendiğinde üretilir, sıcak yol değildir. "Ucuz" + iddiası kaldırıldı. + +Bu, ADR-013'teki "ref-count Symbol'da yaşar" kararıyla tutarlıdır: ref-count +Symbol'da olduğu için, klonun kendi Symbol'larına sahip olması şarttır. + --- ## ADR-008: Optimizasyon Konumu — AST mı, IR mı? @@ -129,7 +166,7 @@ sorusu tartışıldı. İki uç yaklaşım var: - **Kaynak-seviyesi, ağaç-yerel optimizasyonlar** (constant folding, ölü kod işaretleme, unused variable) → **AST'de** yapılır. Çünkü: 1. Dil JS gibi basit; ağır optimizasyona ihtiyaç yok. - 2. Backend-bağımsız → C transpile, QBE, JIT üçü birden faydalanır. + 2. Backend-bağımsız → bytecode VM ve ileride C transpile birden faydalanır. 3. İncelenebilir kalır (`saqut ast --optimized`) — projenin varlık sebebi. - **CFG/dataflow gerektiren optimizasyonlar** ("bir kez atanıp bir kez @@ -169,6 +206,39 @@ belki 7 — kodun kendisi belirler. > her **tur** daha az değişiklik yapar. Analiz pass'leri (symbol table, type check) > "kolaylaşmaz"; onlar bir kez çalışır. +### Güncelleme — Sonlanma değişmezi (termination invariant) + +Fixpoint döngüsünün **sonlanacağı garanti edilmeli**. İki seçenekten en az biri +zorunludur: + +1. **Monotonluk:** havuzdaki tüm pass'ler **monoton** olmalı — yalnızca + küçültür/sadeleştirir, asla büyütmez. Constant folding ve dead code + elimination bugün monotondur, dolayısıyla fixpoint sonlanır. +2. **Sert iterasyon tavanı (cap):** bir üst sınır (örn. `maxFixpointRounds`). + +**Neden gerekli:** ileride **büyüten** pass'ler (inlining, loop unrolling) +eklenirse, naif fixpoint **salınabilir** (A büyütür, B küçültür, sonsuz döngü). +Büyüten bir pass eklendiği an, monotonluk bozulur ve **iterasyon tavanı zorunlu +hale gelir.** Bu değişmez şimdiden yazıya geçirildi ki ileride unutulmasın. + +### Güncelleme — "Analiz bir kez çalışır" çelişkisinin çözümü + +ADR-013 "analiz bir kez çalışır" diyor; ama folding **erişilebilirliği** +(`if(false)`) ve **referans sayımlarını** değiştirir, DCE de tam bunlara +dayanır. Eğer analiz gerçekten yalnızca bir kez çalışırsa, fixpoint'in ikinci +turundaki DCE **bayat (stale) veriyle** çalışır ve zincirleme fırsatları kaçırır. + +**Çözüm — iki analiz sınıfını ayır:** + +- **Kaynağa-bağlı analiz** (her ifadenin tipi, sembol bağları): kaynak değişmediği + sürece sabittir → **bir kez** çalışır, klona taşınır. +- **Türetilmiş/akışa-bağlı analiz** (erişilebilirlik `isReachable`, referans + sayıları): bir dönüşüm bunları geçersizleştirir → **fixpoint döngüsünün her + turunda, klon üzerinde yeniden hesaplanır.** + +Yani "analiz bir kez çalışır" ifadesi yalnızca **kaynağa-bağlı** analiz için +geçerlidir; akışa-bağlı analiz tur başına tazelenir. ADR-013 buna göre okunmalı. + --- ## ADR-010: Tip Sistemi Tasarımı @@ -205,6 +275,33 @@ boyut tip eşitliğine girmez (JS gibi). Tip kontrolü basit kalır. de olabilir, yıllarca repolarda tozlanabilir de." Temel sağlam ve büyümeye açık olmalı. +### Güncelleme — Sayısal literal tipleme kuralı + +"Gizli dönüşüm yok + tip çıkarımı yok" altında `float x = 1;` ifadesi +**tanımsızdı**. Bu açıkça karara bağlanmalı, çünkü tip denetleyicisini (Faz 3) +doğrudan yönlendirir. + +**Değerlendirilen iki kural:** + +- **(a) Literal her zaman `int`:** `1` daima `int`'tir. `float x = 1;` bir tip + hatasıdır; `float x = 1.0;` yazmak zorunludur. En katı, en öngörülebilir; ama + rahatsız edici ve "gizli dönüşüm yok" ilkesini literallere kadar gereksiz yere + zorlar. +- **(b) Tamsayı literali bağlama-göre tiplenir (context-typed / polymorphic):** + tipsiz bir tamsayı sabiti, beklenen tip ona **kayıpsız** sığıyorsa o tipe + uyarlanır. `float x = 1;` çalışır (`1` → `1.0`); `int y = 1.5;` ise hata + (kayıp olur). + +**Karar:** ✅ **(b) Bağlama-göre tiplenen tamsayı literalleri.** + +- Gerekçe: bu bir **değişken-değer dönüşümü değil, bir derleme-zamanı sabitinin + uygun tipte yorumlanmasıdır** — tam olarak ADR-010'un zaten tanıdığı "sabit + istisnası" (`int a = 5/2 → 2`) ruhuyla aynı kapıya çıkar. Çalışma zamanı + `int` değişkenini `float`'a gizlice çevirmek hâlâ **yasaktır**; istisna + yalnızca **literal/sabit** içindir. +- Kural net: *değişken→değişken* gizli dönüşüm yok; *literal→beklenen tip* + kayıpsızsa serbest. `float x = anInt;` hata; `float x = 1;` serbest. + --- ## ADR-011: Scope ve Forward Reference Kuralları @@ -269,6 +366,44 @@ Her katman bir namespace tutar; değişken bulunamazsa bir üst katmanda aranır derdi yalnızca global'ler içindir, onu da Geçiş 1 çözer (global'ler en baştan tamamen doludur). +### Güncelleme — Global "tam forward reference" çok genişti: üç-parçalı kural + +İlk metin "global = her zaman forward-reference güvenli" diyordu; bu **fazla +geniş**. Global bir değişkenin **başlatıcısının (initializer) bir çalışma +sırası vardır** (tıpkı lokaller gibi). Düzeltme — üç ayrı kural: + +1. **Global fonksiyonlar / struct'lar → tam hoisting.** Tanım anında çalışmazlar, + sıradan bağımsız her yerde görünür. (Güvenli; değişmedi.) +2. **Global değişken isimleri → hoist edilir.** İsim her yerde görünür. +3. **Global değişken başlatıcıları → değer sırasına tabidir** (lokaller gibi) → + **declare-before-use** VEYA bir **definite-assignment (kesin-atama) analizi** + gerektirir. + +**Neden:** `int a = b; int b = 5;` global scope'ta, isim-hoisting'e güvenilirse, +`a`'ya **sessizce çöp değer** verir — kaçınmaya çalıştığımız tam o JS `var` +durumu. Java da aynı sebeple bunu kısıtlar. Karar: global başlatıcılar için de +**declare-before-use** uygulanır (en basit, definite-assignment'a gerek +bırakmaz). Yani isim görünür ama **kendinden önceki** bir global başlatıcıda +kullanılabilir. + +### Güncelleme — Döngüsel / karşılıklı-özyinelemeli struct tespiti + +Pointer olmadığı için tüm struct iç içeliği **değer (by-value)** ile olur → +herhangi bir kapsama döngüsü sonsuz boyut demektir: + +``` +struct A { B b } // A, B'yi değer olarak içerir +struct B { A a } // B, A'yı değer olarak içerir → sonsuz boyut +``` + +Bu **derleme hatası olmak zorunda** ve hata kataloğunda **eksikti**. Eklendi: +**`E010` — özyinelemeli/döngüsel struct tanımı.** Symbol toplama sonrası bir +**topolojik / kapsama-döngüsü kontrolü** çalışır (struct'ları düğüm, "alan +olarak içerir" kenarını çevrim arayan bir DFS ile). Çevrim bulunursa `E010`. + +(Karşılaştır: `struct A { B b }` + `struct B { int x }` geçerlidir; yalnızca +**çevrim** yasaktır. Pointer olsaydı çevrim mümkün olurdu — ama pointer yok.) + --- ## ADR-012: ExpressionNode / StatementNode Ara Tabanları @@ -351,12 +486,14 @@ Sebep: kullanım sayısı **değişkene** aittir, tek bir kullanım node'una de |---|---|---| | Pointer (kullanıcı syntax'ı `*`/`&`) | ❌ Yok | Ama derleyici/runtime **içeride** pointer'ı sonuna kadar kullanır | | Tuple / Generic (``) | ❌ Yok | | -| Class / OOP | ❌ Yok (başta) | `class` keyword'ü yok sayılır | -| Struct | ✅ Var | `struct A { B bVar }` olur (B başka yerde tanımlı); recursive define yok | +| Class / OOP / kalıtım | ❌ Yok (başta) | `class` keyword'ü yok sayılır | +| Closure | ❌ Yok | Bkz. ADR-019 (bellek bağımlılığı) | +| Struct | ✅ Var | `struct A { B bVar }` olur (B başka yerde tanımlı); **çevrim yasak → `E010`** | +| `interface` | ⏸️ Ertelendi | Reddedilmedi; v0 değil — gerekçe aşağıda + ADR-018 | | Array | ✅ `int[]` | Dinamik yönde; runtime bellek modeli ertelendi | | Fonksiyonlar | ✅ Tipli | Dönüş + parametre tipleri zorunlu | | `auto` / tip çıkarımı | ❌ Yok | Her şey açık tipli | -| Gizli int↔float dönüşümü | ❌ Yok | Sadece sabit folding'de istisna | +| Gizli int↔float dönüşümü | ❌ Yok | Sadece sabit/literal folding'de istisna (ADR-010) | ### Dinamik Array'in Bellek Yükümlülüğü (Gelecek Notu) @@ -364,13 +501,164 @@ Sebep: kullanım sayısı **değişkene** aittir, tek bir kullanım node'una de bir yükümlülüktür ama **frontend'i bloklamaz** ve kolay yolu vardır: - **Frontend:** yalnızca "bu int dizisi" bilgisini ister; bellek modelinden habersiz. -- **C transpile backend (ilk backend):** `int[]` → C'de `struct {int* data; size_t len, cap;}`, - `malloc/realloc/free` ile yönetilir. Bellek yönetimi C'den hazır gelir. -- **JIT backend:** bellek yönetimini kendi yapmaz; minik bir runtime kütüphanesi - (`array_new`, `array_push`, `array_free`) olur, JIT bunlara **call** emit eder. -- **Yönetim stratejisi (ne zaman free):** en basiti scope-tabanlı ownership - (array'i tutan değişken scope'tan çıkınca free). GC gerekmez. Runtime'a - gelince kararlaştırılır. +- **IR + bytecode VM (ilk çalıştırma modeli, ADR-015):** bellek host (C++) + heap'idir; array'ler host tarafında `std::vector` benzeri bir yapıyla tutulur. + VM, array işlemleri için **host fonksiyonlarına** (FFI seam, ADR-016) çağrı + yapar. v0 için özel allocator gerekmez. +- **C transpile backend (ileride, ikinci backend):** `int[]` → C'de + `struct {int* data; size_t len, cap;}`, `malloc/realloc/free` ile yönetilir. +- **Yönetim stratejisi (ne zaman free):** scope-tabanlı ownership (array'i tutan + değişken scope'tan çıkınca free). GC gerekmez — **neden gerekmediği aşağıda + gerekçelendirildi.** + +### Güncelleme — Scope-tabanlı bellek artık GEREKÇELİ (bağımlılığı belgele) + +Önceki kaygı ("scope çıkışında free, aliasing/escape altında bozulur") kilitli +dil kimliğiyle **lehte çözüldü:** + +> prosedürel + value semantics + kullanıcı pointer'ı yok + closure yok + kaçan +> referans yok → array/string'ler tanımlandıkları scope'tan **kaçamaz** → +> scope-tabanlı ownership (scope çıkışında free) **gerçekten çalışır, GC +> gerekmez.** + +**Bağımlılık açıkça yazılır:** scope-tabanlı bellek, *yalnızca* no-pointer / +value-semantics seçimi sayesinde geçerlidir. `interface` değerleri veya kaçan +referanslar eklenirse bu sorun **yeniden açılır**. (Bu, `interface`'i ertelemenin +ikinci sebebidir — bkz. ADR-018, ADR-019.) + +--- + +## ADR-015: Çalıştırma Modeli — IR + Bytecode VM (Makine-Kodu JIT Kapsam Dışı) + +### Bağlam + +Daha önceki belge/konuşmalarda çalıştırma için "JIT" terimi geçiyordu. Hangi +çalıştırma modeli? Üç uç var: tree-walker, bytecode VM, gerçek makine-kodu JIT. + +### Değerlendirilen Yaklaşımlar + +- **Tree-walker (AST'yi doğrudan gez-çalıştır):** en basit, ama **çok yavaş**; + her çalıştırmada ağaç gezilir. +- **Makine-kodu JIT** (register allocation, ABI/çağırma sözleşmeleri, + çalıştırılabilir `mmap` bellek): en hızlı; ama **tek faydası ham hızdır**, ki + burada öncelik değil. Determinizmi ve incelenebilirliği zorlaştırır, devasa + mühendislik yükü getirir. +- **IR + bytecode VM** (kendi IR'imize derle, yorumlayıcı döngü ile çalıştır): + determinizm ve incelenebilirliği **doğrudan** sağlar; tree-walker'dan hızlı; + bellek host heap'iyle kolay. + +### Karar + +✅ **IR + bytecode VM.** saQut kendi IR'sine derler ve bir yorumlayıcı döngüyle +çalıştırır. + +- ❌ **Makine-kodu JIT kapsam dışıdır** (terminoloji düzeltmesi: "JIT" demeyi + bırak). Öncelikler **determinizm + incelenebilirlik** (toolbox), ham hız değil. +- **Bellek kolaydır:** host (C++) heap'i; özel runtime allocator yok (v0). +- **C'ye transpile, geçerli bir İKİNCİ backend olarak ileride kalır** (frontend + backend-bağımsız, ADR-006). +- İleride makine kodu **gerçekten** istenirse: elle code generator yazmak yerine + **libgccjit / LLVM'e bağlan** (ADR-001'deki QBE/custom değerlendirmeleri o gün + için geçerli). Bu **çok uzak gelecektir.** + +--- + +## ADR-016: FFI Seam — Host Fonksiyon Çağırma Deliği + +### Bağlam + +`print` bile bir "dış dünya" çağrısıdır; VM tek başına ekrana yazamaz, host'tan +bir fonksiyon çağırmalıdır. Bu ihtiyaç ya **kaza eseri** tek bir özel-durum +olarak gömülür, ya da **kasıtlı bir mekanizma** olarak tasarlanır. + +### Karar + +✅ **IR/runtime tasarımına bilinçli bir FFI seam konur:** "host fonksiyonu çağır" +için tek, genel bir IR mekanizması (örn. `callhost , args...`). + +- `print` bu seam'in **ilk müşterisidir**, özel-durum değil. +- İleride tüm "batteries" (bkz. ADR-017) bu sınır üzerinden gelir: sıkıştırma/ + kripto C kütüphaneleri buraya bağlanır. +- **Neden şimdi:** seam'i sonradan eklemek IR ve VM'i baştan değiştirmeyi + gerektirir; deliği bir kez doğru açmak ucuzdur. Mekanizmayı **şimdi** doğru + tasarla, içini sonra doldur. + +--- + +## ADR-017: Batteries / Stdlib — Sınır Problemi (Ertelendi) + +### Bağlam + +Gerçek bir genel sürüm pil ile gelmeli (sıralama, sıkıştırma, kripto, +JSON/XML/HTML, ileride runtime/donanım, ses/görüntü/video). JSON/string +ergonomisi olmayan bir dil benimsenmez — bu doğru. Ama korku: pilleri çekirdeğe +gömmek **monolit** yaratır. + +### Karar + +✅ **Pil = sınır (boundary) problemi, "zlib'i yeniden yaz" problemi değil.** + +- Çekirdek: **küçük bir gerçek builtin kümesi** (`print`, temel zorunlular) + + **gerisi kütüphane/FFI.** +- **JSON/XML/HTML ayrıştırıcıları saQut'ta yazılabilir** (string + struct + + fonksiyon + kontrol akışı yeter) — ilk "gerçek program" demoları. +- **Sıkıştırma/kripto:** denenmiş C kütüphanelerine **FFI** ile bağlan. **Kripto + asla elle yazılmaz.** +- **Bugüne tek yansıması:** FFI seam'i (ADR-016) bırak. Gerisi **v0 kapsamı + dışıdır.** Sınır bir kez çizilir, piller üstünde sonsuza dek birikir. + +--- + +## ADR-018: `interface` Ertelemesi (Reddedilmedi) + +### Bağlam + +Kullanıcı struct'ın yanında `interface` de istedi (crypto, compression, custom +data types, JSON, string için). `interface` alınmalı mı, ne zaman? + +### Karar + +✅ **Şimdi `struct`, `interface` ise ertelenir (reddedilmez).** + +**Neden ertelendi:** `interface`, `struct`'tan kategorik olarak ağırdır. +- Struct yalnızca alan yerleşimidir (field layout). +- Interface "bu metotları sağlayan herhangi bir tip" demektir → çağrı yerinde + somut tip **bilinmez** → **dinamik dispatch** → vtable / fat pointer (içsel + pointer, izinli) → ve bir interface değeri **herhangi bir tipi tutabilir**, bu + da **kaçma/yaşam-süresi (escape/lifetime) problemini yeniden açar** (ADR-019). +- Go bunu fat pointer + GC ile çözer; saQut **GC istemiyor.** + +Kullanıcının saydığı her şey (crypto, compression, custom data, JSON, string) +**yalnızca struct + fonksiyonla** yapılabilir (C bunu kanıtlar). Dolayısıyla: +şimdi struct'ı al, interface'i ertele. + +**Metot-çağrı şekeri** (`list.push(5)` → `push(list, 5)`) ileride **parser +seviyesinde, sıfır semantik maliyetli** bir desugaring olarak eklenebilir — +şimdi değil. + +--- + +## ADR-019: Frontend ↔ Runtime Sorumluluk Ayrımı + +### Bağlam + +"Hangi CPU çekirdeği, hangi cihaz, ne zaman tetiklenir, hangi çıktı formatı" +gibi sorular nereye ait? Frontend'e mi, runtime'a mı? + +### Karar + +✅ **Net ayrım, frontend'i runtime kaygılarıyla yükleme:** + +- **Frontend:** **yapı ve anlam** — tip, scope, dataflow. (Bu yol haritasının + konusu.) +- **Runtime/backend:** çekirdek/cihaz/tetikleme/çıktı formatı. + +**Neden:** bu ayrım, kullanıcının önem verdiği **modülerliği korur**; frontend +backend-bağımsız kalır (ADR-006), böylece IR+VM ve ileride C-transpile aynı +frontend'den beslenir. Ayrıca **value-semantics + no-escape** kararının (kaçan +referans/closure yok) bağımlılığı buradadır: bu sayede scope-tabanlı bellek +çalışır (ADR-014). Closure veya interface değerleri eklemek bu ayrımı ve bellek +modelini birlikte zorlar — ikisi de bu yüzden ertelendi. --- @@ -379,11 +667,16 @@ bir yükümlülüktür ama **frontend'i bloklamaz** ve kolay yolu vardır: | ADR | Konu | Karar | |---|---|---| | 006 | Frontend mimarisi | Çok-aşamalı; frontend/middle-end/backend katmanları | -| 007 | Analiz vs optimizasyon | Analiz yerinde işaretler; optimizasyon klonda dönüştürür | +| 007 | Analiz vs optimizasyon | Analiz yerinde işaretler; optimizasyon klonda dönüştürür; `clone()` merkezi, sembol tablosu remap edilir | | 008 | Optimizasyon konumu | Basitler AST'de, dataflow gerektirenler IR'de | -| 009 | Pass yönetimi | Fixpoint döngüsü, toggle'lı | -| 010 | Tip sistemi | Minimal+genişletilebilir Type; gizli dönüşüm yok; Error tipi | -| 011 | Scope/forward ref | Global'de forward ref, lokal'de declare-before-use (Java gibi) | +| 009 | Pass yönetimi | Fixpoint döngüsü, toggle'lı; monotonluk/iterasyon-tavanı değişmezi; akışa-bağlı analiz tur başına tazelenir | +| 010 | Tip sistemi | Minimal+genişletilebilir Type; gizli dönüşüm yok; Error tipi; tamsayı literali bağlama-göre tiplenir | +| 011 | Scope/forward ref | Global'de forward ref (fonksiyon/struct), ama global başlatıcı declare-before-use; lokal declare-before-use; döngüsel struct → `E010` | | 012 | Node hiyerarşisi | ExpressionNode / StatementNode ara tabanları | | 013 | Analiz verisi yeri | Her şey AST'de; ref-count Symbol'da | -| 014 | Dil kapsamı | Pointer/class/generic yok; struct+array+tipli fonksiyon var | +| 014 | Dil kapsamı | Pointer/class/generic/closure yok; struct+array+tipli fonksiyon var; scope-tabanlı bellek gerekçeli | +| 015 | Çalıştırma modeli | IR + bytecode VM; makine-kodu JIT kapsam dışı | +| 016 | FFI seam | Kasıtlı "host fonksiyonu çağır" mekanizması; `print` ilk müşteri | +| 017 | Batteries/stdlib | Sınır problemi; küçük builtin + FFI/kütüphane; ertelendi | +| 018 | `interface` | Ertelendi (reddedilmedi); struct+fonksiyon yeter | +| 019 | Frontend↔runtime | Frontend yapı+anlam; çekirdek/cihaz/çıktı runtime'a ait | diff --git a/docs/fikirler.md b/docs/fikirler.md index f667d67..e129375 100644 --- a/docs/fikirler.md +++ b/docs/fikirler.md @@ -4,6 +4,23 @@ > gelecek yol haritası hakkında kapsamlı analizleri içerir. > Her kararın **neden** alındığı, alternatiflerin neden elendiği ve > gelecekte hangi koşullarda tekrar değerlendirileceği belirtilmiştir. +> +> ⚠️ **Hizalama notu (sonraki oturum):** Aşağıdaki ADR-001 ve ADR-005, backend +> kod-üretimi seçeneklerini (LLVM/QBE/custom/C-transpile) ve "JIT" terimini +> tartışır. Sonradan **çalıştırma modeli netleşti** ve bazı ifadeler güncellendi: +> +> - **Birincil çalıştırma modeli = IR + bytecode VM** (yorumlayıcı döngü). +> Bkz. `docs/adr-frontend-analiz.md` **ADR-015**. +> - **Gerçek makine-kodu JIT kapsam DIŞIDIR** (tek faydası ham hız; öncelik +> determinizm + incelenebilirlik). Buradaki "JIT" geçişleri bu ışıkta okunmalı. +> - **C-transpile**, ileride geçerli bir **ikinci backend**'tir; QBE/custom/LLVM +> ise "makine kodu gerçekten gerekirse libgccjit/LLVM'e bağlan" çerçevesinde +> **çok uzak gelecektir**. ADR-001'deki karşılaştırmalar o gün için geçerli. +> - "HeavyIR/LightIR" ikiliği (ADR-005) bir **gelecek fikri** olarak durur; v0'ın +> IR+VM hedefi tek, basit bir IR'dir + **FFI seam** (ADR-016). +> - **Yapılan vs planlanan:** ADR-001'deki "mevcut durum" listesi hâlâ doğrudur +> (lexer/tokenizer/parser/AST + minimal IR deneyi çalışır); kod üretimi ve VM +> **henüz yoktur.** --- diff --git a/docs/roadmap-frontend.md b/docs/roadmap-frontend.md index 05479ca..897b73d 100644 --- a/docs/roadmap-frontend.md +++ b/docs/roadmap-frontend.md @@ -1,14 +1,30 @@ # saQut Frontend Yol Haritası — Symbol Table + Semantic Analiz + Optimizasyon > Bu belge, frontend'i tamamlamaya yönelik dosya-dosya uygulama planıdır. -> Kararların gerekçeleri: `docs/adr-frontend-analiz.md` (ADR-006…014). +> Kararların gerekçeleri: `docs/adr-frontend-analiz.md` (ADR-006…019). > Tartışma akışı: `docs/transkript-frontend-tasarim.md`. > > **İlke:** Sıralama katıdır — her faz bir öncekine dayanır. Her faz sonunda -> mevcut örneklerle (`examples/Final.sqt`, `examples/source.sqt`) ve CLI +> geçerli örnekle (`examples/fibonacci.sqt`, `examples/source.sqt`) ve CLI > komutlarıyla doğrulama yapılır; regresyon olmamalıdır. Kod temiz, anlaşılır ve > yorum satırlarıyla takip edilebilir olmalıdır (header-only tarzı korunur, > bkz. ADR-003). +> +> ⚠️ **Yapılan vs planlanan:** Bugün çalışan = lexer, tokenizer, Pratt parser, +> AST, AST'nin JSON serileştirmesi, CLI iskeleti, konum takibi, basit aritmetiği +> düşüren minimal IR deneyi. Bu yol haritasındaki **her şey planlıdır** (sembol +> tablosu, semantik analiz, tip sistemi, diagnostic, optimizasyon). +> +> 🎯 **Bu haftanın işi:** **sembol tablosu + iki-geçişli toplayıcı** (Faz 2), +> hedef **"fibonacci'yi derle ve çalıştır"** (`examples/fibonacci.sqt`). Faz 0–1 +> bunun önkoşuludur. +> +> 🧭 **Önce dikey dilim, sonra çerçeve.** Bir şey çalışmadan önce genel pass +> manager / evrensel config / ağır soyutlama inşa etme. Uçtan uca tek bir dilim +> (kaynak → IR → çalıştır; tamsayı + değişken + kontrol akışı + tek `print`) +> önce çalışsın. Faz 4'ün framework'ü (OptimizationManager, fixpoint, config) +> ancak Faz 0–3 fibonacci'yi geçirdikten **sonra** anlam kazanır — erken +> soyutlama daha az değil, daha çok karmaşıklıktır. --- @@ -25,7 +41,8 @@ Faz 4 Optimizasyon Pass manager (fixpoint) + constant folding + dead code Katman eşlemesi (ADR-006): - **Frontend:** Faz 0–3 - **Middle-end:** Faz 4 -- **Backend:** bu yol haritasının dışında (C transpile → QBE → JIT, ADR-001) +- **Backend:** bu yol haritasının dışında (birincil: IR + bytecode VM, ADR-015; + ileride: C transpile; makine kodu uzak gelecek — "JIT" kapsam dışı) --- @@ -46,21 +63,28 @@ Katman eşlemesi (ADR-006): | Kod | Anlam | Hangi fazda üretilir | |---|---|---| -| `E001` | Tanımsız değişken/isim | Faz 2/3 | +| `E001` | Tanımsız değişken/isim (declare-before-use ihlali dahil — lokal ve **global başlatıcı**, ADR-011) | Faz 2/3 | | `E002` | Aynı scope'ta çift tanım | Faz 2 | -| `E003` | Tip uyuşmazlığı | Faz 3 | +| `E003` | Tip uyuşmazlığı (gizli dönüşüm yok; literal için bağlama-göre kural, 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 tanımı** (by-value çevrim → sonsuz boyut, ADR-011) | 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 | *(Liste uygulamada genişleyebilir; yeni hatalar buraya eklenir.)* +**Literal / başlatıcı kuralları (ADR-010/011) hata kataloğunu nasıl etkiler:** +- `float x = 1;` → **hata değil** (tamsayı literali bağlama-göre tiplenir, + kayıpsız). `int y = 1.5;` → `E003` (kayıp). `float x = anInt;` → `E003` + (değişken→değişken gizli dönüşüm yok). +- `int a = b; int b = 5;` (global) → `E001` (global başlatıcı declare-before-use). + ### Doğrulama - `Type::equals` / `toString` birim testleri. - `DiagnosticEngine` topla → `printAll` çıktısı doğru sıralı. @@ -83,7 +107,11 @@ ayır, analiz alanlarını ekle. İlgili ADR: 012, 013. | `src/parser/nodes/*.cpp` | `toJson()`/`log()`'a yeni alanları (tip, isReachable) ekle — boş cpp'ler doluyor. | ### Doğrulama -- `saqut ast examples/Final.sqt` hâlâ geçerli JSON (regresyon yok, `python3 -m json.tool` ile). +- `saqut ast examples/fibonacci.sqt` hâlâ geçerli JSON (regresyon yok, + `python3 -m json.tool` ile). Parser regresyonu için ayrıca + `examples/parser-stress/Final.sqt` de geçerli JSON üretmeye devam etmeli (bu + dosya **geçerli program değildir**, yalnızca parser/AST stres fixture'ıdır — + semantik fazlarda fixture olarak kullanılmaz). - Derleme uyarısız (`-Wall -Wextra`). --- @@ -105,12 +133,20 @@ ayır, analiz alanlarını ekle. İlgili ADR: 012, 013. ### Notlar - Scope oluşturan node'lar: Program, FunctionDecl (parametreler), Block, for/while. - `src/json.hpp`'deki eski `collectSymbolsRecursive` bu sistemle değiştirilir. -- Tanımsız isim → `E001`; bilinmeyen tip → `E007`. +- Tanımsız isim → `E001`; bilinmeyen tip → `E007`; çift tanım → `E002`. +- **Döngüsel struct kontrolü (`E010`):** Geçiş 1'den sonra struct'lar düğüm, + "alanı olarak içerir" kenarıyla bir çevrim-arama (DFS) çalıştır; çevrim → + `E010` (ADR-011). Pointer olmadığı için tüm kapsama by-value'dur; çevrim = + sonsuz boyut. +- **Global başlatıcı declare-before-use (ADR-011):** fonksiyon/struct tam hoist + edilir, global değişken **ismi** hoist edilir, ama global değişken + **başlatıcısı** kendinden önce tanımlı isimleri kullanabilir; aksi → `E001`. ### Doğrulama -- `saqut symbols examples/Final.sqt` → zengin tablo (her sembolün tipi, tanım yeri, - referansları). Forward reference çalışır (sonra tanımlı fonksiyon çağrılabilir). -- Hatalı örnekler → `E001`/`E002`/`E007` diagnostic'leri. +- `saqut symbols examples/fibonacci.sqt` → zengin tablo (her sembolün tipi, tanım + yeri, referansları). Forward reference çalışır (sonra tanımlı fonksiyon + çağrılabilir — `main`, `fibonacci`'yi çağırır). +- Hatalı örnekler → `E001`/`E002`/`E007`/`E010` diagnostic'leri. --- @@ -123,7 +159,7 @@ doğrula. İlgili ADR: 010, 013. | Dosya | İçerik | |---|---| -| `src/sema/type_checker.hpp/.cpp` | İfadeleri alttan üste gez, her `ExpressionNode`'a `resolvedType` ata. Gizli dönüşüm yok (ADR-010) → uyuşmazlıkta `E003`. Kontrol noktaları: atama (`=`), binary op operand tipleri, fonksiyon çağrısı argümanları (`E008`), array index, return değeri (`E006`), variable init tip uyumu. Hata olunca node'a `Type::error()` → ardışık sahte hata yok. | +| `src/sema/type_checker.hpp/.cpp` | İfadeleri alttan üste gez, her `ExpressionNode`'a `resolvedType` ata. Gizli **değişken→değişken** dönüşüm yok (ADR-010) → uyuşmazlıkta `E003`. **Tamsayı literali bağlama-göre tiplenir** (kayıpsızsa beklenen tipe uyar; `float x = 1;` geçerli, `int y = 1.5;` → `E003`). Kontrol noktaları: atama (`=`), binary op operand tipleri, fonksiyon çağrısı argümanları (`E008`), array index, return değeri (`E006`), variable init tip uyumu. Hata olunca node'a `Type::error()` → ardışık sahte hata yok. | | `src/sema/structural_validator.hpp/.cpp` | Parent pointer ile ağaç-tırmanma kontrolleri: `break`/`continue` döngü/switch içinde mi (`E004`), `return` fonksiyon içinde mi (`E005`), array boyutu sabit mi (`E009`). | ### Notlar @@ -148,7 +184,7 @@ optimizasyon. **Orijinali bozmaz — klon üstünde** (ADR-007). İlgili ADR: 00 |---|---| | `src/core/config.hpp` | `CompilerConfig`: pass toggle'ları (`optConstantFolding`, `optDeadCodeElim`, …), `outputFormat`, `mode`, `optimized` bayrağı. | | `src/opt/optimization_pass.hpp` | Soyut `OptimizationPass`: `virtual bool run(ASTNode* root, SymbolTable* table) = 0;` (değişiklik yaptıysa true). `name()`. | -| `src/opt/optimization_manager.hpp` | Pass listesi; `CompilerConfig`'e göre seçim; **fixpoint döngüsü** (hiçbir pass değişiklik yapmayana kadar). Çalışmadan önce AST'yi **klonlar** (`ASTNode::clone()` gerekebilir). | +| `src/opt/optimization_manager.hpp` | Pass listesi; `CompilerConfig`'e göre seçim; **fixpoint döngüsü** (hiçbir pass değişiklik yapmayana kadar + **sert iterasyon tavanı** `maxFixpointRounds`, ADR-009). **Sonlanma değişmezi:** havuzdaki pass'ler monoton (yalnızca küçültür); büyüten pass (inlining) eklenirse tavan zorunlu. Çalışmadan önce AST'yi **klonlar** — `ASTNode::clone()` **merkezi bir bileşendir** (ADR-007): parent pointer'lar yeniden bağlanır, sembol tablosu klonlanıp `IdentifierNode→Symbol` bağları **remap** edilir. **Her turda**, klon üzerinde akışa-bağlı analiz (`isReachable`, ref-count) **yeniden hesaplanır** (ADR-009); aksi halde zincirleme fırsatlar bayat veriyle kaçar. | | `src/opt/constant_folding.hpp/.cpp` | `BinaryExpression` operandları sabitse hesapla, sonucu sabit `Literal` ile değiştir (klonda). Tipe saygılı (`5/2`→int `2`, ADR-010). Sıfıra bölme → `W002`, katlama yapma. | | `src/opt/dead_code_elim.hpp/.cpp` | `isReachable` (Faz 3) işaretine göre: `return`/`break`/`continue` sonrası statement'lar, `if(false)`, sıfır-referanslı değişken (`W001`/`W003`). | @@ -174,6 +210,17 @@ Bu yol haritası bittiğinde frontend tamamlanmış olur: - Opsiyonel, incelenebilir optimizasyon. Sonraki adım (ayrı yol haritası): **IR güçlendirme** (kontrol akışı/fonksiyon/ -bellek opcode'ları, ADR-005/Issue 5.1) → **C transpile backend** → QBE → JIT -(ADR-001 sırası). Dinamik array'in runtime bellek modeli (ADR-014) backend -fazında kararlaştırılır. +bellek opcode'ları + **FFI seam** `callhost`, ADR-016) → **bytecode VM ile +çalıştırma** (ADR-015) → hedef: **`examples/fibonacci.sqt` derlenir ve çalışır.** + +- **Çalıştırma modeli IR + bytecode VM'dir** (ADR-015). **Makine-kodu JIT + açıkça kapsam dışıdır;** öncelik determinizm + incelenebilirlik, ham hız değil. +- **C transpile**, ileride geçerli bir **ikinci** backend olarak kalır (frontend + backend-bağımsız). Makine kodu gerçekten istenirse libgccjit/LLVM'e bağlanılır + — çok uzak gelecek. +- IR/VM tasarlanırken **FFI seam'i şimdiden bırak** (ADR-016); `print` ilk + müşteridir. Bellek host (C++) heap'idir; özel allocator yok. Dinamik array'in + runtime modeli (ADR-014) bu fazda netleşir. + +> Çerçeve uyarısı: bu sonraki adım da **önce dikey dilim** ilkesine tabidir — +> genel VM/optimizasyon altyapısı kurmadan önce fibonacci uçtan uca çalışsın. diff --git a/examples/fibonacci.sqt b/examples/fibonacci.sqt new file mode 100644 index 0000000..c78b7f9 --- /dev/null +++ b/examples/fibonacci.sqt @@ -0,0 +1,33 @@ +// saQut — geçerli örnek program (semantik analiz + kod üretimi fixture'ı) +// +// Kilitlenmiş tasarıma uyar: prosedürel, value semantics, kullanıcıya açık +// pointer yok, tek main, struct/array gerektirmez. Birinci kilometre taşının +// ("fibonacci'yi derle ve çalıştır") referans programıdır. +// +// İlk ifade doğrudan bir fonksiyon tanımı olabilir; zorunlu class/main +// boilerplate'i yoktur (Java'nın aksine). + +int fibonacci(int n) { + if (n <= 1) { + return n; + } + return fibonacci(n - 1) + fibonacci(n - 2); +} + +int fibonacciIterative(int n) { + int first = 0; + int second = 1; + for (int i = 0; i < n; i = i + 1) { + int next = first + second; + first = second; + second = next; + } + return first; +} + +int main() { + int n = 10; + print(fibonacci(n)); // recursive + print(fibonacciIterative(n)); // iterative + return 0; +} diff --git a/examples/Final.sqt b/examples/parser-stress/Final.sqt similarity index 100% rename from examples/Final.sqt rename to examples/parser-stress/Final.sqt diff --git a/examples/parser-stress/README.md b/examples/parser-stress/README.md new file mode 100644 index 0000000..be4d031 --- /dev/null +++ b/examples/parser-stress/README.md @@ -0,0 +1,21 @@ +# Parser Stres Fixture'ları + +Buradaki dosyalar **yalnızca parser/AST'yi zorlamak** için yazılmıştır. +**Geçerli saQut programı değildirler** ve semantik analiz / kod üretimi için +fixture olarak **kullanılmamalıdır**. + +## `Final.sqt` + +Tarihsel olarak parser'ın token/AST kapsamını test etmek için kullanıldı +(289 token, 200+ AST node). Ancak kilitlenmiş dil tasarımını birden çok yerde +**ihlal eder**: + +- **Kullanıcıya açık pointer kullanımı** (`struct List*`, `->`) — dilde `*`/`&` + yoktur (bkz. ADR-014). +- **Sabit boyutlu array** (`int arr[100]`) — array tipi `int[]`'tir, boyut tipin + parçası değildir (bkz. ADR-010). +- **İki `int main()` tanımı** — aynı scope'ta çift tanım yasaktır (ADR-011, `E002`). +- `printf` format-string semantiği — dilin builtin'i `print`'tir; format'lı + çıktı bir kütüphane/FFI işidir (bkz. ADR-017). + +Geçerli, küçük bir örnek için `examples/fibonacci.sqt`'ye bakın. diff --git a/readme.md b/readme.md index b37f806..aa29342 100644 --- a/readme.md +++ b/readme.md @@ -1,127 +1,185 @@ -# Syntax +# saQut -Syntax modunda 2 seçenek bulunmaktadır - - JIR: Söz dizimi tamamen Java programlama diline uygun olarak parse edilmektedir. Compiling, transpiling desteklenir Interpreter desteklenmez - - CIR: Söz dizimi tamamen C programlama diline uygun olarak parse edilir. Compiling ve Interpreter desteklenir. transpiling desteklenmez +**Programlanabilir, incelenebilir bir derleyici — bir "alet çantası" (toolbox).** -# Compiler short options +saQut'un asıl varlık sebebi dilin kendisinden çok, **derleme sürecinin her +aşamasının dışarıdan görülebilir ve müdahale edilebilir olmasıdır.** Token'lar, +AST, sembol tablosu, optimizasyonun öncesi/sonrası ve IR — hepsi ayrı ayrı +incelenebilir. Dil, bu aletin üzerinde çalıştığı küçük, prosedürel bir +örnektir; vitrin değil, alet. + +Uygulama dili **C++**'tır (header-only eğilimli, bkz. `docs/fikirler.md` ADR-003). + +--- + +## Şu an ne çalışıyor, ne çalışmıyor + +Belgeler **planlanan** ile **yapılan**ı net ayırır. Bugünkü gerçek durum: + +### ✅ Çalışıyor (built) +- **Lexer** — karakter seviyesi tarama, konum takibi. +- **Tokenizer** — token üretimi (6 token tipi), yorum satırı desteği. +- **Pratt parser** — ifade (Pratt) + statement (recursive descent) ayrıştırma. +- **AST** — fonksiyon, blok, değişken tanımı, if/for/while/do-while/return, + ifade node'ları. +- **AST'nin JSON serileştirmesi** — `saqut ast` ile incelenebilir. +- **CLI komut yapısı** — `tokens`, `ast`, `symbols`, `run` iskeletleri. +- **Kaynak konum takibi** (SourceLocation) — offset → (satır, sütun). +- **Minimal IR deneyi** — basit aritmetiği düşürür (örn. `1 + (7/3)` → kısa + doğrusal komut dizisi). Henüz tam bir backend değil, bir deneydir. + +### 🚧 Henüz yok (planned) +- Sembol tablosu +- Semantik analiz +- Tip sistemi +- Diagnostic (hata raporlama) motoru +- Optimizasyon +- IR + bytecode VM ile çalıştırma + +> `feature/frontend-analysis` dalı şu an yalnızca bu yapılmamış işin **tasarım +> belgelerini** içerir, kodunu değil. + +**Birinci kilometre taşı ("bitti" tanımı):** derleyici **fibonacci'yi** +(recursive + iterative) ve basit matematik/döngü programlarını **derleyip +çalıştırabilmeli.** Referans program: `examples/fibonacci.sqt`. + +--- + +## Dil kimliği (kilitli) + +Prosedürel, **C ailesi sözdizimi**, **value semantics**. İlk ifade doğrudan bir +işlem/tanım olabilir; zorunlu class/`main` boilerplate'i yoktur (Java'nın aksine). + +| Özellik | Karar | +|---|---| +| Class / OOP / kalıtım | **Yok** | +| Closure | **Yok** | +| Generic | **Yok** | +| Kullanıcıya açık pointer (`*` / `&`) | **Yok** — derleyici/runtime içeride pointer'ı serbestçe kullanır | +| `struct` | **Var** | +| Tipli fonksiyonlar (dönüş + parametre) | **Var** | +| Array (`int[]`) | **Var** | +| `interface` | **Ertelendi** (v0 değil — gerekçe ADR-018) | +| `auto` / tip çıkarımı | **Yok** | +| Gizli int↔float dönüşümü | **Yok** (tek istisna: sabit folding) | + +Gerekçe: prosedürel tasarım semantik karmaşıklığı en aza indirir ve hedeflerle +(fibonacci, matematik, sıralama, ayrıştırma) örtüşür. Standart C'de `class` +yoktur (o C++'tır); C, struct + fonksiyonun yettiğini kanıtlar. + +--- + +## Çalıştırma modeli (kilitli): IR + bytecode VM + +saQut, kendi **IR**'sine derler ve bu IR'yi bir **yorumlayıcı döngü (bytecode +VM)** ile çalıştırır. + +- **Tree-walker DEĞİL** (çok yavaş). +- **Gerçek makine-kodu JIT DEĞİL.** Makine kodu üretimi (register allocation, + ABI/çağırma sözleşmeleri, çalıştırılabilir `mmap` bellek) **kapsam dışıdır** — + tek faydası ham hızdır ve hız burada öncelik değildir. Öncelikler + **determinizm** ve **incelenebilirliktir**; bytecode VM ikisini de doğrudan + sağlar. +- **Bellek bu modelde kolaydır:** host (C++) heap'i kullanılır; v0 için özel + runtime allocator gerekmez. +- **C'ye transpile, geçerli bir İKİNCİ backend olarak ileride kalır** (frontend + backend-bağımsızdır — middle-end ayrımının amacı budur, ADR-006). İleride + makine kodu istenirse elle code generator yazmak yerine **libgccjit / LLVM'e + bağlanılır** — ama bu çok uzak gelecektir. + +> Eski belge/konuşmalarda geçen "JIT" terimi yanlış yönlendiricidir; doğru +> çerçeve **IR + VM**'dir. + +--- + +## Mimari hatlar ``` -sqt kaynak kodunu çallıştırır -saqut file:sourcecode.sqt - -sqt kaynak kodunu C koduna sonrada makine koduna derler. GCC gereklidir -saqut compile file:sourcecode.sqt output:program.exe - -Derleyicinin olduğu gibi çalıştırılması interpreter moduna alır, konsola yazılan kodları alır çalıştırır outputu loglar -saqut - -Derleyici kodu alır ve IR üretir -saqut parse file:sourcecode.sqt output:program.ces - -Derleyici IRyi alır ve çalıştırır. Burda kaynak kodu veya IR olup olmadığını otomatik anlar -saqut file:sourcecode.ces - -Derleyici IRyi veya kaynak kodunu alır C diline çevirir -saqut transpile file:sourcecode.ces output:program.c - -Derleyici kaynak kodu ASTsini çıkarır ve kaydeder -saqut file:sourcecode.sqt ast:sourcecode.xml +KAYNAK KOD + │ lexer + ▼ +TOKEN'LAR ────────────── saqut tokens + │ parser (Pratt + recursive descent) + ▼ +AST ──────────────────── saqut ast + │ sembol toplama (iki geçişli) ┐ + ▼ │ +SEMBOL TABLOSU ───────── saqut symbols │ FRONTEND + │ semantik analiz (annotation) │ (yapı + anlam) + ▼ │ +ANNOTATE EDİLMİŞ AST ─── saqut ast ┘ + │ optimizasyon (opsiyonel, klon üstünde) ── MIDDLE-END + ▼ +IR ───────────────────── (planlanan) ┐ + │ bytecode VM / yorumlayıcı döngü │ BACKEND + ▼ │ (çalıştırma + FFI seam) +ÇALIŞTIRMA / ÇIKTI ───── saqut run ┘ ``` +- **Frontend** yapıyı ve anlamı modeller (tip, scope, dataflow). +- **"Hangi çekirdek, hangi cihaz, ne zaman, hangi çıktı formatı"** runtime/backend + meselesidir — frontend'e yüklenmez. +--- -# Compiler Structure +## CLI (mevcut + planlanan) -## 1 Source Code +``` +# --- çalışıyor --- +saqut tokens file:kaynak.sqt # token listesi +saqut ast file:kaynak.sqt # AST (JSON) +saqut symbols file:kaynak.sqt # sembol tablosu (iskelet) -- Yazılan kaynak kodun derleyiciye aktarılması -- Derleyici için belirlenen seçenekler ile derleyici yapısının yeniden yapılandırılması -- Derleyicinin outputlarının ayarlanması ve çıkışlarının aktarılması +# --- planlanan --- +saqut run file:kaynak.sqt # IR üret + bytecode VM ile çalıştır +saqut ast file:kaynak.sqt --optimized # klon, optimize edilmiş AST (öncesi/sonrası) +saqut transpile file:kaynak.sqt -o prog.c # ikinci backend (ileride) +``` -## 2 Lexing +Tasarım gereği her aşamanın çıktısı erken bir noktada dosyalanabilir/loglanabilir +(programlanabilir derleyici). Token, ham AST, optimize AST ve IR ayrı ayrı +kaydedilebilir. -Kaynak kodun içindeki tüm harflerin gezilip tek parça büyük bir token listesinin oluşturulması +--- -Bu işlemin sonucunda kaynak kodun içindeki tüm yapılar; semboller, sayılar, stringler ve operatörler olarak 4 kategoriye ayrılır +## Batteries / stdlib — kuzey yıldızı, ertelendi -## 3 Tokenning +Gerçek bir genel sürüm pil ile gelmeli (sıralama, sıkıştırma, kripto, +JSON/XML/HTML ayrıştırma). Ama bu **bugünün işi ve v0.1 değildir.** -Tüm tokenler gezilerek bir Abstract Syntax Tree ağacı (AST) oluşturulur. Tek düze tokenler bu aşamada hiyerarşik olarak +Mimari çerçeve (monolit korkusunu önler): derleyici pilleri çekirdeğine +gömmez. Bunun yerine **küçük bir gerçek builtin kümesi** (`print`, temel +zorunlular) + **gerisi kütüphane/FFI** ile gelir. "Batteries" sorunu aslında +bir **sınır (FFI/link seam) sorunudur**, "zlib'i yeniden yaz" sorunu değil. +Sınır bir kez çizilir, piller üstünde sonsuza dek birikir. -File -> Class -> Methods -> Expressions / Statements -> Volumes -> Values +- **JSON/XML/HTML ayrıştırıcıları saQut'un kendisinde yazılabilir** (string + + struct + fonksiyon + kontrol akışı yeter). İlk gerçek demo programları. +- **Sıkıştırma/kripto:** denenmiş C kütüphanelerine FFI ile bağlan. **Kripto + asla elle yazılmaz.** +- **Bugüne tek yansıması:** IR/runtime tasarlanırken **bilinçli bir FFI seam** + ("host fonksiyonu çağır" deliği) bırakılır. `print` bunu zaten zorlar — bunu + kaza değil, **kasıtlı bir mekanizma** yapıyoruz (ADR-016). -Şeklinde bir ağaç yapısına kavuşur. Böylece yazılan kaynak kodu anlaşılır ilk yapısına kavuşur +--- -## 4 Parsing +## Belge haritası -Oluşturulan AST ağacı anlamlaştırılır ve zenginleştirilir. Tanımlanan değerler, fonksiyonlar, classler ve değişkenler belirlenir. Tip kontrolleri ve Syntax hataları burada keşfedilir. Ayrıca Ulaşılamayan kod alanları, sınıfların ulaşılamayan (private) accessorları kontrol edilir, tüm bir kod boyunca class, tipleme, değişken ve döngülerin kullanım adetleri analiz edilir. Sistem içinde kullanılan tüm yapılar için geniş kapsamlı bir Symbol tablosu oluşturulur +| Belge | İçerik | +|---|---| +| `docs/fikirler.md` | ADR-001…005: backend stratejisi, parser, header-only, token, IR | +| `docs/adr-frontend-analiz.md` | ADR-006…019: frontend, analiz/optimizasyon, çalıştırma modeli, FFI, interface, bellek | +| `docs/roadmap-frontend.md` | Faz-faz uygulama planı (sembol tablosu → fibonacci) | +| `docs/transkript-frontend-tasarim.md` | Tasarım oturumunun transkripti | +| `examples/fibonacci.sqt` | Geçerli referans program (semantik + kod üretimi fixture'ı) | +| `examples/parser-stress/` | Yalnızca parser'ı zorlayan, **geçerli olmayan** fixture'lar | -## 5 Optimizing +--- -Zenginleştirilmiş AST üzerindeki analizler üzerinden bazı AST dalları silinir, değiştirilir veya yeni dallar eklenebilir +## İlke -- Constant Folding : 4 + 1 gibi sonucu belli olan ifadeler 5 olarak tutulur -- Dead Code Elimination : returnden sonraki kod bloğunun silinmesi veya if(false) ve dengi statementlerin yapıdan kaldırılması -- Matematiksel olarak değişmez kodların kaldırılması x * 1, x+0, x * 1 gibi valuelerin direkt x olarak değiştirilmesi -- Hiç kullanılmayan değişkenlerin kaldırılması -- Sabit (const) değerlerin döngülerin dışına çıkarılması veya programın globaline taşınması -- Null Check Elimination : Daha önce nullcheck yapılmış bir değişkenin tekrar nullcheck yapılan kontrollerini devredışı bırakmak -- Type Check Elimination : Daha önce typecheck yapılmış bir değişkenin tekrar typecheck yapılan kontrollerini devredışı bırakmak - -## 6 Compiling - -Oluşturulmuş tüm AST ağacını tamamen aynı işi yapan daha alt bir veri kümesine indirgeme işidir. Bellekteki AST yapısı ardışık komutlar dizisine çevrilir (Intermediate Representation) IR daha sonra tekrar okunup çalıştırılabilir. - -Daha sonra IR ile kurulacak yapı ile bazen HeavyIR bazende LightIR üretilir. -LightIR, en temiz ve hızlı ancak hiç bir ayrıntı içermeyen koddur. Kaynak kodun çalıştırılması için mükemmel veridir ancak debug verilerinden yoksundur -HeavyIR, kaynak kodu verilerinin yanı sıra orjinal AST üzerinde tanımlanmış değişken isimleri ayrıntıları ve tiplemeleride içerir. LightIRye göre daha ayrıntılı ve büyüktür ancak debugging ve kaynak kodun parça parça okunduğu durumlar için (örneğin interpreter) kullanışlıdır - -## 7 Interpreting - -Derleyici HeavyIR üretir ve Symbol tablosunu silmez. -Optimizasyonların çoğu kapatılır. -Oluşturulmuş HeavyIR kodu çalıştırılır çalışma bittikten sonra stackframe kapatılmaz yeni girişler beklenir. Yeni kaynak kodu girişleri yapıldığında yine derlenir ve anında çalıştırılır. Yeni çalıştırılan kaynak kodu bir önceki stackframe içersinde symbol tablosu dikkate alınarak output üretir böylece önceki değerler halen kullanılabilir - -## or 7 Executing - -Derleyici LightIR üretir IR oluşturulduktan sonra symbol tablosu silinir. -Üretilen IR otomatize edilmiş bellekte yüksek performans ile çalıştırılır. - -Derleyici o an ürettiği kaynak kodu anında çalıştırdığı (JIT) gibi -Daha önce üretilmiş ve depolanmış IR kodunuda çalıştırabilir - -## or 7 Transpiling - -Derleyici HeavyIR üretir ve Symbol tablosunu silmez. -Derleyici IR üretmez bunun yerine AST Üzerinden yeni bir dile çevrilir. -Duruma göre daha üst bir seviye dile dönüşüm yapıldığı gibi daha alt bir dile dönüşüm yapılabilir. IR üretilmez bunun yerine alınan kaynak kodu farklı bir kaynak koduna çevrilir - -# programmable compiler - -Derleyici tek seferde kaynak kodu alıp okuyup çalıştırabilir veya derleyebilir. -Ayrıca debug ortamlarında veya daha ayrıntılı projelerde derleme anına müdehale edilebilir - -## Stage Session - -Derleyiciye verilen bazı parametreler ile Lexer ve Tokenizer anında bazı işlemlerin yapılması engellenebilir -Örneğin accessorler kapatılabilir, hexedecimal sayılar kapatılabilir. Veya class olmadan globale yazılmış kodlar engellenebilir - -## AST Session - -Derleyiciye verilen bazı parametreler ile class yapılarına müdehale edilebilir, tipleme sistemleri sabitlenebilir, tek bir metot içerisine yazılacak kod sınırlanabilir veya for içerisinde for döngüsü kısıtlanabilir. Yazılan kod için analizler sonucunda bazı bloklar görmezden gelinebilir veya manipüle edilebilir - -## Optimizing Session - -Optimizasyon aşamaları parametreler ile tek tek açılabilir veya kapatılabilir - -## Output Session - -Derleyici ürettiği veriyi erken bir aşamada dosyalayabilir ve loglayabilir. -Derleyicinin oluşturduğui token, Pure AST, Optimized AST, LightIR veya HeavyIR ayrı ayrı kaydedilebilir - -## Compiling Session - -AST ağacını IRye dönüştürürken neleri aktaracağı derleyici parametre şeklinde verilebilir. -IR, yanlızca JIT ve Compiling modunda değiştirilebilir. Interpreter modunda değiştirilmesine izin verilmez -IR olarak tipleme, sınıflar, değişken isimleri, tekrarlama kayıtları, işlemler ve statementlerin hangilerinin eklenebileceği değiştirilebilir \ No newline at end of file +Bir şey çalışmadan önce çerçeve inşa etmekten kaçın. Önce **uçtan uca tek bir +dikey dilim** çalıştır (kaynak → IR → çalıştır; tamsayı aritmetiği + değişken + +kontrol akışı + tek bir `print`). Modülerlik bir kuzey yıldızıdır, v0.1 +gereksinimi değil; ihtiyaç doğmadan eklenen her soyutlama **daha az değil, daha +çok** karmaşıklıktır. From 1232748f9fa1e5905d709bb5bcb03a42687fc1a4 Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Sun, 14 Jun 2026 22:44:30 +0300 Subject: [PATCH 03/28] =?UTF-8?q?chore:=20Gitea=20issue=20y=C3=B6netim=20b?= =?UTF-8?q?etikleri=20ekle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Faz 0-4 ve gelecek vizyonu issue'larını oluşturmak için kullanılan yardımcı betikler (gitea.py API istemcisi + issue içerikleri). Co-Authored-By: Claude Sonnet 4.6 --- scripts/create_future_issues.py | 560 +++++++++++++++++++++++++++ scripts/create_issues.py | 160 ++++++++ scripts/create_syntax_test_issues.py | 499 ++++++++++++++++++++++++ 3 files changed, 1219 insertions(+) create mode 100644 scripts/create_future_issues.py create mode 100644 scripts/create_issues.py create mode 100644 scripts/create_syntax_test_issues.py diff --git a/scripts/create_future_issues.py b/scripts/create_future_issues.py new file mode 100644 index 0000000..e8700a9 --- /dev/null +++ b/scripts/create_future_issues.py @@ -0,0 +1,560 @@ +#!/usr/bin/env python3 +"""Faz 0-4 sonrasi icin vizyon/backlog issue'lari. + +Bu issue'lar PLAN degildir; fikir/tartisma kayitlaridir. Faz issue'larindan +(#69-73) farkli olarak "Sonuc ve Basari Kriterleri" / "Muhendis olmayan analiz" +bolumleri yoktur - bunun yerine "Acik Sorular" bolumu vardir. Iceriklerin +zamanla degismesi beklenir. +""" +from gitea import make_request, REPO_PATH + +L_FIKIR = 66 +L_IRVM = 67 +L_MODUL = 68 +L_TIP = 69 +L_FFI = 70 +L_TOOLING = 71 +L_VIZYON = 72 + +issues_data = [ + # ---------------- IR & Bytecode VM ---------------- + { + "title": "[Fikir] IR Komut Seti Tasarımı (Üç-Adresli Kod / Three-Address Code)", + "labels": [L_FIKIR, L_IRVM], + "body": """### Giriş (Nedir, Neden Önemli?) +Faz 0-4 bitince AST (Abstract Syntax Tree, Soyut Sözdizimi Ağacı) tip ve sembol bilgisiyle dolu olacak. Ama AST hâlâ "ağaç" — VM'in (Bytecode VM, Bayt Kodu Sanal Makinesi) çalıştırabileceği düz bir komut listesi değil. Bu issue, AST'den üretilecek **IR'in (Immediate Representation, Ara Temsil)** komut setini tartışır. + +--- + +### Gelişme (Olası Yaklaşımlar) +- **Üç-adresli kod (three-address code):** `t1 = a + b`, `t2 = t1 * c` gibi her komut en fazla bir işlem yapar. Okunabilirlik (alet çantası felsefesiyle uyumlu — `saqut ir` ile basılabilir) ile uygulama kolaylığı arasında iyi bir denge. +- Minimal opcode ailesi: aritmetik (`add/sub/mul/div`), karşılaştırma, atama (`store/load`), kontrol akışı (`jump/jump_if_false/label`), fonksiyon (`call/return`), dizi/struct erişimi (`get_field/set_field/get_index/set_index`). +- Her IR komutu kaynak `SourceLocation`'ı taşımalı — hata mesajları ve "öncesi/sonrası" karşılaştırması için (alet çantası amacı). +- `examples/fibonacci.sqt` için elle IR çıktısı yazılıp hedef format netleştirilebilir (taslak doküman olarak). + +--- + +### Açık Sorular +- Üç-adresli kod mu, yoksa stack-tabanlı (yığın tabanlı) bir ara form mu daha basit olur? (VM tasarımıyla bağlantılı, bkz. ilgili issue) +- Struct/array gibi değer-semantikli (value semantics) tipler IR seviyesinde nasıl temsil edilir — kopyalama ne zaman gerçek bir IR komutu olur? +- Optimizasyon (Faz 4) pass'leri AST üzerinde mi kalır, yoksa IR seviyesine de mi taşınır? + +*İmza/Yorum:* Bu issue, "IR güçlendirme" yol haritasının (roadmap-frontend.md sonu) ilk taslağıdır. Faz 0-4 bitmeden kilitli karar alınmamalı — sadece beyin fırtınası.""" + }, + { + "title": "[Fikir] IR'in Serileştirilmesi ve İncelenebilirliği (`saqut ir` komutu)", + "labels": [L_FIKIR, L_IRVM], + "body": """### Giriş (Nedir, Neden Önemli?) +saQut'un varlık sebebi "her aşamanın dışarıdan görülebilir olması". Token, AST ve sembol tablosu zaten `saqut tokens/ast/symbols` ile JSON olarak görülebiliyor. IR de aynı muameleyi görmeli. + +--- + +### Gelişme (Olası Yaklaşımlar) +- `saqut ir file:kaynak.sqt` komutu: AST'den üretilen IR'i hem **insan-okur metin** (örn. assembly benzeri `t1 = a + b`) hem de **JSON** (`--format=json`) olarak basar. +- `--optimized` bayrağıyla optimizasyon öncesi/sonrası IR yan yana (diff) gösterilebilir — Faz 4'teki AST öncesi/sonrası karşılaştırmasının IR karşılığı. +- Her IR komutuna kaynak satır/sütun referansı eklenip, IR'den kaynağa "geri işaretleme" (source map benzeri) yapılabilir — ileride debugger için temel oluşturur. + +--- + +### Açık Sorular +- IR metin formatı kendi mini-sözdizimi mi olacak, yoksa mevcut JSON şemasının bir uzantısı mı? +- IR dump'ı dosyaya yazılıp tekrar VM'e beslenebilir mi (round-trip) — bu, derleme adımlarını birbirinden bağımsız test etmeyi kolaylaştırır. + +*İmza/Yorum:* Bu, "programlanabilir derleyici" vaadinin IR ayağı. Küçük ama saQut'un kimliği için sembolik önemde.""" + }, + { + "title": "[Fikir] Bytecode Formatı: Yığın-Tabanlı mı (Stack-based), Register-Tabanlı mı VM?", + "labels": [L_FIKIR, L_IRVM], + "body": """### Giriş (Nedir, Neden Önemli?) +ADR-015 çalıştırma modelini kilitledi: IR + bytecode VM (yorumlayıcı döngü), gerçek makine-kodu JIT yok. Ama VM'in *iç mimarisi* henüz seçilmedi: **yığın-tabanlı (stack-based, Python/JVM/Wasm tarzı)** mi, **register-tabanlı (Lua 5'in VM'i tarzı, sanal register'lar)** mı? + +--- + +### Gelişme (Olası Yaklaşımlar) +- **Yığın-tabanlı:** Komutlar değer push/pop eder (`push a`, `push b`, `add`). Üretmesi basit, IR'den bytecode'a çeviri kolay. Dezavantaj: gereksiz push/pop'lar (performans, ama saQut için öncelik değil — bkz. ADR-015 "determinizm/incelenebilirlik > hız"). +- **Register-tabanlı:** Her fonksiyonun sanal register'ları olur (`add r1, r2, r3`). Daha az komut, ama derleyici tarafı (register allocation - kayıt tahsisi) daha karmaşık. +- saQut'un önceliği **basitlik + incelenebilirlik** olduğu için yığın-tabanlı VM ile başlamak "önce dikey dilim" ilkesine daha uygun olabilir; register-tabanlı'ya geçiş ileride bir "VM v2" issue'su olabilir. + +--- + +### Açık Sorular +- Yığın-tabanlı seçilirse, fonksiyon çağrıları için ayrı bir "call stack" mı, tek bir birleşik yığın mı kullanılır? +- Debug/inceleme modunda her adımdan sonra yığının tam içeriği dump edilebilir mi (alet çantası vaadiyle doğrudan ilişkili)? + +*İmza/Yorum:* Bu karar IR komut setini (önceki issue) doğrudan etkiler — birlikte tartışılmalı. Önerim: v0 için yığın-tabanlı, basitliği ve incelenebilirliği önceliklendirdiği için.""" + }, + { + "title": "[Fikir] VM Yorumlayıcı Döngüsü ve Dispatch Stratejisi", + "labels": [L_FIKIR, L_IRVM], + "body": """### Giriş (Nedir, Neden Önemli?) +Bytecode VM'in kalbi, her komutu okuyup ilgili işlemi yapan "yorumlayıcı döngü" (interpreter loop / dispatch loop). Bu döngünün nasıl yazılacağı hem performansı hem de kod okunabilirliğini etkiler. + +--- + +### Gelişme (Olası Yaklaşımlar) +- **Switch-case dispatch:** `switch(opcode) { case ADD: ...; case JUMP: ...; }`. En basit, en okunabilir, derleyici bağımsız (portable). saQut'un "incelenebilir" felsefesiyle en uyumlu başlangıç noktası. +- **Computed goto / jump table:** Daha hızlı ama derleyiciye özel uzantılar gerektirir (GCC/Clang `&&label`), taşınabilirlik düşer. Hız öncelik değilse (ADR-015) v0'da gereksiz karmaşıklık. +- **Threaded code:** Her IR komutunu doğrudan bir C++ fonksiyon pointer'ına çeviren ileri teknik — şimdilik kapsam dışı. +- v0 önerisi: basit switch-case + her adımda "trace" modu (her komut çalışmadan önce/sonra durum dump edilebilir, ADR-016 FFI seam ile `print` zaten bu yola hazırlanıyor). + +--- + +### Açık Sorular +- Yorumlayıcı tek bir `run()` fonksiyonu mu olacak, yoksa her opcode için ayrı `handle_*` fonksiyonu mu (okunabilirlik vs. fonksiyon çağrı maliyeti — ama maliyet öncelik değil)? +- Adım-adım çalıştırma (step) ve "tüm programı çalıştır" (run) aynı döngüyü mü paylaşacak? + +*İmza/Yorum:* "Önce dikey dilim" ilkesi burada da geçerli: en basit switch-case ile fibonacci çalışsın, optimize dispatch ileri bir konu.""" + }, + { + "title": "[Fikir] Fonksiyon Çağrı Mekanizması ve Call Frame Tasarımı", + "labels": [L_FIKIR, L_IRVM], + "body": """### Giriş (Nedir, Neden Önemli?) +`examples/fibonacci.sqt` özyinelemeli (recursive) bir fonksiyon. VM'in fonksiyon çağrılarını (call/return), parametreleri ve yerel değişkenleri nasıl tuttuğu — yani **call frame (çağrı çerçevesi)** tasarımı — özyinelemenin doğru çalışması için kritik. + +--- + +### Gelişme (Olası Yaklaşımlar) +- Her fonksiyon çağrısında bir "frame" oluşturulur: dönüş adresi, parametreler, yerel değişkenler için ayrılan yer. Bu frame'ler bir "call stack" üzerinde tutulur (host C++ heap'i üzerinde — ADR-015, özel allocator yok). +- Özyinelemeli çağrılar (fibonacci(n-1), fibonacci(n-2)) her biri kendi frame'ine sahip olmalı — değişkenler birbirine karışmamalı (scope-based memory model, ADR-014). +- Maksimum çağrı derinliği (stack overflow koruması) — basit bir sayaç/limit ile "stack taşması" hatası verilebilir (yeni bir E-kodu olabilir, ileride katalogla birleştirilir). + +--- + +### Açık Sorular +- Frame boyutu derleme zamanında mı (compile-time, fonksiyonun yerel değişken sayısına göre) hesaplanır, yoksa dinamik mi büyür? +- Fonksiyon dönüş değeri yığının üstüne mi konur (yığın-tabanlı VM ile uyumlu), yoksa ayrı bir "return register" mı kullanılır? + +*İmza/Yorum:* Bu issue VM tasarımı (önceki issue) seçimine bağımlıdır; ama fibonacci'nin "bitti" tanımı (recursive + iterative) bu mekanizma olmadan anlamsızdır — birinci öncelikli IR/VM konusu.""" + }, + { + "title": "[Fikir] Array ve Struct'ların Runtime Bellek Düzeni", + "labels": [L_FIKIR, L_IRVM], + "body": """### Giriş (Nedir, Neden Önemli?) +Dil kimliği `struct` ve `int[]` (array/dizi) içeriyor, value semantics (değer semantiği) ile. VM çalışırken bu değerlerin bellekte nasıl yer alacağı — kopyalama ne zaman olur, struct içinde struct/array nasıl saklanır — netleşmeli. + +--- + +### Gelişme (Olası Yaklaşımlar) +- Value semantics demek: `struct Point p2 = p1;` ifadesi `p1`'in **tam kopyasını** oluşturur (referans değil). VM'de bu, struct'ın tüm alanlarının yığın/heap'te kopyalanması anlamına gelir. +- Array boyutu derleme zamanında sabit mi (E009 hatası bunu zaten kontrol ediyor), yoksa dinamik büyüyebilen bir array tipi de mi olacak (`std::vector` benzeri, host heap üzerinde)? +- Struct içinde struct: iç içe value-copy maliyeti büyüyebilir — ama saQut'ta "hız öncelik değil" (ADR-015), önce doğruluk. + +--- + +### Açık Sorular +- Dinamik boyutlu array (`int[]` boyutu çalışma zamanında belirlenen) v0 kapsamında mı, yoksa v1'e mi bırakılır? +- Struct kopyalama IR'de tek bir "copy" komutu mu olur, yoksa alan-alan kopyalama komut dizisine mi açılır (incelenebilirlik açısından ikincisi daha "alet çantası" uyumlu olabilir)? + +*İmza/Yorum:* ADR-014'teki "scope-based bellek artık gerekçeli" notuyla doğrudan ilişkili — bu issue o kararın runtime'a yansımasıdır.""" + }, + { + "title": "[Fikir] IR Seviyesinde Kontrol Akışı Grafiği (CFG) ve SSA — Gerekli mi?", + "labels": [L_FIKIR, L_IRVM], + "body": """### Giriş (Nedir, Neden Önemli?) +Çoğu "gerçek" derleyici (GCC, LLVM) IR'i bir **CFG (Control Flow Graph, Kontrol Akışı Grafiği)** üzerinde **SSA (Static Single Assignment, Statik Tekil Atama)** formunda tutar. Bu, ileri optimizasyonları (constant propagation, dead code elimination'ın güçlü hali) çok kolaylaştırır ama ciddi bir mühendislik yatırımıdır. + +--- + +### Gelişme (Olası Yaklaşımlar) +- saQut'un Faz 4 optimizasyonları (constant folding, dead code elimination) şu an **AST üzerinde** çalışıyor ve bu yeterli olabilir — CFG/SSA şart değil. +- CFG/SSA'nın getirisi: döngü içindeki optimizasyonlar, daha güçlü dead-code analizi. Maliyeti: yeni bir ara temsil katmanı, "basit kalsın" ilkesiyle gerilim yaratabilir. +- Orta yol: basit IR (üç-adresli kod, lineer komut listesi + `jump`/`label`) yeterli olduğu sürece CFG/SSA'ya **geçilmez**; ancak optimizasyon ihtiyaçları büyürse (örn. döngü-invariant kod taşıma) bu issue tekrar açılır. + +--- + +### Açık Sorular +- "Yeterlilik" sınırı nasıl ölçülür? Belki: fibonacci + birkaç döngü/dizi örneği optimize edildiğinde gözle görülür iyileşme varsa CFG/SSA'ya gerek yoktur. +- CFG olmadan da basit "basic block" (temel blok) kavramı IR'e eklenebilir mi (sadece jump hedeflerini gruplamak için, SSA olmadan)? + +*İmza/Yorum:* Bu issue kasıtlı olarak "yapma" eğiliminde — erken soyutlama riskine karşı bir hatırlatma (roadmap'teki "önce dikey dilim" ilkesi).""" + }, + # ---------------- Moduller / Import ---------------- + { + "title": "[Fikir] Import Sözdizimi ve Modül Çözümleme", + "labels": [L_FIKIR, L_MODUL], + "body": """### Giriş (Nedir, Neden Önemli?) +Şu ana kadar tüm tasarım **tek dosyalı** programları (`examples/fibonacci.sqt`) hedefliyor. Ama gerçek projeler birden fazla dosyaya bölünür. saQut'a "başka bir dosyadaki fonksiyon/struct'ı kullan" diyebilmek için bir **import (içe aktarma)** sözdizimi gerekir. + +--- + +### Gelişme (Olası Yaklaşımlar) +- En basit model: `import "util.sqt"` — dosya yolu tabanlı, C'nin `#include`'una benzer ama metin yapıştırma değil, **sembol tablosu seviyesinde birleştirme** (her dosya kendi AST'sine sahip kalır, sembol çözümleme dosyalar arası genişler). +- Alternatif: isim-tabanlı modül sistemi (`import util` → `util.sqt` veya `util/` dizini arar), Go/Python tarzı. +- saQut'ta `class`/namespace yok — modül adı, dosya adına eşlenebilecek doğal bir "isim alanı" (namespace) adayı olabilir: `util.helper()` gibi nokta-erişimi. + +--- + +### Açık Sorular +- Döngüsel import (A, B'yi; B, A'yı import ediyor) nasıl ele alınır — derleme hatası mı, yoksa forward-declaration ile mi çözülür (ADR-011'deki forward-reference mantığına benzer)? +- Import edilen dosyanın AST'si her derlemede yeniden mi ayrıştırılır, yoksa bir "derleme birimi cache"i mi olur (LSP issue'suyla bağlantılı)? + +*İmza/Yorum:* Bu, "Faz 5: Modüller" için doğal bir başlangıç noktası olabilir — ama Faz 0-4 (tek dosya, fibonacci) bitmeden ele alınmamalı.""" + }, + { + "title": "[Fikir] Modüller Arası Görünürlük (public/private) ve İsim Çakışmaları", + "labels": [L_FIKIR, L_MODUL], + "body": """### Giriş (Nedir, Neden Önemli?) +İmport sistemi geldiğinde, "her şey her yerden görülebilir mi" sorusu ortaya çıkar. Bu, sembol tablosunun (Faz 2) modüller arası nasıl genişletileceğiyle doğrudan ilgili. + +--- + +### Gelişme (Olası Yaklaşımlar) +- En basit kural: bir dosyadaki **tüm üst-seviye tanımlar** (fonksiyon, struct, global değişken) import eden dosyaya açık olur — "herkese açık" (public-by-default), C'nin extern'siz fonksiyonlarına benzer. Basitlik açısından v0 için cazip. +- Daha kontrollü model: `private` anahtar kelimesi ile bir dosyaya özel tanımlar işaretlenebilir — ama bu, dil kimliğine yeni bir anahtar kelime ekler (ADR'lerle uyumlu mu tartışılmalı). +- İsim çakışması (iki modülde aynı isimde fonksiyon): modül-öneki (`util.process()`) zorunlu kılınarak çözülebilir — bu, import sözdizimi issue'suyla birlikte kararlaştırılmalı. + +--- + +### Açık Sorular +- "Herkese açık" model, sembol tablosunun global scope'unu modüller arasında nasıl birleştirir — her modül kendi global scope'una mı sahip olur, yoksa tek bir "program-geneli" scope mu? +- Bu karar E002 (çift tanım) hatasının kapsamını değiştirir mi — aynı isim iki modülde tanımlanırsa hata mı, yoksa öneklemeyle ayrışır mı? + +*İmza/Yorum:* Önerim: v0 için "herkese açık, modül-önekiyle eriş" — basit ve declare-before-use (ADR-011) felsefesiyle tutarlı.""" + }, + { + "title": "[Fikir] Çoklu Dosya Derleme ve Bağımlılık Sırası", + "labels": [L_FIKIR, L_MODUL], + "body": """### Giriş (Nedir, Neden Önemli?) +Import sistemi geldiğinde, `saqut run main.sqt` komutu artık tek dosya değil, bir **bağımlılık ağacı** (dependency graph) derlemek zorunda kalır. Bu issue, CLI ve derleme akışının (pipeline) buna nasıl uyacağını tartışır. + +--- + +### Gelişme (Olası Yaklaşımlar) +- Derleyici önce tüm `import` ifadelerini tarayıp bir **dosya bağımlılık grafiği** çıkarır (basit DFS/topological sort — ADR-011'deki struct çevrim kontrolüyle aynı algoritmik aile). +- Her dosya kendi AST'sine ve (Faz 2 sonrası) kendi sembol tablosu parçasına sahip olur; sembol çözümleme son adımda birleştirilir. +- "Programlanabilir derleyici" felsefesiyle: `saqut ast --module=util.sqt` gibi tek bir modülün AST'si de ayrı incelenebilir kalmalı — çoklu dosya derleme tek-dosya inceleme yeteneğini kırmamalı. + +--- + +### Açık Sorular +- Döngüsel bağımlılık (önceki issue'da bahsedilen) burada nasıl raporlanır — yeni bir E-kodu mu (örn. `E011`)? +- Derleme çıktısı (IR/bytecode) tek bir birleşik dosya mı olur, yoksa modül-başına ayrı IR mi üretilip VM'de "link" edilir (gerçek linker'lara benzer ama çok daha basit)? + +*İmza/Yorum:* Bu konunun karmaşıklığı yüksek olabilir — "önce dikey dilim" ilkesi burada özellikle geçerli: tek-dosya fibonacci bitmeden bu issue'ya başlanmamalı.""" + }, + # ---------------- Tip Sistemi Genişletmeleri ---------------- + { + "title": "[Fikir] Native Decimal Tipi (Ondalıklı Sayılarda Hassasiyet)", + "labels": [L_FIKIR, L_TIP], + "body": """### Giriş (Nedir, Neden Önemli?) +`float`/`double` ikili (binary) kayan-nokta sayılardır ve ondalık kesirleri (örn. `0.1`) tam temsil edemez — bu, para/finans hesaplamalarında hatalara yol açar. Birçok modern dil (C#, Python `Decimal`) bunun için ayrı bir **decimal (ondalık) tip** sunar. + +--- + +### Gelişme (Olası Yaklaşımlar) +- `decimal` yeni bir primitif `TypeKind` olarak `src/core/type.hpp`'ye eklenebilir (Faz 0'ın `Type` sınıfı genişletilebilir tasarlanmalı — bu issue o genişletilebilirliği şimdiden akılda tutmak için var). +- Runtime temsili: sabit-noktalı (fixed-point) tamsayı + ölçek (scale) çifti (örn. "scaled integer" — `12345` ve ölçek `2` → `123.45`). Host heap'te basit bir struct olarak tutulabilir, özel kütüphane gerekmez (v0). +- Literal Adaptasyon Kuralı (ADR-010) ile ilişki: `decimal x = 1;` geçerli olmalı (tamsayı → decimal kayıpsız); `decimal x = 1.5;` (float literal → decimal) hassasiyet tartışması gerektirir. + +--- + +### Açık Sorular +- `decimal` aritmetiği (`+`, `*`) için taşma (overflow) kuralları ne olacak — hata mı, yoksa otomatik büyüme mi (bu, "host heap, özel allocator yok" ADR-015 ilkesiyle gerilim yaratabilir)? +- Bu tip v0.1'in parçası mı, yoksa "batteries" (ADR-017) kapsamında ileride bir FFI/kütüphane çözümü mü? + +*İmza/Yorum:* "Modern dillerin standart hale getirdiği ama derleyici çekirdeğine gömülmesi gereken" tiplerin ilk örneği — kullanıcı isteğiyle doğrudan örtüşüyor.""" + }, + { + "title": "[Fikir] Native Date/Time (Tarih/Zaman) Tipi", + "labels": [L_FIKIR, L_TIP], + "body": """### Giriş (Nedir, Neden Önemli?) +Tarih/zaman, hemen her gerçek programda karşılaşılan ama yanlış yapılması çok kolay bir konudur (saat dilimleri, artık yıllar, formatlar). Modern diller (Go, Rust, JS `Temporal`) bunu standart kütüphaneye/derleyiciye yakın tutar. + +--- + +### Gelişme (Olası Yaklaşımlar) +- v0 için minimal yaklaşım: `date`/`datetime` yeni bir primitif tip olarak değil, **struct olarak saQut'un kendisinde** tanımlanabilir (`struct Date { int year; int month; int day; }`) — bu, "batteries = FFI/kütüphane sınırı" (ADR-017) felsefesiyle örtüşür ve derleyici çekirdeğine yük bindirmez. +- Daha ileri: gerçek saat/takvim hesapları (örn. "bugünden 30 gün sonrası") host sisteminden FFI (ADR-016, `callhost`) ile alınabilir — saat dilimi/takvim mantığı saQut içine yazılmaz, denenmiş bir C kütüphanesine (örn. sistem `time.h`) bağlanır. +- Eğer ileride performans/ergonomi nedeniyle native bir `date` tipi gerekirse, bu issue "native tip mi, struct+FFI mi" kararının kaydı olarak kalır. + +--- + +### Açık Sorular +- "Şu anki zaman" gibi dış-dünya bağımlı bilgi nasıl elde edilir — bu doğrudan FFI seam'in (`print` sonrası) ikinci gerçek kullanım örneği olabilir mi? +- Tarih aritmetiği (`tarih + 5 gün`) operatör overload'ı gerektirir mi — ama dilde operatör overload yok (kilitli karar); bu çatışmayı nasıl çözeriz (fonksiyon: `addDays(d, 5)`)? + +*İmza/Yorum:* Önerim: v0'da struct+FFI, native tip değil — "batteries boundary" ilkesinin ikinci somut test vakası.""" + }, + { + "title": "[Fikir] Enum (Sabit Kümesi) Desteği", + "labels": [L_FIKIR, L_TIP], + "body": """### Giriş (Nedir, Neden Önemli?) +Şu anki dil kimliğinde `enum` yok. Ama "renk", "durum", "yön" gibi sabit bir küme içinden değer alan değişkenler çok yaygındır ve bunları `int` ile temsil etmek (örn. `0=KIRMIZI, 1=MAVI`) hem hata-eğilimli hem de okunaksızdır. + +--- + +### Gelişme (Olası Yaklaşımlar) +- En basit model: `enum Renk { KIRMIZI, MAVI, YESIL }` — derleme zamanında `int`'e eşlenen adlandırılmış sabitler. Tip denetimi (Faz 3) açısından `Renk` ayrı bir `TypeKind` (ya da struct'a benzer adlandırılmış-tip) olarak ele alınabilir; `int`'le gizli dönüşüm yasak (ADR-010 ile tutarlı — `Renk x = 0;` yerine `Renk x = KIRMIZI;`). +- `switch`/`match` ile birlikte düşünülürse (dilde şu an `switch` yok, sadece `if`) enum'un asıl gücü ortaya çıkar — bu issue, ileride bir `switch` tartışmasını da tetikleyebilir. +- Struct'lara ek yük getirmez, sembol tablosuna (Faz 2) yeni bir `SymbolKind::EnumValue` eklenmesi yeterli olabilir. + +--- + +### Açık Sorular +- Enum değerleri sadece `int` mi temsil eder, yoksa ileride `string` etiketli enum (örn. JSON serileştirmede yararlı) da düşünülür mü? +- `interface` gibi enum da "ertelendi" listesine mi girer, yoksa v0.1'e (fibonacci sonrası ilk gerçek dil-genişletmesi) yakın bir öncelik mi? + +*İmza/Yorum:* Düşük karmaşıklıkta, yüksek günlük-kullanım faydası olan bir özellik — "fibonacci sonrası ilk küçük kazanımlar" listesine iyi bir aday.""" + }, + { + "title": "[Fikir] String'in İç Temsili ve Unicode/UTF-8 Stratejisi", + "labels": [L_FIKIR, L_TIP], + "body": """### Giriş (Nedir, Neden Önemli?) +`string` tipi dil kimliğinde var ama "string nedir" sorusu (bayt dizisi mi, karakter dizisi mi, UTF-8 mi) henüz hiç tartışılmadı. Bu karar, `length()`, indeksleme (`s[0]`), ve dosya/konsol I/O'sunun davranışını doğrudan belirler. + +--- + +### Gelişme (Olası Yaklaşımlar) +- **UTF-8 bayt dizisi (Go/Rust tarzı):** En basit runtime temsili (host C++ `std::string`'e doğrudan eşlenir, ADR-015 "host heap" ilkesiyle uyumlu). Ama `s[0]` bir bayt döner, bir "karakter" değil — Türkçe karakterler (ç, ş, ğ) çok-baytlı olduğundan indeksleme kafa karıştırabilir. +- **Kod-noktası (code point) dizisi:** Her "karakter" tek birim — daha sezgisel ama dönüşüm/depolama maliyeti var. +- v0 önerisi: UTF-8 bayt temsilini benimse (C++'la doğal uyum), ama `length()`/indeksleme dokümantasyonunda "bayt sayısı/bayt indeksi" olduğu açıkça yazılsın — ileride `runeAt()`/`codepointLength()` gibi yardımcı builtin'lerle (ADR-016/017) kod-noktası erişimi sağlanabilir. + +--- + +### Açık Sorular +- String **immutable (değişmez)** mi olacak (Java/Python tarzı, value-semantics ile de uyumlu) yoksa mutable mi? +- String birleştirme (`+`) ve karşılaştırma operatörleri tip denetiminde (Faz 3) nasıl ele alınacak — `string + int` gizli dönüşüm mü (ADR-010 "gizli dönüşüm yok" ile çatışır, muhtemelen `E003`)? + +*İmza/Yorum:* Bu karar ne kadar erken alınırsa, sonraki tüm builtin/stdlib tasarımı (özellikle JSON/XML parser örnekleri, ADR-017) o kadar sağlam temellenir.""" + }, + # ---------------- FFI / Builtin / Stdlib ---------------- + { + "title": "[Fikir] FFI Seam Detaylı Tasarımı — `callhost` İmzası ve Tip Eşleme (Marshaling)", + "labels": [L_FIKIR, L_FFI], + "body": """### Giriş (Nedir, Neden Önemli?) +ADR-016, "host fonksiyonu çağır" (FFI — Foreign Function Interface, Yabancı Fonksiyon Arayüzü) mekanizmasının **kasıtlı** bir tasarım kararı olduğunu, `print`'in ilk müşterisi olacağını söylüyor. Ama mekanizmanın somut hali (fonksiyon imzası, parametre/dönüş tipi eşlemesi) henüz tasarlanmadı. + +--- + +### Gelişme (Olası Yaklaşımlar) +- VM'de bir `callhost ` IR/bytecode komutu: argümanlar yığından alınır, C++ tarafındaki kayıtlı bir fonksiyon tablosuna (`std::map`) bakılır, sonuç yığına geri konur. +- Tip eşleme: saQut `int`/`float`/`string`/`bool` değerleri C++ `int`/`double`/`std::string`/`bool`'a nasıl çevrilir (marshaling) — basit primitiflerle başlamak ("önce dikey dilim"), struct/array marshaling'i ileri bir adım olarak bırakmak. +- Hata yönetimi: host fonksiyon başarısız olursa (örn. dosya bulunamadı) bu, saQut tarafına nasıl yansır — bir hata kodu mu, yoksa `panic` benzeri bir çalışma-zamanı hatası mı (yeni runtime hata kategorisi gerekebilir)? + +--- + +### Açık Sorular +- Host fonksiyon tablosu derleme zamanında mı sabit (yalnızca derleyicinin sunduğu `print` gibi fonksiyonlar), yoksa kullanıcı kendi C++ fonksiyonunu kayıt edebilir mi (gömülü/embeddable derleyici senaryosu — "alet çantası" ruhuna çok uygun ama kapsam büyütür)? +- `callhost` IR seviyesinde mi, yoksa daha yüksek seviyeli bir AST-annotation mı (Faz 1'in `ExpressionNode` alanlarına eklenebilir)? + +*İmza/Yorum:* `print(fibonacci(n))` çalıştığı gün, bu issue'nun "v0" kapsamı fiilen tamamlanmış olacak — minimal hedef gayet net.""" + }, + { + "title": "[Fikir] Builtin Fonksiyon Kataloğu ve Çözümleme Mekanizması", + "labels": [L_FIKIR, L_FFI], + "body": """### Giriş (Nedir, Neden Önemli?) +`print` ilk builtin (yerleşik) fonksiyon. Ama "builtin" kelimesinin derleyici içinde nasıl bir yeri olacağı — sembol tablosunda mı, ayrı bir kayıt defterinde mi — henüz netleşmedi. Bu issue, `print`'ten sonra gelecek `len`, `toString`, `parseInt` gibi fonksiyonların **sistematik** bir şekilde eklenmesini planlar. + +--- + +### Gelişme (Olası Yaklaşımlar) +- Faz 2'nin Symbol Table'ı (sembol tablosu) başlangıçta "önceden tanımlı" (pre-defined) bir global scope ile kurulabilir — her builtin, kullanıcı kodu hiç okunmadan önce bu scope'a `SymbolKind::Function` olarak eklenir. Böylece `print(x)` çağrısı normal bir fonksiyon çağrısı gibi tip denetiminden (Faz 3) geçer. +- Builtin kataloğu merkezi bir dosyada (`src/runtime/builtins.hpp` gibi) tek listede tutulur: isim, parametre tipleri, dönüş tipi, ve VM'deki karşılığı (FFI üzerinden mi, yoksa doğrudan bir IR opcode'u mu). +- İlk aday liste (fibonacci sonrası "küçük kazanımlar"): `print`, `len` (string/array uzunluğu), `toString` (sayıdan string'e), `parseInt`/`parseFloat`. + +--- + +### Açık Sorular +- Builtin'ler kullanıcı tarafından **gölgelenebilir (shadow)** mi — yani kullanıcı kendi `print` fonksiyonunu tanımlarsa ne olur (muhtemelen `E002` çift tanım, ama global scope'ta builtin'lerle çakışma ayrı ele alınmalı)? +- Builtin kataloğu büyüdükçe (örn. 50+ fonksiyon), bunların hepsi "her zaman yüklü" mü olacak, yoksa modül sistemi (ayrı issue) ile "import edilen" bir stdlib mantığına mı evrilecek? + +*İmza/Yorum:* `print`'in nasıl çözümlendiğini doğru kurmak, sonraki tüm builtin'lerin şablonu olacak — bu yüzden bu issue erken (Faz 2-3 sırasında) gündeme gelmeli.""" + }, + { + "title": "[Fikir] Minimal Stdlib Seti (String/Math/Koleksiyon Yardımcıları)", + "labels": [L_FIKIR, L_FFI], + "body": """### Giriş (Nedir, Neden Önemli?) +ADR-017 "batteries = sınır problemi" diyor ve JSON/XML/HTML gibi parser'ların saQut'un kendisinde yazılabileceğini söylüyor. Ama bunlar için bile bir **minimal temel** (string birleştirme, karşılaştırma, sayı↔string dönüşümleri, dizi üzerinde gezinme yardımcıları) gerekir. Bu issue, "demo programları yazılabilir olması için gereken en küçük stdlib" kümesini tanımlar. + +--- + +### Gelişme (Olası Yaklaşımlar) +- **String:** `length(s)`, `substring(s, start, end)`, `charAt(s, i)`, `concat(a, b)` (veya `+` operatörü), `equals(a, b)`. +- **Sayı:** `toString(n)`, `parseInt(s)`, `parseFloat(s)`, `abs`, `min`, `max`. +- **Array:** `length(arr)`, belki `append`/`push` (dinamik array tartışmasına bağlı — ayrı issue). +- Hepsi builtin kataloğu (önceki issue) üzerinden, ya doğrudan IR opcode'u ya da FFI (`callhost`) ile saç host C++ standart kütüphanesine (``, ``) yaslanır — "asla elle yeniden yazma" (ADR-017, kripto örneğiyle aynı ilke string/math için de geçerli). + +--- + +### Açık Sorular +- Bu set "derleyiciye gömülü" mü olmalı (her zaman hazır) yoksa ileride bir "standart modül" (`import std`) olarak mı paketlenmeli — import sistemi (ayrı issue) ile zamanlama ilişkisi var. +- JSON parser demo'su (ADR-017'de bahsedilen) için bu listenin yeterli olup olmadığı, demo yazılmaya başlandığında netleşecek. + +*İmza/Yorum:* "Fibonacci çalıştı" milestone'undan sonraki ikinci somut hedef belki de "stdlib ile küçük bir JSON parser demo'su" olabilir — bu issue o hedefin ön koşullarını listeliyor.""" + }, + # ---------------- Tooling: LSP / Syntax Highlighting ---------------- + { + "title": "[Fikir] LSP (Language Server Protocol) Sunucusu Mimarisi", + "labels": [L_FIKIR, L_TOOLING], + "body": """### Giriş (Nedir, Neden Önemli?) +**LSP (Language Server Protocol, Dil Sunucusu Protokolü)**, editörlerin (VS Code, Neovim vb.) "kırmızı çizgi göster", "tanıma git", "otomatik tamamla" gibi özellikleri standart bir protokolle derleyiciden alabilmesini sağlar. saQut'un "incelenebilir derleyici" felsefesi, LSP için aslında olağanüstü bir başlangıç noktası: AST, sembol tablosu ve diagnostic'ler zaten JSON olarak dışa açık. + +--- + +### Gelişme (Olası Yaklaşımlar) +- LSP sunucusu, saQut derleyicisinin **üstüne** yazılan ayrı bir süreç (process) olabilir — derleyici çekirdeğini bir kütüphane (library) olarak kullanır, stdin/stdout üzerinden JSON-RPC (LSP'nin temel protokolü) ile editörle konuşur. +- En kritik performans sorunu: editördeki her tuş vuruşunda **tüm dosyayı yeniden derlemek** pahalıdır. "Incremental parsing" (artımlı ayrıştırma) veya en azından "değişen fonksiyonu yeniden derle" gibi bir strateji gerekir — ama bu, v0'ın çok ilerisinde bir konu. +- "Önce dikey dilim": LSP'nin ilk versiyonu sadece `DiagnosticEngine`'in (Faz 0) çıktısını "hover/error squiggle" olarak göstermekle başlayabilir — tüm dosyayı her kaydette yeniden derlemek v0 için yeterli olabilir. + +--- + +### Açık Sorular +- LSP sunucusu aynı C++ binary'sinin bir modu mu (`saqut lsp`) olacak, yoksa tamamen ayrı bir proje mi? +- "Tanıma git" (go-to-definition) özelliği doğrudan Faz 2'nin Symbol Table'ındaki `definitionLoc`/`references` alanlarından besleniyor — bu alanların LSP ihtiyaçlarına göre yeterli olup olmadığı (örn. cross-file references, modül sistemi geldiğinde) kontrol edilmeli. + +*İmza/Yorum:* "Derleyici tamamlandıktan sonra" diye düşünülecek bir konu ama Faz 2'nin sembol tablosu tasarımı şimdiden bunu destekleyecek şekilde (her referansın konumu kayıtlı) kurulursa, LSP'ye geçiş çok daha az acı verir.""" + }, + { + "title": "[Fikir] Syntax Highlighting (Sözdizimi Renklendirme) Grameri", + "labels": [L_FIKIR, L_TOOLING], + "body": """### Giriş (Nedir, Neden Önemli?) +Editörlerde `.sqt` dosyalarının renkli görünmesi (anahtar kelimeler, string'ler, yorumlar farklı renkte) geliştirici deneyiminin en temel parçalarından biri — ve LSP'den bağımsız, çok daha basit bir kazanım. + +--- + +### Gelişme (Olası Yaklaşımlar) +- **TextMate grameri** (VS Code'un kullandığı, regex-tabanlı `.tmLanguage.json`): saQut'un tokenizer'ındaki (Tokenizer) 6 token tipinden (`docs` belgelerine göre) yola çıkarak basit bir regex seti yazılabilir — derleyiciden bağımsız, statik bir dosya. +- **Tree-sitter grameri:** Daha güçlü (gerçek bir parser üretir, hata-toleranslı), ama saQut'un kendi Pratt parser'ından ayrı bir gramer tanımı gerektirir — bakım yükü iki ayrı "dil tanımı" demektir. +- v0 önerisi: TextMate grameri (en düşük efor, en hızlı görsel kazanım) — `saqut tokens` çıktısı referans alınarak anahtar kelimeler/operatörler/literal'ler renklendirilir. + +--- + +### Açık Sorular +- Bu gramer, tokenizer'daki token tanımları değiştiğinde **elle senkronize** mi tutulacak, yoksa `saqut tokens --dump-grammar` gibi bir komutla **otomatik üretilebilir** mi (programlanabilir derleyici felsefesiyle çok uyumlu bir fikir)? +- Hedef editör önceliği ne olacak — VS Code (TextMate) mı, Neovim/Helix (Tree-sitter ekosistemi daha güçlü) mı? + +*İmza/Yorum:* Bu, listedeki **en düşük efor / en yüksek "keyif" oranına** sahip issue'lardan biri — derleyici bitmeden bile, sadece tokenizer çıktısından üretilebilir.""" + }, + { + "title": "[Fikir] `saqut fmt` — Otomatik Kod Biçimlendirici (Formatter)", + "labels": [L_FIKIR, L_TOOLING], + "body": """### Giriş (Nedir, Neden Önemli?) +`gofmt`, `rustfmt`, `prettier` gibi araçlar artık modern bir dilin "olmazsa olmaz"ı haline geldi: kod her zaman aynı şekilde biçimlenir, "stil tartışmaları" ortadan kalkar. saQut'un AST'si zaten JSON'a serileştirilebiliyor — bu, bir formatter için iyi bir temel. + +--- + +### Gelişme (Olası Yaklaşımlar) +- `saqut fmt file:kaynak.sqt`: dosyayı ayrıştırır (AST), AST'yi **kanonik bir şekilde** tekrar kaynak koda yazdırır (pretty-printer / AST → metin). +- Yorumların (comment) korunması en zor kısım — AST yorum bilgisini taşımıyorsa (Faz 0-1 sırasında bu netleşmeli), formatter yorumları silebilir veya yanlış yere koyabilir. Bu, **AST tasarımına şimdiden not edilmesi gereken bir kısıt.** +- "Öncesi/sonrası" felsefesiyle: `saqut fmt --check` (CI'da kullanılabilir — "bu dosya zaten formatlı mı?") ve `saqut fmt --write` (dosyayı yerinde değiştir) ayrımı yapılabilir. + +--- + +### Açık Sorular +- Pretty-printer, AST'den mi yoksa doğrudan token akışından mı (yorumlar dahil tüm token'lar tokenizer'da zaten tutuluyor) üretilmeli — token-tabanlı yaklaşım yorum-koruma sorununu çözebilir. +- Biçimlendirme kuralları (girinti, boşluk, satır uzunluğu) nasıl ve nerede sabitlenecek — `docs/` altında bir "stil kılavuzu" mu yazılacak? + +*İmza/Yorum:* AST tasarımı (Faz 1) sırasında "yorumlar AST'de nasıl temsil edilir" sorusu bu issue'yu doğrudan etkiler — şimdiden not düşülmeye değer bir bağımlılık.""" + }, + # ---------------- Gelecek Vizyonu / Deneysel ---------------- + { + "title": "[Fikir] Zaman-Yolculuğu Hata Ayıklama (Time-Travel Debugging) — IR Anlık Görüntüleri", + "labels": [L_FIKIR, L_VIZYON], + "body": """### Giriş (Nedir, Neden Önemli?) +saQut'un "her aşama incelenebilir" felsefesi VM çalışma zamanına da taşınabilir: VM her IR komutunu çalıştırdığında **tüm değişken/yığın durumunun anlık görüntüsünü (snapshot)** kaydederse, kullanıcı programı "ileri-geri sarabilir" — modern debugger'larda (rr, Chrome DevTools "time travel") popüler ama çoğu küçük dilde olmayan bir özellik. + +--- + +### Gelişme (Olası Yaklaşımlar) +- VM'in yorumlayıcı döngüsüne (ilgili issue) bir "trace modu" eklenir: her adımda (komut, önceki durum, sonraki durum) bir listeye/dosyaya yazılır. +- `saqut run file --trace=trace.json` → `saqut replay trace.json` gibi bir akış: kullanıcı adım adım ileri/geri gidebilir, herhangi bir adımdaki değişken değerlerini görebilir. +- Bellek modeli basit olduğu için (host heap, özel allocator yok — ADR-015) snapshot almak büyük bir teknik engel değil; asıl maliyet disk/bellek kullanımıdır (büyük döngülerde trace çok büyüyebilir — örnekleme/limit gerekebilir). + +--- + +### Açık Sorular +- Trace formatı IR serileştirmesiyle (ilgili issue) aynı JSON şemasını mı paylaşmalı? +- Bu özellik "VM v1"in parçası mı, yoksa tamamen ayrı bir "saqut debug" aracı mı? + +*İmza/Yorum:* Bu, "alet çantası" felsefesinin VM çalışma zamanına en doğal uzantısı — diğer küçük dillerde nadiren bulunan, saQut'u **ayırt edici** kılabilecek bir özellik.""" + }, + { + "title": "[Fikir] Derleyici Playground — WebAssembly'e Derleyip Tarayıcıda Çalıştırma", + "labels": [L_FIKIR, L_VIZYON], + "body": """### Giriş (Nedir, Neden Önemli?) +Rust/Go/TypeScript gibi dillerin "playground" siteleri (tarayıcıda kod yaz, çalıştır, AST/derleme adımlarını gör) hem öğretim hem de tanıtım için çok güçlü bir araç. saQut'un C++ çekirdeği **WebAssembly (Wasm)**'a derlenebilirse (Emscripten ile), tüm derleyici tarayıcıda çalışabilir — sunucu gerekmez. + +--- + +### Gelişme (Olası Yaklaşımlar) +- Emscripten ile `saqut` binary'si bir `.wasm` + JS "glue" koduna derlenir. Web sayfası bu Wasm modülünü yükler, kullanıcı kodunu derleyiciye verir. +- saQut'un CLI komutları (`tokens`, `ast`, `symbols`, ileride `ir`, `run`) zaten JSON döndürdüğü için, web arayüzü bu JSON'ları görselleştirir — örneğin AST'yi bir ağaç diyagramı olarak çizmek. +- "Önce dikey dilim, sonra çerçeve" ilkesiyle: bu issue, derleyicinin **kendisi** tamamlanmadan ele alınmaması gereken, ama CMake yapılandırmasına (ADR-003, header-only) Wasm hedefinin **erkenden uyumlu** olup olmadığının kontrol edilmesi gereken bir konudur. + +--- + +### Açık Sorular +- Wasm derlemesi CI'a (varsa) eklenir mi — "her commit'te playground güncel" gibi bir otomasyon hedefi olur mu? +- Playground sadece görüntüleme mi yapar, yoksa `saqut run` ile gerçek **çalıştırma** da (VM tamamlandıktan sonra) tarayıcıda mümkün olur mu? + +*İmza/Yorum:* "Keyif veren" kategorisinin tipik örneği — teknik olarak büyük bir engel yok (C++ → Wasm olgun bir yol), ama önceliği derleyici çekirdeğinden sonra gelmeli.""" + }, + { + "title": "[Fikir] Dil-İçi Test Bloğu (`test { }`) ve Yerleşik Test Çalıştırıcı", + "labels": [L_FIKIR, L_VIZYON], + "body": """### Giriş (Nedir, Neden Önemli?) +Rust'ın `#[test]` ve Go'nun `_test.go` dosyaları gibi, modern diller test yazmayı dilin/araç zincirinin **bir parçası** haline getiriyor. saQut için de "fonksiyonumu yazdım, hemen yanına küçük bir test ekleyeyim" akışı düşünülebilir — derleyicinin kendi `examples/fibonacci.sqt` gibi referans programlarını doğrulaması için bile yararlı olur. + +--- + +### Gelişme (Olası Yaklaşımlar) +- Sözdizimi fikri: `test "fibonacci(5) dogru sonucu verir" { assert(fibonacci(5) == 5); }` — `test` ve `assert` yeni anahtar kelimeler/builtin'ler olarak eklenir. +- `saqut test file:kaynak.sqt`: dosyadaki tüm `test` bloklarını çalıştırır, `assert` başarısız olursa hangi test/satır olduğunu raporlar (DiagnosticEngine'in bir "test sonucu" varyantı gibi düşünülebilir). +- Bu özellik aslında `assert` builtin'i (FFI/builtin kataloğu issue'suyla ilişkili) + basit bir "bu bloğu normal akıştan ayrı çalıştır" kuralı kadar küçük olabilir — büyük bir çerçeveye gerek yok. + +--- + +### Açık Sorular +- `test` blokları normal derlemede (`saqut run`) tamamen yok sayılır mı (production kodundan ayrışma), yoksa özel bir bayrakla mı dahil edilir? +- Bu, dilin **sözdizimine** mi (yeni anahtar kelime) yoksa sadece bir **kütüphane fonksiyonu** (`assert(...)` + isim kuralına dayalı dosya/fonksiyon tarama) düzeyinde mi kalmalı — ikincisi dil kimliğini (kilitli kararlar) bozmaz. + +*İmza/Yorum:* "Günümüzde frameworklerde olan ama derleyiciye gömülü gelebilecek" taleplere iyi bir örnek — minimal versiyonu (`assert` builtin'i) çok düşük maliyetli.""" + }, + { + "title": "[Fikir] Paket Yöneticisi / Modül Kayıt Defteri (Registry) Vizyonu", + "labels": [L_FIKIR, L_VIZYON], + "body": """### Giriş (Nedir, Neden Önemli?) +Modül sistemi (ayrı issue) "aynı projede birden fazla dosya" sorusunu çözer. Ama "başka birinin yazdığı bir saQut kütüphanesini projeme nasıl eklerim" sorusu bir **paket yöneticisi** gerektirir (npm, cargo, go modules tarzı). Bu, şu an çok uzak bir vizyon ama erken not edilmeye değer. + +--- + +### Gelişme (Olası Yaklaşımlar) +- En minimal hali: `import "https://git.saqut.com/.../util.sqt"` gibi URL-tabanlı import (Go'nun ilk modül modeline benzer) — merkezi bir registry gerektirmez, ADR-017'deki "FFI/kütüphane sınırı" felsefesiyle uyumlu (saQut çekirdeği paket yönetimini bilmez, sadece dosya/URL okur). +- Daha "gerçek" hali: `saqut.toml` gibi bir manifest dosyası, bağımlılık sürümleri, kilit dosyası (lock file) — bu, derleyici çekirdeğinden tamamen ayrı bir CLI aracı (`saqut-pkg`) olarak düşünülebilir, çekirdeği şişirmez. +- saQut'un "alet çantası" kimliği burada bir fırsat sunuyor: paket yöneticisi, saQut'un kendisiyle yazılabilecek bir **dogfooding** (kendi aracını kendi diliyle yazma) projesi olabilir — ama bu, dilin dosya I/O ve string işleme (stdlib issue'ları) yeterince olgunlaştıktan sonra mümkün. + +--- + +### Açık Sorular +- Bu vizyon, projenin "küçük/incelenebilir alet çantası" kimliğiyle ne kadar uyumlu — paket ekosistemi büyüdükçe "monolit korkusu" (ADR-017) geri gelir mi? +- Merkezi bir registry (sunucu, hosting maliyeti) gerçekten gerekli mi, yoksa Git-tabanlı/URL-tabanlı dağıtık model yeterli mi? + +*İmza/Yorum:* En "uzak gelecek" issue'lardan biri — ama "import sistemi" tasarlanırken (örn. URL desteği baştan düşünülürse mi, sonradan mı eklenir) bu vizyonun gölgesi düşebilir, o yüzden şimdiden not.""" + }, + { + "title": "[Fikir] Akıllı Diagnostic — Hata Mesajlarına \"Neden\" ve \"Nasıl Düzeltilir\" Ekleme", + "labels": [L_FIKIR, L_VIZYON], + "body": """### Giriş (Nedir, Neden Önemli?) +Faz 0'ın `Diagnostic` yapısında zaten bir `hint` (ipucu) alanı planlanıyor. Bu issue, o alanın **nasıl** dolduğunu ve modern derleyicilerin (Rust, Elm) "hata mesajı bir öğretmen gibi konuşur" felsefesini saQut'a nasıl taşıyabileceğimizi tartışır — yapay zeka kullanmadan, tamamen kural-tabanlı (rule-based). + +--- + +### Gelişme (Olası Yaklaşımlar) +- Her hata kodu (`E001`...`E010`) için, hata mesajına ek olarak **statik bir "neden" şablonu** ve mümkünse **"şunu dener misin"** önerisi eklenir. Örnek: `E003` (tip uyuşmazlığı) → "saQut'ta değişkenler arası gizli dönüşüm yapılmaz (bkz. ADR-010); `int` bir değeri `float` değişkene atamak için ... yapabilirsiniz." +- Bu şablonlar `docs/adr-frontend-analiz.md`'deki kararlarla **doğrudan bağlantılı** olabilir — hata mesajı, ilgili ADR'nin "neden"ini özetleyen bir cümle içerebilir. Bu, dökümantasyon ile derleyici çıktısını birbirine bağlar (saQut'un "her şey ilişkili ve incelenebilir" ruhuna uygun). +- Elm tarzı "did you mean...?" (yazım hatası önerisi): tanımsız isim hatasında (`E001`), sembol tablosundaki (Faz 2) benzer isimli sembollere Levenshtein-mesafesi gibi basit bir algoritmla öneri sunulabilir — küçük, eğlenceli, yüksek-etkili bir özellik. + +--- + +### Açık Sorular +- Bu zenginleştirilmiş mesajlar `DiagnosticEngine`'in (Faz 0) temel yapısına mı gömülür, yoksa ayrı bir "mesaj kataloğu" dosyası mı olur (çeviri/yerelleştirme ihtimaline de açık kapı bırakır)? +- "Did you mean" önerisi performans maliyeti yaratır mı (her hata için sembol tablosu taraması) — büyük projelerde sorun olur mu? + +*İmza/Yorum:* Bu, derleyicinin "kullanıcıyla konuşma tarzını" belirleyen, teknik olarak küçük ama **algıyı** çok değiştirebilecek bir issue — Faz 0 bittiğinde, kataloğa hint şablonları eklemek ucuz bir ek iştir.""" + }, +] + +for issue in issues_data: + endpoint = f"{REPO_PATH}/issues" + res = make_request(endpoint, method="POST", data=issue) + print(f"Created issue #{res['number']}: {res['title']}") diff --git a/scripts/create_issues.py b/scripts/create_issues.py new file mode 100644 index 0000000..6d4aa98 --- /dev/null +++ b/scripts/create_issues.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python3 +import sys +from gitea import make_request, REPO_PATH + +issues_data = [ + { + "title": "Faz 0 — Tip Sistemi ve Hata Kayıt Motoru (Type & Diagnostics)", + "body": """### Giriş (Nedir, Neden Yapıyoruz?) +Bu iş paketinde derleyicinin çalışması için en temel iki altyapıyı kuracağız: Tip Sistemi (Type System) ve Hata Kayıt/Diagnostic Motoru. +Tip Sistemi, derleyicinin kaynak koddaki verileri (sayılar, metinler vb.) anlamlandırabilmesi ve tür doğruluğunu denetleyebilmesi için gerekli veri yapısını sağlar. +Hata Kayıt Motoru ise derleme sırasında oluşan hataları (örneğin tip uyuşmazlığı veya tanımsız değişken kullanımı) biriktirip, kullanıcıya hatanın kaynak koddaki tam yerini (dosya, satır, sütun koordinatları) göstererek raporlayan mekanizmadır. Bu yapı sayesinde derleyici ilk bulduğu hatada hemen durmayacak, tüm hataları toplayıp tek seferde kullanıcıya sunacaktır. + +--- + +### Gelişme (Neyi, Nerede ve Nasıl Yapacaksın?) +Aşağıdaki adımları sırasıyla gerçekleştir: +1. **Tip Yapısı:** `src/core/type.hpp` adında yeni bir dosya oluştur. Burada `TypeKind` (Primitive, Array, Struct, Function, Error) enum sınıfını ve `Type` sınıfını tanımla. Primitif türler için `int`, `float`, `double`, `char`, `string`, `bool`, `void` alt tiplerini destekle. Dizi (Array) türü için eleman tipini (`elementType`), fonksiyon için dönüş ve parametre tiplerini taşıyacak alanlar ekle. `equals()` ve `toString()` gibi metotları implement et. +2. **Hata Yapısı:** `src/diagnostic/diagnostic.hpp` dosyasını oluştur. Burada hata seviyelerini (`Error`, `Warning`, `Note`, `Hint`) içeren `DiagLevel` enum sınıfını ve hatanın koordinatlarını tutan `Diagnostic` yapısını tanımla. +3. **Diagnostic Kataloğu:** Aynı dosyada derleyicide oluşabilecek hata kodlarını içeren kataloğu (örneğin `E001` - Tanımsız Değişken, `E002` - Çift Tanım, `E003` - Tip Uyuşmazlığı, `E010` - Döngüsel Struct Tanımı vb.) sabitle. +4. **DiagnosticEngine:** `src/diagnostic/diagnostic_engine.hpp` dosyasını oluştur. `DiagnosticEngine` sınıfı hataları bir vektörde biriktirmeli, `report()` metoduyla yeni hata almalı ve `printAll()` ile bunları ekrana formatlı yazmalıdır. + +*Geliştirme Dalı (Branch):* `feature/faz0-temeller` + +--- + +### Sonuç ve Başarı Kriterleri +Bu işin bittiğini ve başarılı olduğunu şu kriterlerle doğrulayacağız: +1. `Type::equals()` metodu için yazılan birim testler (Unit Tests) farklı tip kombinasyonlarını (örneğin `int` ile `int` eşit, `int` ile `float` veya `int[]` farklı) hatasız doğrulamalıdır. +2. `DiagnosticEngine` sınıfına 3 farklı hata raporlanıp `printAll()` çağrıldığında, çıktıda hata kodları (`E001` vb.) ve kaynak kod satır/sütun koordinatları doğru sırayla ve biçimde ekrana yazılmalıdır. +3. Derleyici uyarısız (`-Wall -Wextra`) derlenmelidir. + +*Mühendis Olmayanlar İçin Analiz:* Bu aşama derleyicinin arka planındaki veri yapılarını kurduğu için görsel bir çıktı üretmez, ancak sonraki tüm aşamaların temelidir. Karmaşıklığı **Düşük**, yapım süresi yaklaşık **1-2 gün**dür. +*İmza/Yorum:* Bu altyapı semantik analizin (Faz 3) hata raporlayabilmesi için kritik önkoşuldur.""" + }, + { + "title": "Faz 1 — AST Hiyerarşisinin Refaktörü (Expression ve Statement Ayrımı)", + "body": """### Giriş (Nedir, Neden Yapıyoruz?) +Bu iş paketinde, derleyicinin kaynak kodu okuduktan sonra hafızada oluşturduğu Soyut Sözdizimi Ağacı (Abstract Syntax Tree - AST) düğümlerini yeniden yapılandıracağız. +Şu anda tüm AST düğümleri tek bir `ASTNode` taban sınıfından türemektedir. Ancak anlamsal olarak iki farklı düğüm türü vardır: +1. **Expression (İfade):** Bir değer üreten yapılar (örneğin `5 + 3` veya değişken isimleri). Bunların bir veri tipi (Type) olur. +2. **Statement (Deyim):** Bir değer üretmeyen, sadece bir iş/eylem yürüten kontrol yapıları (örneğin `if` bloğu, döngüler veya `return`). Bunların tipi yoktur ancak erişilebilirlik (reachability) durumları analiz edilir. +Bu iki yapıyı birbirinden ayırmak, sonraki aşamada tip denetimi yapabilmemiz için zorunludur. + +--- + +### Gelişme (Neyi, Nerede ve Nasıl Yapacaksın?) +Aşağıdaki adımları sırasıyla gerçekleştir: +1. **Ara Taban Sınıflarını Ekle:** `src/parser/ast_node.hpp` dosyasına `ExpressionNode` ve `StatementNode` adında iki yeni sınıf ekle. `ExpressionNode` sınıfına `resolvedType` (çözümlenmiş tip), `isConstant` ve `foldedValue` (optimizasyon için) alanlarını koy. `StatementNode` sınıfına ise `isReachable` (erişilebilirlik bayrağı) alanını ekle. +2. **Düğümleri Güncelle:** `src/parser/nodes/` dizinindeki tüm dosyaları tara. `LiteralNode`, `BinaryExpressionNode`, `IdentifierNode`, `CallExpressionNode` gibi değer üreten tüm sınıfları `ExpressionNode`'dan türet. `IfStatementNode`, `WhileStatementNode`, `ReturnStatementNode` vb. sınıfları ise `StatementNode`'dan türet. +3. **Çocuk Gezintisini Düzelt:** AST taban sınıfındaki `getChildren()` metodunun alt sınıflar tarafından ezilmesini (override) sağla. Örneğin `BinaryExpressionNode` sınıfında `Left` ve `Right` düğümlerini dinamik olarak `getChildren()` içinde döndür. Bu, genel ağaç gezginlerinin (Tree Walker) alt düğümleri eksiksiz taramasını sağlayacaktır. +4. **toJson Modifikasyonu:** `toJson()` metotlarını güncelleyerek yeni alanları (çözümlenmiş tip ve erişilebilirlik bilgileri) JSON çıktısına ekle. + +*Geliştirme Dalı (Branch):* `feature/faz1-ast-refactor` + +--- + +### Sonuç ve Başarı Kriterleri +Bu işin bittiğini ve başarılı olduğunu şu kriterlerle doğrulayacağız: +1. `saqut ast examples/fibonacci.sqt` komutu çalıştırıldığında üretilen JSON çıktısında, ifadeler için `resolvedType` alanı (boş olarak) ve deyimler için `isReachable` alanı (true olarak) görünmelidir. +2. JSON yapısının doğruluğu `python3 -m json.tool` ile test edildiğinde hiçbir parse hatası vermebelidir (regresyon testi). +3. Tüm kodlar uyarısız derlenmelidir. + +*Mühendis Olmayanlar İçin Analiz:* Bu aşama mevcut veri yapısını daha düzenli hale getirir. Dışarıdan bakıldığında JSON çıktısında yeni alanlar görülür. Karmaşıklığı **Düşük-Orta**, yapım süresi yaklaşık **2 gün**dür. +*İmza/Yorum:* Düğüm alanlarındaki `children` vektörü tutarsızlığı bu fazda tamamen çözülmeli, ağaçta yukarı ve aşağı gezinme API'si garanti altına alınmalıdır.""" + }, + { + "title": "Faz 2 — Sembol Tablosu ve İki Geçişli Toplama (Scope & Symbol Table)", + "body": """### Giriş (Nedir, Neden Yapıyoruz?) +Bu iş paketinde derleyicinin \"Hafızası\" sayılan Sembol Tablosunu (Symbol Table) kuracağız. +Sembol Tablosu, kaynak koddaki değişkenlerin, fonksiyonların ve veri yapılarının (struct) tanımlarını, veri tiplerini, hangi kapsamlarda (Scope) geçerli olduklarını ve kodun neresinde kullanıldıklarını (referanslarını) takip eden bir veri yapısıdır. +Dilimiz, tanımlanmadan önce fonksiyon çağrılmasına izin verdiği için (ileri başvuru / forward-reference), sembolleri toplama işlemini iki geçişli bir algoritma ile yapmak zorundayız. + +--- + +### Gelişme (Neyi, Nerede ve Nasıl Yapacaksın?) +Aşağıdaki adımları sırasıyla gerçekleştir: +1. **Sembol ve Kapsam Yapıları:** `src/symbol/` adında yeni bir dizin aç. Burada `Symbol` yapısını tanımla (ad, tür, tip, tanım konumu, referans listesi alanları bulunsun). `Scope` sınıfını iç içe geçebilir ağaç yapısında yaz; her scope bir üst scope'a pointer tutsun. +2. **SymbolTable Yöneticisi:** `src/symbol/symbol_table.hpp` dosyasını oluştur. Scope yığınını yöneten `enterScope()`, `exitScope()`, sembol ekleyen `define()` (aynı scope'ta çift tanım varsa hata üret) ve içten dışa arayan `resolve()` metotlarını yaz. +3. **İki Geçişli Toplayıcı:** `src/symbol/symbol_collector.hpp` ve `.cpp` dosyalarını oluştur. + * **Geçiş 1 (Global Hoisting):** AST'yi tarayarak sadece üst seviye fonksiyon ve struct imzalarını global scope'a kaydet. + * **Geçiş 2 (Local Resolution):** Fonksiyon gövdelerine in. Lokal değişkenleri declare-before-use (kullanmadan önce tanımlama) kuralıyla topla ve Identifier (isim referansı) düğümlerini sembol tablosundaki sembollerle bağla. Global değişken başlatıcılarında declare-before-use kuralını zorunlu kıl. +4. **Döngüsel Struct Kontrolü:** Struct tanımları toplandıktan sonra, pointer olmadığı için birbirini değer olarak içeren döngüsel struct tanımlarını (örn. `struct A { B b; }` ve `struct B { A a; }`) DFS (Derinlik Öncelikli Arama) algoritmasıyla tespit et ve `E010` hatasını raporla. + +*Geliştirme Dalı (Branch):* `feature/faz2-symbols` + +--- + +### Sonuç ve Başarı Kriterleri +Bu işin bittiğini ve başarılı olduğunu şu kriterlerle doğrulayacağız: +1. `saqut symbols examples/fibonacci.sqt` komutu çalıştırıldığında, programdaki fonksiyonlar, parametreler ve lokal değişkenler doğru tipleri ve tüm kullanım koordinatlarıyla (satır/sütun referans listesi) ekrana yazılmalıdır. +2. Aynı isimde iki değişken tanımlandığında `E002` (Çift Tanım), tanımsız bir değişken çağrıldığında veya global başlatıcı sırasında ileri başvuru yapıldığında `E001` (Tanımsız İsim), döngüsel struct tanımlandığında ise `E010` hataları DiagnosticEngine tarafından raporlanmalı ve derleme durmalıdır. + +*Mühendis Olmayanlar İçin Analiz:* Derleyicinin değişken ve fonksiyon isimlerini anlamlandırmaya başladığı aşamadır. Hatalı kod yazıldığında derleyicinin verdiği akıllı uyarıların temelidir. Karmaşıklığı **Yüksek**, yapım süresi yaklaşık **4-5 gün**dür. +*İmza/Yorum:* Bu aşamada pointer ve scope yapıları çok hassas tasarlanmalıdır; bellek sızıntılarını önlemek için akıllı işaretçiler veya net sahiplik modelleri tercih edilmelidir.""" + }, + { + "title": "Faz 3 — Semantik Analiz ve Tip Denetimi (Type Checking)", + "body": """### Giriş (Nedir, Neden Yapıyoruz?) +Bu iş paketinde derleyicinin kurallarını işleten Semantik Analiz (Anlamsal Analiz) ve Tip Denetimi (Type Checking) motorunu yazacağız. +Sözdizimi (Syntax) doğru olan bir kod anlamsal olarak yanlış olabilir (örneğin `int x = \"merhaba\" + 5;` yazmak sözdizimsel olarak geçerlidir ancak mantıksızdır). +Tip Denetimi, ifadelerin veri tiplerinin uyumlu olup olmadığını kontrol eder. Ayrıca dilimizin \"otomatik tip dönüşümü yasaktır\" kuralını işletir. Yapısal doğrulama ise `break`/`continue` deyimlerinin döngü dışında kullanılmasını engeller. + +--- + +### Gelişme (Neyi, Nerede ve Nasıl Yapacaksın?) +Aşağıdaki adımları sırasıyla gerçekleştir: +1. **Tip Denetleyici:** `src/sema/type_checker.hpp` ve `.cpp` dosyalarını oluştur. AST'yi aşağıdan yukarıya (bottom-up) gezerek her `ExpressionNode` düğümünün tipini (`resolvedType`) belirle. +2. **Uyuşmazlık Kuralları:** Atama işlemlerinde (`=`), aritmetik operatörlerde ve fonksiyon çağrılarında tip uyumunu denetle. Gizli değişken-değişken dönüşümlerini yasakla (hata: `E003`). +3. **Literal Uyarlama Kuralı:** Sabit sayı literal'ları için bağlama göre tiplendirme kuralını işlet (Örn: `float x = 1;` geçerli olmalı çünkü `1` kayıpsızca float'a dönüşebilir, ancak `int y = 1.5;` `E003` hatası vermelidir). +4. **Error Tipi:** Bir ifade hatalıysa tipine `ErrorType` ata. Bu sayede, o ifadeyi kullanan üst ifadelerde tekrar tekrar sahte hatalar üretilmez. +5. **Yapısal Doğrulayıcı:** `src/sema/structural_validator.hpp` ve `.cpp` dosyalarını oluştur. Ağacı tırmanarak `break`/`continue` ifadelerinin üstünde bir döngü olup olmadığını (`E004`), `return` ifadesinin bir fonksiyon gövdesinde olup olmadığını (`E005` ve dönüş tipi uyumu için `E006`) denetle. + +*Geliştirme Dalı (Branch):* `feature/faz3-semantic-analysis` + +--- + +### Sonuç ve Başarı Kriterleri +Bu işin bittiğini ve başarılı olduğunu şu kriterlerle doğrulayacağız: +1. Geçerli olan `examples/fibonacci.sqt` dosyası semantik analizden sıfır hatayla geçmeli ve her AST ifadesinin tipi JSON çıktısında (`resolvedType`) görünmelidir. +2. Hatalı bir test dosyası verildiğinde (örneğin döngü dışında `break;` yazıldığında veya `int` değişkene `string` atandığında) derleyici ilgili hata kodlarını (`E003`, `E004` vb.) raporlamalı ve derleme süreci kesilmelidir. + +*Mühendis Olmayanlar İçin Analiz:* Bu aşama, derleyicinin yazılan kodun \"anlamlı\" olup olmadığını kontrol ettiği güvenlik kapısıdır. Karmaşıklığı **Orta-Yüksek**, yapım süresi yaklaşık **3-4 gün**dür. +*İmza/Yorum:* Sabit ifadelerde constant folding istisnasını unutmama kuralları burada işletilecektir.""" + }, + { + "title": "Faz 4 — Optimizasyon Altyapısı ve Kaynak Optimizasyonları (Optimization)", + "body": """### Giriş (Nedir, Neden Yapıyoruz?) +Bu iş paketinde derleyicinin ürettiği kodu daha verimli hale getiren Optimizasyon (Eniyileme) altyapısını ve ilk optimizasyon adımlarını (pass'leri) yazacağız. +Optimizasyon, yazılan kodun anlamını değiştirmeden daha hızlı çalışacak veya daha az yer kaplayacak şekilde dönüştürülmesidir. +saQut'un \"alet çantası\" felsefesi gereği, optimizasyon orijinal kaynak kod görüntüsünü bozmamalıdır. Bu nedenle optimizasyonlar AST'nin bir kopyası (klon) üzerinde gerçekleştirilir. + +--- + +### Gelişme (Neyi, Nerede ve Nasıl Yapacaksın?) +Aşağıdaki adımları sırasıyla gerçekleştir: +1. **Optimizasyon Yöneticisi:** `src/opt/` dizinini oluştur. Soyut `OptimizationPass` sınıfını tanımla. `OptimizationManager` sınıfını yaz; bu sınıf `CompilerConfig` üzerinden aktif edilen pass'leri sırayla çalıştırsın. +2. **Fixpoint Döngüsü:** Pass'lerin birbirini tetiklemesi için (örn. folding sonrası ölü kod oluşması) optimizasyonları bir fixpoint döngüsünde (hiçbir pass değişiklik yapmayana kadar) çalıştır. Monoton olmayan pass'lerin sonsuz döngüye girmemesi için sert bir tur sınırı (`maxFixpointRounds`) ekle. +3. **Ağaç Klonlama ve Remap:** `ASTNode::clone()` metodunu tüm AST düğümleri için yaz. Kopyalanan düğümlerin `parent` pointer'larını yeni ağaca göre bağla. Klonlanan ağaçtaki Identifier (isim referansı) düğümlerinin sembol tablosu bağlarını, klonlanmış yeni bir sembol tablosuna yönlendir (Remapping). +4. **Constant Folding Pass:** `src/opt/constant_folding.hpp` dosyasını oluştur. İki sabit terimin işlemini derleme zamanında hesapla (Örn: `1 + 2` → `3`). Sıfıra bölme varsa katlama yapma, `W002` uyarısı ver. +5. **Dead Code Elimination (DCE) Pass:** `src/opt/dead_code_elim.hpp` dosyasını oluştur. Erişilemez deyimleri (örn. `return` sonrası kodlar, `if(false)` gövdeleri) ve hiç kullanılmayan lokal değişkenleri (`W001`) sil. + +*Geliştirme Dalı (Branch):* `feature/faz4-optimization` + +--- + +### Sonuç ve Başarı Kriterleri +Bu işin bittiğini ve başarılı olduğunu şu kriterlerle doğrulayacağız: +1. `saqut ast examples/fibonacci.sqt --optimized` komutu çalıştırıldığında sabit ifadelerin katlandığı ve varsa ölü kodların silindiği doğrulanmalıdır. +2. `--optimized` bayrağı verilmeden çağrıldığında orijinal (optimize edilmemiş) AST çıktısı elde edilmelidir (Öncesi/Sonrası karşılaştırması). +3. Folding ve DCE işlemlerinin ardışık olarak birbirini beslediği (folding sonucu oluşan ölü kodun DCE tarafından temizlendiği) zincirleme senaryolar tek bir komutla doğrulanmalıdır. + +*Mühendis Olmayanlar İçin Analiz:* Yazdığınız programın gereksiz kısımlarını temizleyen akıllı temizlikçi aşamasıdır. Kodun boyutunu küçültür. Karmaşıklığı **Yüksek**, yapım süresi yaklaşık **4-5 gün**dür. +*İmza/Yorum:* `ASTNode::clone()` implementasyonu bu fazın en kritik ve hata yapmaya açık kısmıdır, parent pointer bağlarına azami dikkat gösterilmelidir.""" + } +] + +for issue in issues_data: + endpoint = f"{REPO_PATH}/issues" + res = make_request(endpoint, method="POST", data=issue) + print(f"Created issue #{res['number']}: {res['title']}") diff --git a/scripts/create_syntax_test_issues.py b/scripts/create_syntax_test_issues.py new file mode 100644 index 0000000..5984980 --- /dev/null +++ b/scripts/create_syntax_test_issues.py @@ -0,0 +1,499 @@ +#!/usr/bin/env python3 +"""Sozdizimi/davranis golden-test senaryolari + CLI/UX + kalite-mimari fikirleri. + +"[Test]" basliklilar: somut .sqt kodu + beklenen cikti/davranis iceren +golden-test taslaklaridir. Derleyici (Faz 0-4 + IR/VM) tamamlandiginda bu +dosyalar `examples/tests/` altina yerlestirilip regresyon testi olarak +kullanilabilir; ayni zamanda "syntax X soyle calismali" spesifikasyonudur - +calismiyorsa ilgili faz/pass'te bugfix konusu acar. + +"[Fikir]" basliklilar onceki script'lerle aynisekilde fikir/backlog kayitlaridir. +""" +from gitea import make_request, REPO_PATH + +L_FIKIR = 66 +L_TEST = 73 +L_CLIUX = 74 +L_KALITE = 75 + +issues_data = [ + # ---------------- Golden-test senaryolari ---------------- + { + "title": "[Test] Temel Aritmetik, Operatör Önceliği ve `print` Çıktısı", + "labels": [L_TEST], + "body": """### Giriş (Nedir, Neden Önemli?) +Bu issue, derleyicinin **en temel** davranışını sabitleyen bir golden-test taslağıdır: sayı literalleri, dört işlem, operatör önceliği (precedence) ve `print` builtin'i. "Fibonacci çalıştı" hedefinden önce bile bu örneğin doğru çalışması gerekir — Pratt parser'ın (zaten yapılı) önceliği doğru uyguladığının kanıtıdır. + +--- + +### Test Kodu (`examples/tests/aritmetik.sqt`) +```c +int main() { + print(1 + 2 * 3); // çarpma toplamadan önce + print((1 + 2) * 3); // parantez önceliği + print(10 - 4 - 3); // soldan-sağa birliktelik (left-assoc) + print(10 / 3); // tamsayı bölmesi (truncation) + print(10 % 3); // mod + print(2 + 3 * 4 - 6 / 2); + return 0; +} +``` + +### Beklenen Çıktı (`saqut run examples/tests/aritmetik.sqt`) +``` +7 +9 +3 +3 +1 +11 +``` + +--- + +### Açık Sorular / Bağlı Fazlar +- Bu test, `saqut run` (IR + VM, ADR-015) tamamlanmadan **AST** seviyesinde de kısmen doğrulanabilir: `saqut ast --optimized` ile constant folding (Faz 4) çalıştığında her `print` argümanı doğrudan tek bir `Literal` düğümüne katlanmalı (örn. `1 + 2 * 3` → `Literal(7)`). +- `10 / 3` → `3` (tamsayı bölmesi) davranışı tip denetiminde (Faz 3) açıkça test edilmeli; `int / int = int` (kayıp olabilir ama bu saQut'ta hata değil, sadece kesme/truncation — ADR-010'daki "kayıpsız literal" kuralından farklı bir konu, karıştırılmamalı). + +*İmza/Yorum:* Bu dosya, "derleyici bitti mi?" sorusuna verilecek **ilk** somut cevaplardan biri olmalı — `examples/fibonacci.sqt`'den önce, daha küçük bir adım.""" + }, + { + "title": "[Test] Döngüler — `while` / `do-while` / `for` Davranış Farkları", + "labels": [L_TEST], + "body": """### Giriş (Nedir, Neden Önemli?) +Üç döngü yapısının (`while`, `do-while`, `for`) **birbirinden farklı** davrandığı noktalar — özellikle `do-while`'ın gövdeyi **en az bir kez** çalıştırması — derleyicide kolayca karıştırılabilecek köşe durumlardır (edge case). Bu issue, bu farkları somut kodla sabitler. + +--- + +### Test Kodu 1 — Üç döngü de aynı sayıları üretmeli (`examples/tests/donguler_temel.sqt`) +```c +int main() { + int i = 0; + while (i < 3) { + print(i); + i = i + 1; + } + + int j = 0; + do { + print(j); + j = j + 1; + } while (j < 3); + + for (int k = 0; k < 3; k = k + 1) { + print(k); + } + return 0; +} +``` + +### Beklenen Çıktı +``` +0 +1 +2 +0 +1 +2 +0 +1 +2 +``` + +--- + +### Test Kodu 2 — `do-while` koşulu en baştan yanlışsa bile gövde bir kez çalışır (`examples/tests/do_while_en_az_bir.sqt`) +```c +int main() { + int x = 5; + do { + print(x); + x = x + 1; + } while (x < 0); // baştan yanlış! + return 0; +} +``` + +### Beklenen Çıktı +``` +5 +``` +(Eğer çıktı **boş** ise — yani `do-while`, `while` gibi davranıyorsa — bu bir **bug**'dır: `do-while`'ın AST düğümü/IR alçaltması `while` ile aynı koddan üretilmiş ve gövdeyi koşuldan **sonra** kontrol etmiyor olabilir.) + +--- + +### Açık Sorular / Bağlı Fazlar +- `for` döngüsünün üç parçası (`init; condition; step`) ayrı ayrı `AST` düğümlerinde mi tutuluyor, yoksa `while`'a "alçaltılıyor" (desugar) mu? İkinci durumda, `for (int k = 0; ...)` içindeki `k`'nın scope'u (sadece `for` bloğuna özel mi?) Faz 2'de doğru kurulmalı. +- `break`/`continue` (E004 ile ilişkili) bu üç döngü türünde de test edilmeli — ayrı bir test dosyası (`donguler_break_continue.sqt`) eklenebilir. + +*İmza/Yorum:* `do-while`/`while` karışıklığı, "derleyici neredeyse bitti ama syntax X yanlış davranıyor" tarzı klasik bug'lardandır — bu test erken yazılırsa erken yakalanır.""" + }, + { + "title": "[Test] Bit Düzeyi (Bitwise) İşlemler — `&`, `|`, `^`, `~`, `<<`, `>>`", + "labels": [L_TEST], + "body": """### Giriş (Nedir, Neden Önemli?) +Tokenizer'da `&`, `|`, `^`, `~`, `<<`, `>>` token'ları zaten tanımlı (`src/tokenizer/tokenizer.hpp`). Ama bu operatörlerin **Pratt parser'da doğru öncelik** ile ayrıştırıldığı ve **tip denetiminde** (Faz 3, sadece `int` üzerinde tanımlı) doğru ele alındığı henüz doğrulanmadı. Bu issue, "karmaşık bit işlemleri" için bir golden-test taslağıdır. + +--- + +### Test Kodu (`examples/tests/bit_islemleri.sqt`) +```c +int main() { + int a = 12; // 0b1100 + int b = 10; // 0b1010 + + print(a & b); // bitwise AND + print(a | b); // bitwise OR + print(a ^ b); // bitwise XOR + print(~a); // bitwise NOT (iki's complement) + print(a << 2); // sola kaydır + print(a >> 2); // sağa kaydır + + // Operatör önceliği: << ve >>, + ve - 'dan düşük öncelikli olmalı (C kuralı) + print(1 << 2 + 1); // (2+1)=3 -> 1 << 3 = 8, yoksa (1<<2)+1=5 olur + print(a & b | b); // & , | 'dan önce: (a&b) | b = 8 | 10 = 10 + return 0; +} +``` + +### Beklenen Çıktı +``` +8 +14 +6 +-13 +48 +3 +8 +10 +``` + +--- + +### Açık Sorular / Bağlı Fazlar +- `~a` için `-13` beklentisi, `int`'in **iki's complement (ikiye tümleyen) imzalı 32-bit** temsiline dayanır — bu, `src/core/type.hpp`'de `int`'in tam temsilinin (bit genişliği) **şimdiden** dokümante edilmesini gerektirir (Faz 0'a not). +- `1 << 2 + 1` örneği **kasıtlı olarak kafa karıştırıcı** — C'de `<<`/`>>` aritmetik operatörlerden (`+`/`-`) daha düşük önceliklidir. saQut Pratt parser'ı bu sırayı C ile aynı mı tutacak, yoksa daha "şaşırtmasız" bir öncelik mi tanımlayacak? **Karar ne olursa olsun docs'a yazılmalı**, çünkü bu tip kararlar "sessiz" kalırsa en çok şikayet edilen bug kaynağı olur. +- Bu operatörler sadece `int` için tanımlı olmalı; `bool & bool` veya `float << 1` gibi kullanımlar `E003` üretmeli (Faz 3'e not). + +*İmza/Yorum:* "Karmaşık byte işlemleri" testi olarak istenen tam da bu — bit-manipülasyonu doğru çalışmayan bir derleyici, gerçek programlar (hash, sıkıştırma, bayrak/flag kümeleri) için kullanılamaz hale gelir.""" + }, + { + "title": "[Test] Builtin Fonksiyonların Kullanım Örnekleri (`print`, `len`, `toString`, `parseInt`, ...)", + "labels": [L_TEST], + "body": """### Giriş (Nedir, Neden Önemli?) +`print` dışındaki builtin'ler henüz yazılmadı (bkz. "[Fikir] Builtin Fonksiyon Kataloğu", #89), ama bu issue **hedefin son hâlini** somut kodla göstermek için var — yani "builtin kataloğu" tamamlandığında bu dosyanın **aynen bu çıktıyı** vermesi beklenir. Erken yazmanın faydası: builtin imzaları (parametre/dönüş tipleri) bu örnekten geriye doğru türetilebilir. + +--- + +### Test Kodu (`examples/tests/builtin_fonksiyonlar.sqt`) +```c +int main() { + // print: farklı tiplerde çalışmalı + print(42); + print(3.14); + print("merhaba"); + print(true); + + // toString: sayıdan string'e + print(toString(123)); // "123" + + // parseInt / parseFloat: string'den sayıya + print(parseInt("45") + 5); // 50 + print(parseFloat("2.5") * 2.0); // 5.0 + + // len: string ve array uzunluğu + print(len("saqut")); // 5 + + int[] sayilar = {10, 20, 30}; + print(len(sayilar)); // 3 + + return 0; +} +``` + +### Beklenen Çıktı +``` +42 +3.14 +merhaba +true +123 +50 +5.0 +5 +3 +``` + +--- + +### Açık Sorular / Bağlı Fazlar +- `print(true)` çıktısı `true`/`false` mi yoksa `1`/`0` mı olmalı? saQut'ta `bool` ayrı bir tip olduğu için (ADR-010, gizli int↔bool dönüşümü de yok varsayımıyla) `true`/`false` **daha tutarlı** görünüyor — ama bu kararın `print`'in builtin tablosuna (#89) not edilmesi gerekir. +- `int[] sayilar = {10, 20, 30};` — array literal sözdizimi (`{...}`) şu an dilde **tanımlı mı**? Eğer değilse, bu issue aynı zamanda "array literal sözdizimi eklenmeli" şeklinde bir alt-konu açar (Faz 1/parser'a not). +- `parseFloat("2.5") * 2.0` → `5.0` çıktısının `5` değil `5.0` (ondalık nokta korunarak) basılması, `print`'in `float` biçimlendirmesi için bir kural gerektirir — bu kural baştan netleşmeli (örn. her zaman en az bir ondalık basamak). + +*İmza/Yorum:* Bu dosya, builtin kataloğu (#89) ve minimal stdlib (#90) issue'larının "kabul testi" (acceptance test) gibi düşünülebilir.""" + }, + { + "title": "[Test] Struct + Array Birlikte Kullanım Senaryosu", + "labels": [L_TEST], + "body": """### Giriş (Nedir, Neden Önemli?) +`struct` ve `int[]` dil kimliğinde "var" olarak işaretli ama bu ikisinin **birlikte** kullanıldığı (struct içinde array, array of struct) bir örnek henüz yazılmadı. Bu kombinasyon, value-semantics (değer semantiği) kopyalama davranışını (bkz. #79 "Array ve Struct'ların Runtime Bellek Düzeni") en çok zorlayan senaryodur. + +--- + +### Test Kodu (`examples/tests/struct_array.sqt`) +```c +struct Ogrenci { + string ad; + int notlar[3]; +} + +int toplaNotlar(Ogrenci o) { + int toplam = 0; + for (int i = 0; i < 3; i = i + 1) { + toplam = toplam + o.notlar[i]; + } + return toplam; +} + +int main() { + Ogrenci ali; + ali.ad = "Ali"; + ali.notlar[0] = 70; + ali.notlar[1] = 85; + ali.notlar[2] = 90; + + print(ali.ad); + print(toplaNotlar(ali)); + + // value semantics: kopya degisse de orijinal degismemeli + Ogrenci kopya = ali; + kopya.notlar[0] = 0; + print(toplaNotlar(ali)); // değişmemeli: 245 + print(toplaNotlar(kopya)); // değişmeli: 175 + + return 0; +} +``` + +### Beklenen Çıktı +``` +Ali +245 +245 +175 +``` + +--- + +### Açık Sorular / Bağlı Fazlar +- `int notlar[3];` sözdizimi (struct alanı olarak sabit-boyutlu array) — parser bunu destekliyor mu, yoksa `int[3] notlar;` mı olmalı? Dil kimliğinde array sözdizimi `int[]` olarak yazılmış ama boyutlu hali (`[3]`) henüz örneklenmemiş — bu issue, sözdizimini netleştirme ihtiyacını da gösterir. +- `Ogrenci kopya = ali;` satırının **gerçekten derin kopya** yapması (struct içindeki array dahil) — bu, #79'daki "struct kopyalama IR'de alan-alan mı genişler" sorusunun **somut test vakasıdır**. Eğer `kopya.notlar[0] = 0;` satırı `ali.notlar[0]`'ı da değiştirirse (yüzeysel kopya/shallow copy), bu **value semantics kuralının ihlalidir** — kritik bir bug. + +*İmza/Yorum:* Bu test, "value semantics" kilitli kararının (dil kimliği tablosu) en sıkı sınandığı yer — diğer tüm testler geçse bile bu test başarısızsa, dilin temel garantisi bozulmuş demektir.""" + }, + # ---------------- Optimizasyon test senaryolari ---------------- + { + "title": "[Test] Optimizasyon — Constant Folding Doğrulama (`--optimized` Öncesi/Sonrası)", + "labels": [L_TEST], + "body": """### Giriş (Nedir, Neden Önemli?) +Faz 4'ün constant folding pass'i, sabit ifadeleri derleme zamanında hesaplayıp `Literal` düğümüyle değiştirmeli (bkz. roadmap Faz 4). Bu issue, "öncesi/sonrası" AST karşılaştırmasının **tam olarak nasıl görünmesi gerektiğini** somutlaştırır. + +--- + +### Test Kodu (`examples/tests/opt_constant_folding.sqt`) +```c +int main() { + int x = 2 + 3 * 4; // sabit ifade -> 14 + int y = (10 - 4) / 2; // sabit ifade -> 3 + int z = x + y; // x, y sabit olduğu için z de katlanabilir -> 17 + int w = 10 / 0; // sıfıra bölme: KATLANMAZ, W002 uyarısı + print(z); + print(w); + return 0; +} +``` + +### Beklenen Davranış +- `saqut ast examples/tests/opt_constant_folding.sqt` (bayraksız): orijinal AST — `x`'in initializer'ı `BinaryExpression(2, +, BinaryExpression(3, *, 4))` olarak **değişmeden** görünür. +- `saqut ast examples/tests/opt_constant_folding.sqt --optimized`: klonlanmış AST'de: + - `x`'in initializer'ı → `Literal(14)` + - `y`'nin initializer'ı → `Literal(3)` + - `z`'nin initializer'ı → `Literal(17)` (**zincirleme**: `x` ve `y` önce katlanmalı, sonra `z = x + y` de katlanabilmeli — bu, fixpoint döngüsünün gerekliliğinin kanıtıdır) + - `w`'nin initializer'ı → **değişmez** (`10 / 0` kalır), ve diagnostic çıktısında `W002` (sıfıra bölme) uyarısı görünür. +- `saqut run examples/tests/opt_constant_folding.sqt` çıktısı (VM tamamlandığında): `17` ve ardından `10 / 0` çalışma-zamanı hatası (bu son satır, IR/VM tasarımına `E0xx`/runtime-error kategorisi notu olarak düşülmeli). + +--- + +### Açık Sorular / Bağlı Fazlar +- "Zincirleme katlama" (`z = x + y`, `x` ve `y` kendileri katlanmış sabitlerden geliyor) tek bir fixpoint turunda mı yoksa birden fazla turda mı gerçekleşmeli — bu, ADR-009'daki fixpoint/iterasyon-tavanı kararının **somut test sayısı** olabilir (örn. "bu örnek 2 turda kararlı hale gelmeli"). +- `10 / 0` ifadesinin **derleme zamanında uyarı, çalışma zamanında hata** ayrımı IR/VM tasarımına (#74-78) açıkça not edilmeli. + +*İmza/Yorum:* Bu test dosyası, Faz 4'ün "bitti" tanımının resmi kanıtı olabilir — roadmap'teki "Doğrulama" bölümüne doğrudan eklenebilir.""" + }, + { + "title": "[Test] Optimizasyon — Dead Code Elimination Doğrulama (Ölü Kod Temizliği)", + "labels": [L_TEST], + "body": """### Giriş (Nedir, Neden Önemli?) +Faz 4'ün DCE (Dead Code Elimination, Ölü Kod Eleme) pass'i, erişilemez kodu ve kullanılmayan değişkenleri temizlemeli. Bu issue, "ölü kod" sayılan **farklı durumların** her birini ayrı ayrı örnekler — DCE'nin sadece "return sonrası kod" ile sınırlı kalmaması gerektiğini gösterir. + +--- + +### Test Kodu (`examples/tests/opt_dead_code.sqt`) +```c +int hesapla(int n) { + int kullanilmayan = 99; // hiç kullanılmıyor -> W001 + + if (n > 0) { + return n * 2; + print(n); // return sonrası -> erişilemez, W003 + } + + return -1; + + int olu = 5; // fonksiyonun erişilemez kuyruğu -> W003 + return olu; +} + +int main() { + print(hesapla(5)); + return 0; +} +``` + +### Beklenen Davranış +- `saqut ast examples/tests/opt_dead_code.sqt --optimized` çıktısında: + - `int kullanilmayan = 99;` satırı **silinmiş** olmalı (referans sayısı 0 → Faz 2'nin `references` listesi boş). + - `print(n);` (return sonrası) **silinmiş** olmalı. + - `int olu = 5; return olu;` (fonksiyonun son `return -1;`'inden sonraki erişilemez kuyruk) **silinmiş** olmalı. +- Diagnostic çıktısında **3 uyarı** görünmeli: `W001` (kullanılmayan değişken), iki adet `W003` (erişilemez kod) — konum bilgileriyle (satır/sütun) birlikte. +- `saqut ast examples/tests/opt_dead_code.sqt` (bayraksız, optimize edilmemiş): **hiçbir satır silinmemiş**, ama uyarılar yine de raporlanabilir (uyarı raporlama optimizasyondan bağımsız olabilir — bu ayrım netleştirilmeli). +- `saqut run examples/tests/opt_dead_code.sqt` çıktısı (optimize edilsin/edilmesin aynı olmalı — **DCE anlamı değiştirmez**, sadece temizler): `10` + +--- + +### Açık Sorular / Bağlı Fazlar +- "Kullanılmayan değişken" (`W001`) tespiti Faz 2'nin `references` sayacına dayanır — ama bu sayaç **optimize edilmemiş orijinal AST'de** mi tutulur, yoksa her fixpoint turunda klon üzerinde yeniden mi hesaplanır (ADR-009, "flow-bound analiz her turda klon üzerinde yeniden hesaplanır")? Bu örnek, o kararın doğru uygulanıp uygulanmadığının testi. +- Fonksiyonun "erişilemez kuyruğu" (son `return`'den sonraki kod) ile "if içindeki return sonrası kod" aynı `isReachable=false` mekanizmasıyla mı işaretleniyor — yoksa farklı kod yolları mı? + +*İmza/Yorum:* "deadcode elimination eklenecek" değil, tam olarak kullanıcının istediği gibi: "optimizasyonlu/optimizasyonsuz çıktı karşılaştırıldığında gereksiz kod gözlemlenene kadar" çalışılacak somut hedef budur.""" + }, + # ---------------- CLI / UX ---------------- + { + "title": "[Fikir] CLI'da AST Görüntüleme — Ağaç (Tree), Tablo ve `--format=dot` Seçenekleri", + "labels": [L_FIKIR, L_CLIUX], + "body": """### Giriş (Nedir, Neden Önemli?) +Şu an `saqut ast` ham JSON basıyor. JSON, makineler için ideal ama bir insanın "bu kod nasıl bir ağaca dönüşmüş" sorusuna hızlı cevap vermesi için **okunması zor**. "Programlanabilir derleyici" felsefesi hem makine-okur (JSON) hem **insan-okur** çıktıyı hak ediyor. + +--- + +### Gelişme (Olası Yaklaşımlar) +- `saqut ast file --format=json` (mevcut, varsayılan kalabilir), `--format=tree`: terminalde girintili/kutu-çizgili bir ağaç (örn. `tree` komutunun çıktısına benzer: `├──`, `└──`). +- `--format=dot`: Graphviz DOT formatı — `saqut ast file --format=dot | dot -Tpng -o ast.png` ile görsel AST diyagramı üretilebilir (#43'te zaten "AST görselleştirme" fikri vardı, bu onun somut hâli). +- `--format=table`: her düğümü satır olarak basan, `tip | konum | değer` kolonlarına sahip düz bir tablo — `grep`/`awk` ile script'lenmesi kolay bir ara format. +- Renkli terminal çıktısı (`--color`): düğüm tipine göre (Expression mavi, Statement sarı, Literal yeşil gibi) ANSI renk kodları — `--optimized` ile birlikte kullanılırsa, **silinen düğümler kırmızı/üstü çizili** gösterilebilir (DCE'nin görsel kanıtı). + +--- + +### Açık Sorular +- `--format=tree`/`table`/`dot` çıktıları AST'nin **tam** bilgisini mi taşır (her alan), yoksa "özet" mi (sadece tip + konum + kısa değer)? Tam JSON her zaman `--format=json` ile erişilebilir kalmalı — diğerleri "insan için özet" olabilir. +- Bu format seçenekleri `saqut symbols` ve ileride `saqut ir` için de **aynı bayrak isimleriyle** tutarlı olmalı mı (örn. her komut `--format=tree/json/dot/table` desteklesin — CLI'da tek bir ortak altyapı, `src/cli/format.hpp` gibi)? + +*İmza/Yorum:* `--format=dot` özellikle düşük efor / yüksek "vitrin" değeri taşıyor — bir blog yazısında/README'de "işte saQut'un AST'si" diye gösterilebilecek bir görsel üretir.""" + }, + { + "title": "[Fikir] CLI Komut Seti Genişletme Önerileri (`check`, `explain`, `watch`)", + "labels": [L_FIKIR, L_CLIUX], + "body": """### Giriş (Nedir, Neden Önemli?) +Mevcut/planlanan komutlar (`tokens`, `ast`, `symbols`, `run`, ileride `ir`, `fmt`, `lsp`) hep "bir aşamanın çıktısını göster" mantığında. Bu issue, geliştirici deneyimini iyileştirecek **birleşik/yardımcı** komutları tartışır. + +--- + +### Gelişme (Olası Yaklaşımlar) +- **`saqut check file`**: sadece derleme hatalarını (Faz 0-3 diagnostic'leri) raporlar, **hiçbir çıktı üretmez/çalıştırmaz** — "bu kod derlenir mi?" sorusuna hızlı cevap. CI'larda (otomatik test sistemlerinde) kullanışlı. Çıkış kodu (exit code) `0` = hatasız, `1` = hata var. +- **`saqut explain E003`**: bir hata kodunun ne anlama geldiğini, **neden** var olduğunu (ilgili ADR'ye atıfla) ve örnek doğru/yanlış kod gösteren bir açıklama basar — hata kataloğunun (roadmap'teki tablo) CLI'dan erişilebilir hâli. "[Fikir] Akıllı Diagnostic" (#98) ile doğrudan ilişkili. +- **`saqut watch file --run`**: dosya her kaydedildiğinde otomatik olarak `check`/`run` çalıştırır, sonucu terminalde gösterir — hızlı geri-bildirim döngüsü (`cargo watch` benzeri). v0 için basit bir dosya-değişikliği izleme (polling veya `inotify`) yeterli. +- **`saqut --version` / `saqut --help`**: temel ama unutulmaması gereken iskelet komutlar — her CLI aracının beklediği standart. + +--- + +### Açık Sorular +- `saqut explain` kataloğu, hata mesajlarının içine gömülü mü olacak (örn. her hata "detaylar için: `saqut explain E003`" diye bitiyor), yoksa ayrı statik bir JSON/Markdown kataloğundan mı okunacak? +- `saqut watch`, LSP (#91) ile fonksiyonel olarak örtüşüyor — ikisi de "kodu değiştirdikçe geri bildirim" sağlıyor. `watch` LSP'den **önce**, basit/terminal-tabanlı bir "ara çözüm" olarak mı konumlanmalı? + +*İmza/Yorum:* `saqut check` ve `saqut explain`, düşük maliyetli ama günlük kullanımda en çok hissedilecek iyileştirmeler — Faz 0'ın `DiagnosticEngine`'i bittiği anda `check` neredeyse bedavaya gelir.""" + }, + # ---------------- Kalite / Mimari tavsiyeler ---------------- + { + "title": "[Fikir] Performans için C Tarzı Tasarım Kararları (Hız Önceliksiz Ama Bilinçli)", + "labels": [L_FIKIR, L_KALITE], + "body": """### Giriş (Nedir, Neden Önemli?) +ADR-015 "öncelik determinizm + incelenebilirlik, ham hız değil" diyor — bu **doğru** bir karar. Ama "hız öncelik değil" ile "gereksiz yere yavaş" aynı şey değildir. Bu issue, **mimariyi karmaşıklaştırmadan** (yeni soyutlama eklemeden) elde edilebilecek "bedava" performans kazanımlarını listeler — C'nin "ne kadar az iş, o kadar hızlı" felsefesinden ilham alarak. + +--- + +### Gelişme (Tavsiyeler) +- **Gereksiz kopyalama'dan kaçın:** AST düğümleri ve `Type`/`Symbol` nesneleri `std::string` gibi alanlar taşıyor — bunlar fonksiyonlara **referans/`const&`** ile geçilmeli, değer ile değil. Bu, "header-only" (ADR-003) ile çatışmaz, sadece dikkatli imza yazımı gerektirir. +- **`std::unique_ptr` ile sahiplik (ownership) net olsun** (#44'te bahsedilen issue tipi) — bellek sahipliği belirsizse hem bug hem performans kaybı (gereksiz `shared_ptr`/kopya) olur. +- **Tokenizer/Lexer tek geçişte (single-pass) çalışıyor mu** — kaynak dosya birden fazla kez taranıyorsa (örn. önce tokenize, sonra tekrar karakter-karakter konum hesaplama), bu birleştirilebilir. +- **IR/VM tasarımında (ileride):** yığın-tabanlı VM'de (#76) gereksiz push/pop zincirleri, basit "peephole" (göz ucu) optimizasyonlarla (örn. `push X; pop` → hiçbir şey) IR seviyesinde temizlenebilir — bu, Faz 4'ün constant folding'ine **benzer** ama IR'e özel, küçük bir ek pass olabilir. +- **Derleme zamanı (`saqut` binary'sinin kendi derlenme hızı):** header-only + agresif template kullanımı derleme süresini şişirebilir — `-Wall -Wextra` yanında zaman zaman derleme süresi de (örn. `time cmake --build`) izlenmeli. + +--- + +### Açık Sorular +- "Bedava" optimizasyonlar (kopya azaltma, peephole) ile "erken optimizasyon yapma" ilkesi (roadmap'teki "önce dikey dilim") arasındaki çizgi nerede? Önerim: **mimariyi değiştirmeyen, sadece imza/kopya düzeltmeleri** her zaman yapılabilir; **yeni pass/altyapı gerektirenler** (peephole gibi) Faz 4 sonrasına bırakılır. + +*İmza/Yorum:* "C gibi hızlı olmak", saQut için "C kadar hızlı VM" anlamına gelmek zorunda değil — "gereksiz iş yapmayan, dikkatli yazılmış C++ kodu" anlamına gelebilir; bu, ADR-015 ile çatışmaz.""" + }, + { + "title": "[Fikir] Güvenlik ve Stabilite için Java Tarzı Tasarım Kararları (Sınır Kontrolü, Hata İzolasyonu)", + "labels": [L_FIKIR, L_KALITE], + "body": """### Giriş (Nedir, Neden Önemli?) +saQut'ta kullanıcıya açık pointer yok (dil kimliği) — bu, C'nin en büyük güvenlik açığı kaynağı olan "pointer aritmetiği"ni baştan eliyor. Ama Java'nın asıl gücü bundan da fazlası: **her hata kontrollü bir şekilde yakalanır, programın geri kalanı çökmeden devam edebilir** (exception/hata izolasyonu) ve **dizi sınırları her zaman kontrol edilir**. Bu issue, bu ilkelerin saQut'a nasıl yansıyacağını tartışır. + +--- + +### Gelişme (Tavsiyeler) +- **Array sınır kontrolü (bounds checking):** `int[3] notlar; notlar[5] = 1;` gibi bir erişim — eğer boyut derleme zamanında biliniyorsa (`E009` zaten "array boyutu sabit değil" hatasını kapsıyor, ama "sabit boyut + sınır-dışı indeks" ayrı bir konu) **derleme zamanında** `E0xx` ile yakalanmalı; eğer indeks çalışma zamanı değeriyse (`notlar[i]`, `i` döngü değişkeni), **VM çalışma zamanında kontrol etmeli** ve kontrollü bir "runtime error" üretmeli (C'deki sessiz bellek bozulmasının tam tersi). +- **Çalışma zamanı hatalarının kategorize edilmesi:** sıfıra bölme (Faz 4'te `W002` derleme-zamanı uyarısı var, ama çalışma zamanında gerçek bir bölme `10 / x` ile `x=0` olursa ne olur?), dizi sınır taşması, derinlik taşması (call stack overflow, #78) — bunların hepsi **aynı "RuntimeError" ailesinde**, konum bilgisiyle (hangi `print`/satırda patladı) raporlanmalı; VM **segfault** ile çökmemeli. +- **"Programın bir kısmı patlasın, derleyici/VM çökmesin":** VM'in kendi C++ kodunda `assert`/exception kullanımı, kullanıcı programındaki bir hatayı (örn. sınır-dışı erişim) **VM crash'ine** dönüştürmemeli — bu, VM geliştirilirken her runtime-error noktasında "bu durum kullanıcıya nasıl raporlanır" sorusunun sorulması demektir. +- **Tip sisteminin sıkılığı (ADR-010) zaten "Java tarzı" bir güvenlik katmanı** — gizli dönüşüm yok kuralı, C'deki "implicit int→pointer" gibi klasik hata sınıflarını zaten önlüyor. Bu issue bunu **devam ettirme** çağrısıdır, yeni bir şey eklemiyor. + +--- + +### Açık Sorular +- Çalışma zamanı hataları (array sınır taşması vb.) için **yeni bir diagnostic kategorisi** (`R001`, `R002`... "Runtime" öneki ile, `E`/`W`'den ayrı) mı açılmalı — IR/VM tasarım issue'larına (#74-78) not edilmeli. +- Sınır kontrolü **her zaman** mı açık olacak, yoksa "release modu"nda (varsa böyle bir kavram) kapatılabilir mi — ADR-015'in "determinizm > hız" ilkesi düşünülürse, **her zaman açık** olması daha tutarlı görünüyor. + +*İmza/Yorum:* "Güvenli dil" derken kastedilen genelde "bellek güvenliği" — saQut bunu zaten pointer'sızlıkla büyük ölçüde kazandı; kalan iş, **çalışma zamanı hatalarını zarif bir şekilde raporlamak**.""" + }, + { + "title": "[Fikir] Modernlik için Go Tarzı Tasarım Kararları (Basitlik, Hızlı Geri-Bildirim, Tek Binary)", + "labels": [L_FIKIR, L_KALITE], + "body": """### Giriş (Nedir, Neden Önemli?) +Go'nun başarısının çoğu **dil özelliklerinden değil, geliştirici deneyiminden** geliyor: çok hızlı derleme, yerleşik formatter (`gofmt`), tek-binary dağıtım, anlaşılır hata mesajları, "az ama öz" bir standart kütüphane. saQut zaten küçük/basit bir dil — bu issue, Go'nun **araç zinciri (toolchain) felsefesini** saQut'a nasıl taşıyabileceğimizi listeler. + +--- + +### Gelişme (Tavsiyeler) +- **Tek binary, sıfır bağımlılık:** `saqut` CLI'sı tüm komutları (`tokens`, `ast`, `symbols`, ileride `run`, `fmt`, `lsp`) **tek bir çalıştırılabilir dosyada** barındırır — kullanıcı hiçbir ek paket/runtime kurmaz. Header-only C++ (ADR-003) bu hedefe zaten doğal olarak uygun; bu issue sadece **bunu bir hedef olarak yazıya dökmek**. +- **Hızlı derleme = hızlı geri-bildirim:** Go'nun derleme hızı, "kodu yaz → hemen çalıştır" döngüsünü mümkün kılıyor. saQut için bu, `saqut run` (IR+VM) ile birleşince **"saQut programını derleyip çalıştırmak, C++ programını derlemekten çok daha hızlı olmalı"** gibi somut bir hedef olabilir — VM yorumlayıcı olduğu için bu zaten doğal bir avantaj. +- **`gofmt` zaten bir issue olarak var (#93, `saqut fmt`)** — Go'nun "tartışmasız tek doğru format" felsefesi: format ayarlanabilir **olmamalı** (yapılandırma dosyası yok), bu da formatter'ın tasarımını basitleştirir. +- **Anlaşılır hata mesajları (#98 ile ilişkili):** Go'nun hata mesajları kısa ve doğrudandır (`undefined: x`). saQut'un hata kataloğu (E001 vb.) zaten bu yönde — bu issue, mesaj **dilinin** (Türkçe/İngilizce) ve **tonunun** (kısa cümle + örnek) standartlaştırılmasını önerir. +- **Yerleşik test çalıştırıcı (#96 ile ilişkili)** ve **modül sistemi (#81-83)** — Go'nun `go test` ve `go mod`'u, dilin "etrafına" değil **içine** gömülü araçlar. saQut'un CLI'sı da bu felsefeyle büyümeli: her yeni özellik (test, format, modül) **ayrı bir 3. parti araç değil, `saqut` alt-komutu** olmalı. + +--- + +### Açık Sorular +- "Tek binary" hedefi, FFI (#88) ile gerilim yaratabilir mi — kullanıcı kendi C++ host fonksiyonlarını eklemek isterse, bu "tek binary"yi nasıl etkiler (dinamik kütüphane yükleme mi, yeniden derleme mi)? +- Hata mesajı dili: şu anki dokümantasyon Türkçe — CLI çıktısı da Türkçe mi olacak, yoksa İngilizce + Türkçe `explain` (#issue) mi? Bu, uluslararası kullanıcı kitlesi hedefleniyorsa önemli bir erken karar. + +*İmza/Yorum:* saQut'un "alet çantası" kimliği ile Go'nun "az şey, ama hepsi birlikte ve iyi çalışıyor" felsefesi doğal bir eşleşme — bu issue, var olan diğer issue'ları (#91-98) tek bir "araç zinciri vizyonu" şemsiyesi altında toplama denemesidir.""" + }, +] + +for issue in issues_data: + endpoint = f"{REPO_PATH}/issues" + res = make_request(endpoint, method="POST", data=issue) + print(f"Created issue #{res['number']}: {res['title']}") From 1859cea9a1a9059fd1a192d28ac7ea9fa2bd82be Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Sun, 14 Jun 2026 23:17:21 +0300 Subject: [PATCH 04/28] LICENSE.md Ekle Signed-off-by: saqut --- LICENSE.md | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 LICENSE.md diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..72748b0 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,96 @@ +## Lisans / License / Lizenz + +[Türkçe Sürüm](#türkçe-lisans-sürümü) | [English Version](#english-license-version) | [Deutsche Version](#deutsche-lizenzversion) + +--- + +### Türkçe Lisans Sürümü + +# saQut Kamu Lisansı (Sürüm 1.0) + +Telif Hakkı (c) 2026, Abdussamed ULUTAŞ (ve saQut Katkıda Bulunanları). +Tüm hakları saklıdır. + +Bu lisans; saQut Derleyicisi, kaynak kodları, derleme betikleri (build scripts) ve beraberindeki dokümantasyonu (toplu olarak "Yazılım" olarak anılacaktır) kapsar. + +--- + +#### 1. Temel Felsefe (Alet Çantası Kuralı) +saQut, programlanabilir ve incelenebilir bir derleyici alet çantası (toolbox) olarak tasarlanmıştır. Ana varlık sebebi; derleme sürecinin (Token'lar, AST, Sembol Tabloları ve IR) dışarıdan tamamen şeffaf ve görülebilir kalmasıdır. Bu Yazılımın her türlü yeniden dağıtımı veya üzerinde yapılacak değişiklikler bu şeffaflık ilkesine saygı duymak zorundadır. + +#### 2. İzinler ve Koşullar +Bu Yazılımın bir kopyasını edinen herhangi bir kişiye; aşağıdaki koşullara uymak kaydıyla, Yazılımı kullanma, kopyalama, değiştirme, birleştirme, yayınlama veya dağıtma hakkı ücretsiz olarak tanınmıştır: + +* **Copyleft (Açık Kaynak Kalma) Şartı:** Eğer Yazılım üzerinde bir değişiklik yaparsanız (derleyici, lexer, parser, VM veya çekirdek mimari) ve bunu dağıtırsanız, değiştirdiğiniz kaynak kodları da BU AYNI LİSANS altında açık kaynaklı olarak herkese sunmak zorundasınız. saQut'u alıp kapalı kaynaklı, tescilli bir ticari ürüne dönüştüremezsiniz. +* **Atıf Şartı:** Orijinal telif hakkı bildirimi ve işbu izin bildirimi, Yazılımın tüm kopyalarına veya önemli parçalarına dahil edilmelidir. +* **İnceleme ve Şeffaflık Daveti:** saQut incelenmek için var olduğundan; bu derleyiciyi eğitim projelerinde, sınıflarda veya topluluk sunumlarında kullanırsanız, öğrencilerinize veya dinleyicilerinize en az bir kez `saqut tokens` veya `saqut ast` çıktılarını göstermeniz önemle tavsiye edilir (hukuki bir zorunluluk değildir). İç mekanizmayı görünür tutun! + +#### 3. Runtime (Çalışma Zamanı) ve Çıktı İstisnası (KRİTİK) +Bu dili kullanan geliştiricilerin mutlak özgürlüğünü garanti altına almak adına: +* **Kodunuz Sizindir:** saQut diliyle yazılmış tüm kaynak kodları (örn. `.sqt` dosyaları) ve derleyici tarafından üretilen tüm veriler (JSON AST dökümleri, sembol tabloları veya derlenmiş bytecode çıktısı) bu lisansın kısıtlamalarına **TABİ DEĞİLDİR**. +* Geliştiriciler, kendi saQut programlarının kaynak kodlarını ve derleyici çıktılarını istedikleri gibi lisanslamakta, satmakta veya kapalı kaynak yapmakta tamamen özgürdür. saQut tarafından sağlanan çalışma zamanı ortamı (runtime/VM), bu ortamı barındıran ana uygulamaların lisanslarını kısıtlamaksızın diğer uygulamaların içine gömülebilir (embed edilebilir). + +#### 4. Garanti Reddi +YAZILIM "OLDUĞU GİBİ" SUNULMAKTADIR; TİCARETE UYGUNLUK, BELİRLİ BİR AMACA UYGUNLUK VE İHLAL ETMEME GARANTİLERİ DAHİL ANCAK BUNLARLA SINIRLI OLMAMAK ÜZERE, AÇIK VEYA ZIMNİ HERHANGİ BİR GARANTİ VERİLMEMEKTEDİR. YAZARLAR VEYA TELİF HAKKI SAHİPLERİ, YAZILIMLA VEYA YAZILIMIN KULLANIMIYLA YA DA DİĞER İŞLEMLERLE BAĞLANTILI OLARAK ORTAYA ÇIKAN SÖZLEŞME, HAKSIZ FİİL VEYA DİĞER DURUMLARDAKİ HİÇBİR TALEP, TAZMİNAT VEYA DİĞER YÜKÜMLÜLÜKLERDEN SORUMLU TUTULAMAZ. + +--- + +### English License Version + +# The saQut Public License (Version 1.0) + +Copyright (c) 2026, Abdussamed ULUTAŞ (and saQut Contributors). +All rights reserved. + +This license applies to the saQut Compiler, its source code, build scripts, and accompanying documentation (collectively referred to as "the Software"). + +--- + +#### 1. The Core Philosophy (The Toolbox Rule) +saQut is designed as a programmable, inspectable compiler toolbox. Its core purpose is to keep the compilation process transparent (Tokens, AST, Symbol Tables, and IR). Any redistribution or modification of this Software must respect this transparency. + +#### 2. Permissions & Conditions +Permission is hereby granted, free of charge, to any person obtaining a copy of this Software, to use, copy, modify, merge, publish, or distribute the Software, subject to the following conditions: + +* **The Copyleft Requirement:** If you modify the Software (the compiler, lexer, parser, VM, or core architecture) and distribute it, you MUST make your modified source code publicly available under this same license. You cannot turn saQut into a closed-source proprietary product. +* **The Attribution Requirement:** The original copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +* **The Inspection Invitation:** Since saQut is built to be inspected, if you use this compiler in an educational project, classroom, or public presentation, you are highly encouraged (though not legally forced) to show your students or audience the output of `saqut tokens` or `saqut ast` at least once. Keep the internals visible! + +#### 3. The Runtime & Output Exception (CRITICAL) +To ensure the absolute freedom of the developers using this language: +* **Your Code is Yours:** Any source code written *in* the saQut language (e.g., `.sqt` files), and any data generated *by* the compiler (such as JSON AST dumps, symbol tables, or compiled bytecode) are **NOT** subject to this license. +* Developers are completely free to license, sell, or close the source code of their own saQut programs and compiler outputs as they see fit. The runtime environment/VM provided by saQut may be embedded into other applications without restricting those applications' licenses. + +#### 4. Disclaimer of Warranty +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- + +### Deutsche Lizenzversion + +# Die saQut Öffentliche Lizenz (Version 1.0) + +Copyright (c) 2026, Abdussamed ULUTAŞ (und saQut Mitwirkende). +Alle Rechte vorbehalten. + +Diese Lizenz gilt für den saQut-Compiler, seinen Quellcode, Build-Skripte und die dazugehörige Dokumentation (zusammenfassend als „die Software“ bezeichnet). + +--- + +#### 1. Die Kernphilosophie (Die Toolbox-Regel) +saQut ist als programmierbare, inspizierbare Compiler-Toolbox konzipiert. Der Hauptzweck besteht darin, den Kompilierungsprozess (Tokens, AST, Symboltabellen und IR) transparent zu halten. Jede Weitergabe oder Änderung dieser Software muss diese Transparenz respektieren. + +#### 2. Berechtigungen & Bedingungen +Hiermit wird jeder Person, die eine Kopie dieser Software erhält, kostenlos die Berechtigung erteilt, die Software zu nutzen, zu kopieren, zu modifizieren, zusammenzufügen, zu veröffentlichen oder zu verbreiten, sofern folgende Bedingungen erfüllt sind: + +* **Die Copyleft-Bedingung:** Wenn Sie die Software verändern (Compiler, Lexer, Parser, VM oder Kernarchitektur) und verbreiten, MÜSSEN Sie Ihren geänderten Quellcode unter derselben Lizenz öffentlich zugänglich machen. Sie dürfen saQut nicht in ein proprietäres Closed-Source-Produkt umwandeln. +* **Die Namensnennung-Bedingung:** Der obige Urheberrechtshinweis und dieser Berechtigungshinweis müssen in allen Kopien oder wesentlichen Teilen der Software enthalten sein. +* **Die Einladung zur Inspektion:** Da saQut dafür gebaut wurde, inspiziert zu werden, werden Sie ausdrücklich dazu ermutigt (wenn auch nicht rechtlich gezwungen), Ihren Schülern, Studenten oder dem Publikum mindestens einmal die Ausgabe von `saqut tokens` oder `saqut ast` zu zeigen, wenn Sie diesen Compiler in einem Bildungsprojekt, im Unterricht oder bei einer öffentlichen Präsentation verwenden. Halten Sie die Interna sichtbar! + +#### 3. Die Laufzeit- und Ausgabe-Ausnahme (KRITISCH) +Um die absolute Freiheit der Entwickler zu gewährleisten, die diese Sprache verwenden: +* **Ihr Code gehört Ihnen:** Quellcode, der *in* der saQut-Sprache geschrieben wurde (z. B. `.sqt`-Dateien), und alle vom Compiler generierten Daten (wie JSON-AST-Dumps, Symboltabellen oder kompilierter Bytecode) unterliegen **NICHT** dieser Lizenz. +* Entwickler können den Quellcode ihrer eigenen saQut-Programme und Compiler-Ausgaben nach eigenem Ermessen lizenzieren, verkaufen oder schließen. Die von saQut bereitgestellte Laufzeitumgebung/VM kann in andere Anwendungen eingebettet werden, ohne die Lizenzen dieser Anwendungen einzuschränken. + +#### 4. Haftungsausschluss +DIE SOFTWARE WIRD „WIE BESEHEN“ (AS IS) OHNE JEGLICHE AUSDRÜCKLICHE ODER ZIMNLICHE GEWÄHRLEISTUNG ZUR VERFÜGUNG GESTELLT, EINSCHLIESSLICH, ABER NICHT BESCHRÄNKT AUF DIE GEWÄHRLEISTUNG DER MARKTGÄNGIGKEIT, DER EIGNUNG FÜR EINEN BESTIMMTEN ZWECK UND DER NICHTVERLETZUNG VON RECHTEN DRITTER. IN KEINEM FALL SIND DIE AUTOREN ODER URHEBERRECHTSINHABER FÜR ANSPRÜCHE, SCHÄDEN ODER ANDERE HAFTUNGEN HAFTPAR, SEI ES IN FOLGE EINES VERTRAGES, EINER UNERLAUBTEN HANDLUNG ODER AUF ANDERE WEISE, DIE SICH AUS ODER IM ZUSAMMENHANG MIT DER SOFTWARE ODER DER NUTZUNG ODER DEM UMGANG MIT DER SOFTWARE ERGEBEN. \ No newline at end of file From dae55d5907fdabda38cb97acf583ffe991e3ecc5 Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Sun, 14 Jun 2026 23:48:22 +0300 Subject: [PATCH 05/28] =?UTF-8?q?docs:=20lisans=C4=B1=20yeniden=20yaz=20(k?= =?UTF-8?q?ayna=C4=9F=C4=B1=20a=C3=A7=C4=B1k,=20ticari=20kullan=C4=B1m?= =?UTF-8?q?=C4=B1=20k=C4=B1s=C4=B1tl=C4=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Önceki metin GPL tarzı copyleft bir "özgür yazılım" lisansıydı ve niyetle çelişiyordu (ticari kullanıma açıkça izin veriyordu). Çekirdek ilke netleşti: gelir saQut'un ürettiği çıktıdan elde edilir, saQut'un kendisinden değil. - Üç dilde (TR/EN/DE) yeniden yazıldı, kurumsal dile çekildi - Tanımlar, Ticari Kısıtlamalar ve sunucu/sürüm notu eklendi - Çıktı istisnası korundu ve güçlendirildi - İzin/iletişim maddesi (ticari lisans) eklendi - Almanca yazım hataları düzeltildi Co-Authored-By: Claude Opus 4.8 --- LICENSE.md | 174 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 123 insertions(+), 51 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 72748b0..e64b715 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -2,95 +2,167 @@ [Türkçe Sürüm](#türkçe-lisans-sürümü) | [English Version](#english-license-version) | [Deutsche Version](#deutsche-lizenzversion) +> Bu lisans üç dilde sunulmuştur. Yorum farklılıklarında **Türkçe sürüm esas alınır.** +> This license is provided in three languages. In case of any discrepancy, the **Turkish version prevails.** + --- ### Türkçe Lisans Sürümü -# saQut Kamu Lisansı (Sürüm 1.0) +# saQut Lisansı (Sürüm 1.0) +**Kaynağı Açık — Ticari Kullanımı Kısıtlı Lisans** -Telif Hakkı (c) 2026, Abdussamed ULUTAŞ (ve saQut Katkıda Bulunanları). -Tüm hakları saklıdır. +Telif Hakkı (c) 2026, Abdussamed ULUTAŞ (ve saQut Katkıda Bulunanları). Tüm hakları saklıdır. -Bu lisans; saQut Derleyicisi, kaynak kodları, derleme betikleri (build scripts) ve beraberindeki dokümantasyonu (toplu olarak "Yazılım" olarak anılacaktır) kapsar. +Bu lisans; saQut derleyicisini, kaynak kodlarını, derleme betiklerini (build scripts), tüm backend bileşenlerini (yorumlayıcı, bytecode VM, derleyici ve transpiler) ve beraberindeki dokümantasyon ile mimari tasarımı (ADR belgeleri dâhil) — toplu olarak "Yazılım" olarak anılacaktır — kapsar. ---- +saQut açık kaynaklı (kaynağı görülebilir) bir projedir; ancak **özgür yazılım (free/libre software) değildir.** Yazılımın incelenmesi ve değiştirilmesi serbestken, ticari kullanımı işbu lisansın koşullarına ve telif hakkı sahibinin iznine tabidir. #### 1. Temel Felsefe (Alet Çantası Kuralı) -saQut, programlanabilir ve incelenebilir bir derleyici alet çantası (toolbox) olarak tasarlanmıştır. Ana varlık sebebi; derleme sürecinin (Token'lar, AST, Sembol Tabloları ve IR) dışarıdan tamamen şeffaf ve görülebilir kalmasıdır. Bu Yazılımın her türlü yeniden dağıtımı veya üzerinde yapılacak değişiklikler bu şeffaflık ilkesine saygı duymak zorundadır. +saQut; programlanabilir ve incelenebilir bir derleyici alet çantası (toolbox) olarak tasarlanmıştır. Varlık sebebi, derleme sürecinin her aşamasının — token'lar, Soyut Sözdizimi Ağacı (AST), sembol tabloları ve Ara Temsil (IR) — dışarıdan şeffaf ve görülebilir kalmasıdır. Yazılımın her türlü yeniden dağıtımı ve üzerinde yapılacak değişiklikler bu şeffaflık ilkesini korumakla yükümlüdür. -#### 2. İzinler ve Koşullar -Bu Yazılımın bir kopyasını edinen herhangi bir kişiye; aşağıdaki koşullara uymak kaydıyla, Yazılımı kullanma, kopyalama, değiştirme, birleştirme, yayınlama veya dağıtma hakkı ücretsiz olarak tanınmıştır: +#### 2. Tanımlar +- **Yazılım:** Yukarıda tanımlanan saQut derleyicisi ve tüm bileşenleri (kaynak kod, yorumlayıcı, bytecode VM, derleyici ve transpiler backend'leri, dokümantasyon ve mimari tasarım). +- **Çıktı:** Yazılım kullanılarak üretilen her şey; saQut dilinde yazılmış kaynak kodlar (`.sqt` dosyaları), token/AST/sembol tablosu dökümleri, üretilen bytecode, transpile edilmiş kaynak kod, bağımsız çalıştırılabilir dosyalar ve Yazılımın işlediği verilerden elde edilen sonuçlar. +- **Ticari Kullanım:** Yazılımın kendisinden doğrudan veya dolaylı olarak gelir elde edilmesi; Yazılımın bir ürün, hizmet, motor, bileşen veya otomasyon aracı olarak Üçüncü Taraflara sunulması, kurulması ya da onlar adına işletilmesi. +- **Üçüncü Taraf:** Yazılımı kullanan kişi veya kurum dışında kalan müşteri, son kullanıcı ya da diğer taraflar. -* **Copyleft (Açık Kaynak Kalma) Şartı:** Eğer Yazılım üzerinde bir değişiklik yaparsanız (derleyici, lexer, parser, VM veya çekirdek mimari) ve bunu dağıtırsanız, değiştirdiğiniz kaynak kodları da BU AYNI LİSANS altında açık kaynaklı olarak herkese sunmak zorundasınız. saQut'u alıp kapalı kaynaklı, tescilli bir ticari ürüne dönüştüremezsiniz. -* **Atıf Şartı:** Orijinal telif hakkı bildirimi ve işbu izin bildirimi, Yazılımın tüm kopyalarına veya önemli parçalarına dahil edilmelidir. -* **İnceleme ve Şeffaflık Daveti:** saQut incelenmek için var olduğundan; bu derleyiciyi eğitim projelerinde, sınıflarda veya topluluk sunumlarında kullanırsanız, öğrencilerinize veya dinleyicilerinize en az bir kez `saqut tokens` veya `saqut ast` çıktılarını göstermeniz önemle tavsiye edilir (hukuki bir zorunluluk değildir). İç mekanizmayı görünür tutun! +#### 3. İnceleme, Değiştirme ve Ticari Olmayan Kullanım İzni +İşbu lisans kapsamında herkese, ücretsiz olarak aşağıdaki haklar tanınır: +- Yazılımı kişisel, eğitsel ve ticari olmayan amaçlarla kullanmak, incelemek ve çalıştırmak. +- Yazılımın kaynak kodunu incelemek ve değiştirmek. +- Değiştirilmiş veya değiştirilmemiş kopyaları ticari olmayan koşullarda dağıtmak. Ancak dağıtılan her kopya; (a) işbu lisansa tabi kalmalı, (b) kaynağı açık (source-available) kalmalı ve (c) aşağıdaki Atıf Şartı'na uymalıdır. -#### 3. Runtime (Çalışma Zamanı) ve Çıktı İstisnası (KRİTİK) -Bu dili kullanan geliştiricilerin mutlak özgürlüğünü garanti altına almak adına: -* **Kodunuz Sizindir:** saQut diliyle yazılmış tüm kaynak kodları (örn. `.sqt` dosyaları) ve derleyici tarafından üretilen tüm veriler (JSON AST dökümleri, sembol tabloları veya derlenmiş bytecode çıktısı) bu lisansın kısıtlamalarına **TABİ DEĞİLDİR**. -* Geliştiriciler, kendi saQut programlarının kaynak kodlarını ve derleyici çıktılarını istedikleri gibi lisanslamakta, satmakta veya kapalı kaynak yapmakta tamamen özgürdür. saQut tarafından sağlanan çalışma zamanı ortamı (runtime/VM), bu ortamı barındıran ana uygulamaların lisanslarını kısıtlamaksızın diğer uygulamaların içine gömülebilir (embed edilebilir). +#### 4. Çıktı ve Sonuç İstisnası (KRİTİK) +Yazılımı kullanan geliştiricilerin özgürlüğünü güvence altına almak amacıyla: +- **Çıktı sizindir.** Bölüm 2'de tanımlanan tüm Çıktı, işbu lisansın kısıtlamalarına **tabi değildir.** Geliştiriciler kendi Çıktılarını diledikleri gibi kullanma, kapatma (kapalı kaynak yapma), lisanslama ve **ticari olarak satma** hakkına tam olarak sahiptir. +- **Gelir, Çıktıdan elde edilir.** Yazılımı kendi makinenizde (kişisel veya kurumsal) özel bir araç olarak kullanıp ürettiğiniz programları, bağımsız çalıştırılabilir dosyaları veya işlenmiş verileri (örneğin bir Excel raporu veya bir veritabanı sonucu) satmanız serbesttir. Bu durumda Üçüncü Taraf, Yazılımı değil yalnızca sonucu alır. -#### 4. Garanti Reddi -YAZILIM "OLDUĞU GİBİ" SUNULMAKTADIR; TİCARETE UYGUNLUK, BELİRLİ BİR AMACA UYGUNLUK VE İHLAL ETMEME GARANTİLERİ DAHİL ANCAK BUNLARLA SINIRLI OLMAMAK ÜZERE, AÇIK VEYA ZIMNİ HERHANGİ BİR GARANTİ VERİLMEMEKTEDİR. YAZARLAR VEYA TELİF HAKKI SAHİPLERİ, YAZILIMLA VEYA YAZILIMIN KULLANIMIYLA YA DA DİĞER İŞLEMLERLE BAĞLANTILI OLARAK ORTAYA ÇIKAN SÖZLEŞME, HAKSIZ FİİL VEYA DİĞER DURUMLARDAKİ HİÇBİR TALEP, TAZMİNAT VEYA DİĞER YÜKÜMLÜLÜKLERDEN SORUMLU TUTULAMAZ. +#### 5. Ticari Kısıtlamalar +Aşağıdaki kullanımlar, Yazılımın bizzat kendisinden gelir elde edilmesi anlamına geldiğinden, telif hakkı sahibinin önceden yazılı izni olmaksızın yapılamaz: +- Yazılımı bir Üçüncü Taraf'ın sunucusuna veya cihazına kurup çalıştırılması karşılığında ücret almak (örneğin bir müşteri için `saqut run yedek.sql` komutunu çalıştırıp ücret talep etmek). +- Yazılımı çevrimiçi bir hizmet olarak sunmak (Web tabanlı IDE, çevrimiçi derleme veya çalıştırma servisi). +- Yazılımı, Üçüncü Tarafların canlı istekleriyle işleyen ticari bir hizmetin backend'i veya motoru hâline getirmek. +- Yazılımı ticari bir otomasyon/iş hattının (pipeline) aracı olarak işletmek ya da bir yapay zekâ sistemine araç olarak sağlamak. +- Yazılımı ticari bir ürünün alt bileşeni olarak gömmek (embed). +- Yazılımın iç bileşenlerini veya mimari tasarımını (örneğin AST görüntüleme veya optimizasyon algoritmaları) ticari bir özellik ya da ürün olarak yeniden kullanmak. + +**Sunucu ve sürüm notu:** Yazılım çalışmak için saQut çalışma zamanına (yorumlayıcı / bytecode VM) ihtiyaç duyduğu sürece, sunucu tarafındaki her ticari kullanım fiilen Yazılımı sunucuya yerleştirmek anlamına gelir ve bu nedenle yukarıdaki kısıtlamalara tabidir. Yazılımın, saQut çalışma zamanına ihtiyaç duymayan bağımsız çalıştırılabilir dosyalar üreten backend'i kullanıma sunulduğunda; bu tür bağımsız Çıktıların sunucuda ticari olarak çalıştırılması Bölüm 4 kapsamında serbesttir. + +#### 6. İzin ve Ticari Lisans +Bölüm 5'te sayılan kısıtlamaların tamamı yalnızca telif hakkı sahibine aittir ve istisna tanıma yetkisi münhasıran ona aittir. Bu kullanımlardan herhangi birini gerçekleştirmek isteyen kişi veya kurum, telif hakkı sahibinden (Abdussamed ULUTAŞ) önceden yazılı izin talep edebilir; izin verildiği takdirde ilgili kullanım serbest hâle gelir. +İletişim (ticari lisans talepleri): saqutsoftware+gitea@gmail.com + +#### 7. Atıf Şartı +Orijinal telif hakkı bildirimi ile işbu izin bildirimi, Yazılımın tüm kopyalarına veya önemli parçalarına dâhil edilmelidir. + +#### 8. Garanti Reddi +YAZILIM "OLDUĞU GİBİ" SUNULMAKTADIR; TİCARETE UYGUNLUK, BELİRLİ BİR AMACA UYGUNLUK VE İHLAL ETMEME GARANTİLERİ DAHİL ANCAK BUNLARLA SINIRLI OLMAMAK ÜZERE, AÇIK VEYA ZIMNİ HİÇBİR GARANTİ VERİLMEMEKTEDİR. YAZARLAR VEYA TELİF HAKKI SAHİPLERİ, YAZILIMLA VEYA YAZILIMIN KULLANIMIYLA YA DA DİĞER İŞLEMLERLE BAĞLANTILI OLARAK ORTAYA ÇIKAN SÖZLEŞME, HAKSIZ FİİL VEYA DİĞER DURUMLARDAKİ HİÇBİR TALEP, TAZMİNAT VEYA DİĞER YÜKÜMLÜLÜKLERDEN SORUMLU TUTULAMAZ. --- ### English License Version -# The saQut Public License (Version 1.0) +# The saQut License (Version 1.0) +**Source-Available — Commercial-Use Restricted License** -Copyright (c) 2026, Abdussamed ULUTAŞ (and saQut Contributors). -All rights reserved. +Copyright (c) 2026, Abdussamed ULUTAŞ (and saQut Contributors). All rights reserved. -This license applies to the saQut Compiler, its source code, build scripts, and accompanying documentation (collectively referred to as "the Software"). +This license applies to the saQut compiler, its source code, build scripts, all backend components (the interpreter, the bytecode VM, the compiler, and the transpiler), and the accompanying documentation and architectural design (including the ADR documents) — collectively referred to as "the Software". ---- +saQut is an open-source (source-available) project; however, it is **not free/libre software.** While inspecting and modifying the Software is permitted, its commercial use is subject to the terms of this license and to the permission of the copyright holder. -#### 1. The Core Philosophy (The Toolbox Rule) -saQut is designed as a programmable, inspectable compiler toolbox. Its core purpose is to keep the compilation process transparent (Tokens, AST, Symbol Tables, and IR). Any redistribution or modification of this Software must respect this transparency. +#### 1. Core Philosophy (The Toolbox Rule) +saQut is designed as a programmable, inspectable compiler toolbox. Its reason for existence is to keep every stage of the compilation process — tokens, the Abstract Syntax Tree (AST), symbol tables, and the Intermediate Representation (IR) — transparent and observable from the outside. Any redistribution or modification of the Software must preserve this principle of transparency. -#### 2. Permissions & Conditions -Permission is hereby granted, free of charge, to any person obtaining a copy of this Software, to use, copy, modify, merge, publish, or distribute the Software, subject to the following conditions: +#### 2. Definitions +- **The Software:** The saQut compiler and all of its components as defined above (source code, interpreter, bytecode VM, compiler and transpiler backends, documentation, and architectural design). +- **Output:** Anything produced using the Software; source code written in the saQut language (`.sqt` files), token/AST/symbol-table dumps, generated bytecode, transpiled source code, standalone executables, and any results derived from data processed by the Software. +- **Commercial Use:** Deriving revenue, directly or indirectly, from the Software itself; offering, deploying, or operating the Software as a product, service, engine, component, or automation tool for or on behalf of Third Parties. +- **Third Party:** Any customer, end user, or other party other than the person or organization using the Software. -* **The Copyleft Requirement:** If you modify the Software (the compiler, lexer, parser, VM, or core architecture) and distribute it, you MUST make your modified source code publicly available under this same license. You cannot turn saQut into a closed-source proprietary product. -* **The Attribution Requirement:** The original copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -* **The Inspection Invitation:** Since saQut is built to be inspected, if you use this compiler in an educational project, classroom, or public presentation, you are highly encouraged (though not legally forced) to show your students or audience the output of `saqut tokens` or `saqut ast` at least once. Keep the internals visible! +#### 3. Permission to Inspect, Modify, and Use Non-Commercially +This license grants everyone, free of charge, the following rights: +- To use, inspect, and run the Software for personal, educational, and non-commercial purposes. +- To inspect and modify the source code of the Software. +- To distribute modified or unmodified copies under non-commercial terms, provided that each distributed copy (a) remains under this license, (b) remains source-available, and (c) complies with the Attribution Requirement below. -#### 3. The Runtime & Output Exception (CRITICAL) -To ensure the absolute freedom of the developers using this language: -* **Your Code is Yours:** Any source code written *in* the saQut language (e.g., `.sqt` files), and any data generated *by* the compiler (such as JSON AST dumps, symbol tables, or compiled bytecode) are **NOT** subject to this license. -* Developers are completely free to license, sell, or close the source code of their own saQut programs and compiler outputs as they see fit. The runtime environment/VM provided by saQut may be embedded into other applications without restricting those applications' licenses. +#### 4. The Output & Results Exception (CRITICAL) +To safeguard the freedom of developers using the Software: +- **Your Output is yours.** All Output as defined in Section 2 is **not** subject to the restrictions of this license. Developers retain the full right to use, close (make proprietary), license, and **sell commercially** their own Output. +- **Revenue is earned from the Output.** You are free to use the Software as a private tool on your own machine (personal or corporate) and to sell the programs, standalone executables, or processed data you produce (for example, an Excel report or a database result). In such cases the Third Party receives only the result, not the Software. -#### 4. Disclaimer of Warranty +#### 5. Commercial Restrictions +Because the following uses amount to deriving revenue from the Software itself, they may not be carried out without the prior written permission of the copyright holder: +- Installing the Software on a Third Party's server or device and charging for its execution (for example, running `saqut run backup.sql` for a customer for a fee). +- Offering the Software as an online service (a web-based IDE, or an online compilation or execution service). +- Making the Software the backend or engine of a commercial service that is driven by the live requests of Third Parties. +- Operating the Software as a tool within a commercial automation pipeline, or providing it as a tool to an artificial-intelligence system. +- Embedding the Software as a sub-component of a commercial product. +- Repurposing the internal components or architectural design of the Software (for example, its AST visualization or optimization algorithms) as a commercial feature or product. + +**Server and version note:** As long as the Software requires the saQut runtime (the interpreter / bytecode VM) in order to run, any commercial server-side use effectively places the Software on the server and is therefore subject to the restrictions above. Once a backend that produces standalone executables not requiring the saQut runtime becomes available, running such standalone Output commercially on a server is permitted under Section 4. + +#### 6. Permission and Commercial Licensing +All restrictions listed in Section 5 belong solely to the copyright holder, who has the exclusive authority to grant exceptions. Any person or organization wishing to carry out any of these uses may request prior written permission from the copyright holder (Abdussamed ULUTAŞ); once granted, the relevant use becomes permitted. +Contact (commercial-license requests): saqutsoftware+gitea@gmail.com + +#### 7. Attribution Requirement +The original copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +#### 8. Disclaimer of Warranty THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --- ### Deutsche Lizenzversion -# Die saQut Öffentliche Lizenz (Version 1.0) +# Die saQut-Lizenz (Version 1.0) +**Quelloffene Lizenz mit eingeschränkter kommerzieller Nutzung** -Copyright (c) 2026, Abdussamed ULUTAŞ (und saQut Mitwirkende). -Alle Rechte vorbehalten. +Copyright (c) 2026, Abdussamed ULUTAŞ (und saQut-Mitwirkende). Alle Rechte vorbehalten. -Diese Lizenz gilt für den saQut-Compiler, seinen Quellcode, Build-Skripte und die dazugehörige Dokumentation (zusammenfassend als „die Software“ bezeichnet). +Diese Lizenz gilt für den saQut-Compiler, seinen Quellcode, die Build-Skripte, alle Backend-Komponenten (den Interpreter, die Bytecode-VM, den Compiler und den Transpiler) sowie die dazugehörige Dokumentation und den architektonischen Entwurf (einschließlich der ADR-Dokumente) — zusammenfassend als „die Software" bezeichnet. ---- +saQut ist ein quelloffenes (einsehbares) Projekt; es ist jedoch **keine freie Software (Free/Libre Software).** Während das Einsehen und Verändern der Software gestattet ist, unterliegt ihre kommerzielle Nutzung den Bedingungen dieser Lizenz und der Genehmigung des Urheberrechtsinhabers. #### 1. Die Kernphilosophie (Die Toolbox-Regel) -saQut ist als programmierbare, inspizierbare Compiler-Toolbox konzipiert. Der Hauptzweck besteht darin, den Kompilierungsprozess (Tokens, AST, Symboltabellen und IR) transparent zu halten. Jede Weitergabe oder Änderung dieser Software muss diese Transparenz respektieren. +saQut ist als programmierbare, inspizierbare Compiler-Toolbox konzipiert. Ihr Daseinszweck ist es, jede Phase des Kompilierungsprozesses — Tokens, den Abstrakten Syntaxbaum (AST), Symboltabellen und die Zwischendarstellung (IR) — von außen transparent und einsehbar zu halten. Jede Weitergabe oder Veränderung der Software muss diesen Grundsatz der Transparenz wahren. -#### 2. Berechtigungen & Bedingungen -Hiermit wird jeder Person, die eine Kopie dieser Software erhält, kostenlos die Berechtigung erteilt, die Software zu nutzen, zu kopieren, zu modifizieren, zusammenzufügen, zu veröffentlichen oder zu verbreiten, sofern folgende Bedingungen erfüllt sind: +#### 2. Definitionen +- **Die Software:** Der oben definierte saQut-Compiler und alle seine Komponenten (Quellcode, Interpreter, Bytecode-VM, Compiler- und Transpiler-Backends, Dokumentation und architektonischer Entwurf). +- **Ausgabe:** Alles, was mithilfe der Software erzeugt wird; in der saQut-Sprache geschriebener Quellcode (`.sqt`-Dateien), Token-/AST-/Symboltabellen-Ausgaben, erzeugter Bytecode, transpilierter Quellcode, eigenständige ausführbare Dateien sowie alle Ergebnisse, die aus von der Software verarbeiteten Daten gewonnen werden. +- **Kommerzielle Nutzung:** Das direkte oder indirekte Erzielen von Einnahmen aus der Software selbst; das Anbieten, Bereitstellen oder Betreiben der Software als Produkt, Dienst, Engine, Komponente oder Automatisierungswerkzeug für oder im Auftrag von Dritten. +- **Dritte:** Jeder Kunde, Endnutzer oder sonstige Partei außer der Person oder Organisation, die die Software nutzt. -* **Die Copyleft-Bedingung:** Wenn Sie die Software verändern (Compiler, Lexer, Parser, VM oder Kernarchitektur) und verbreiten, MÜSSEN Sie Ihren geänderten Quellcode unter derselben Lizenz öffentlich zugänglich machen. Sie dürfen saQut nicht in ein proprietäres Closed-Source-Produkt umwandeln. -* **Die Namensnennung-Bedingung:** Der obige Urheberrechtshinweis und dieser Berechtigungshinweis müssen in allen Kopien oder wesentlichen Teilen der Software enthalten sein. -* **Die Einladung zur Inspektion:** Da saQut dafür gebaut wurde, inspiziert zu werden, werden Sie ausdrücklich dazu ermutigt (wenn auch nicht rechtlich gezwungen), Ihren Schülern, Studenten oder dem Publikum mindestens einmal die Ausgabe von `saqut tokens` oder `saqut ast` zu zeigen, wenn Sie diesen Compiler in einem Bildungsprojekt, im Unterricht oder bei einer öffentlichen Präsentation verwenden. Halten Sie die Interna sichtbar! +#### 3. Genehmigung zum Einsehen, Verändern und zur nicht-kommerziellen Nutzung +Diese Lizenz gewährt jeder Person kostenlos die folgenden Rechte: +- Die Software zu persönlichen, schulischen/bildenden und nicht-kommerziellen Zwecken zu nutzen, einzusehen und auszuführen. +- Den Quellcode der Software einzusehen und zu verändern. +- Veränderte oder unveränderte Kopien unter nicht-kommerziellen Bedingungen weiterzugeben, sofern jede weitergegebene Kopie (a) dieser Lizenz unterstellt bleibt, (b) quelloffen (source-available) bleibt und (c) der nachstehenden Namensnennung-Bedingung entspricht. -#### 3. Die Laufzeit- und Ausgabe-Ausnahme (KRITISCH) -Um die absolute Freiheit der Entwickler zu gewährleisten, die diese Sprache verwenden: -* **Ihr Code gehört Ihnen:** Quellcode, der *in* der saQut-Sprache geschrieben wurde (z. B. `.sqt`-Dateien), und alle vom Compiler generierten Daten (wie JSON-AST-Dumps, Symboltabellen oder kompilierter Bytecode) unterliegen **NICHT** dieser Lizenz. -* Entwickler können den Quellcode ihrer eigenen saQut-Programme und Compiler-Ausgaben nach eigenem Ermessen lizenzieren, verkaufen oder schließen. Die von saQut bereitgestellte Laufzeitumgebung/VM kann in andere Anwendungen eingebettet werden, ohne die Lizenzen dieser Anwendungen einzuschränken. +#### 4. Die Ausnahme für Ausgabe und Ergebnisse (KRITISCH) +Um die Freiheit der Entwickler zu gewährleisten, die die Software nutzen: +- **Ihre Ausgabe gehört Ihnen.** Die gesamte in Abschnitt 2 definierte Ausgabe unterliegt **nicht** den Beschränkungen dieser Lizenz. Entwickler behalten das uneingeschränkte Recht, ihre eigene Ausgabe zu nutzen, zu schließen (proprietär zu machen), zu lizenzieren und **kommerziell zu verkaufen.** +- **Einnahmen werden aus der Ausgabe erzielt.** Es steht Ihnen frei, die Software als privates Werkzeug auf Ihrem eigenen Rechner (privat oder geschäftlich) zu nutzen und die von Ihnen erzeugten Programme, eigenständigen ausführbaren Dateien oder verarbeiteten Daten (etwa einen Excel-Bericht oder ein Datenbankergebnis) zu verkaufen. In diesem Fall erhält der Dritte nur das Ergebnis, nicht die Software. -#### 4. Haftungsausschluss -DIE SOFTWARE WIRD „WIE BESEHEN“ (AS IS) OHNE JEGLICHE AUSDRÜCKLICHE ODER ZIMNLICHE GEWÄHRLEISTUNG ZUR VERFÜGUNG GESTELLT, EINSCHLIESSLICH, ABER NICHT BESCHRÄNKT AUF DIE GEWÄHRLEISTUNG DER MARKTGÄNGIGKEIT, DER EIGNUNG FÜR EINEN BESTIMMTEN ZWECK UND DER NICHTVERLETZUNG VON RECHTEN DRITTER. IN KEINEM FALL SIND DIE AUTOREN ODER URHEBERRECHTSINHABER FÜR ANSPRÜCHE, SCHÄDEN ODER ANDERE HAFTUNGEN HAFTPAR, SEI ES IN FOLGE EINES VERTRAGES, EINER UNERLAUBTEN HANDLUNG ODER AUF ANDERE WEISE, DIE SICH AUS ODER IM ZUSAMMENHANG MIT DER SOFTWARE ODER DER NUTZUNG ODER DEM UMGANG MIT DER SOFTWARE ERGEBEN. \ No newline at end of file +#### 5. Kommerzielle Beschränkungen +Da die folgenden Nutzungen darauf hinauslaufen, Einnahmen aus der Software selbst zu erzielen, dürfen sie ohne vorherige schriftliche Genehmigung des Urheberrechtsinhabers nicht vorgenommen werden: +- Die Software auf dem Server oder Gerät eines Dritten zu installieren und für ihre Ausführung ein Entgelt zu verlangen (zum Beispiel das Ausführen von `saqut run backup.sql` für einen Kunden gegen Bezahlung). +- Die Software als Online-Dienst anzubieten (eine webbasierte IDE oder einen Online-Kompilier- oder -Ausführungsdienst). +- Die Software zum Backend oder zur Engine eines kommerziellen Dienstes zu machen, der durch die Live-Anfragen Dritter angetrieben wird. +- Die Software als Werkzeug innerhalb einer kommerziellen Automatisierungs-Pipeline zu betreiben oder sie einem System künstlicher Intelligenz als Werkzeug bereitzustellen. +- Die Software als Unterkomponente eines kommerziellen Produkts einzubetten (embedden). +- Die internen Komponenten oder den architektonischen Entwurf der Software (zum Beispiel ihre AST-Visualisierung oder Optimierungsalgorithmen) als kommerzielles Merkmal oder Produkt wiederzuverwenden. + +**Server- und Versionshinweis:** Solange die Software zur Ausführung die saQut-Laufzeitumgebung (den Interpreter / die Bytecode-VM) benötigt, bedeutet jede kommerzielle serverseitige Nutzung faktisch das Platzieren der Software auf dem Server und unterliegt daher den obigen Beschränkungen. Sobald ein Backend verfügbar ist, das eigenständige ausführbare Dateien erzeugt, die die saQut-Laufzeitumgebung nicht benötigen, ist das kommerzielle Ausführen einer solchen eigenständigen Ausgabe auf einem Server gemäß Abschnitt 4 gestattet. + +#### 6. Genehmigung und kommerzielle Lizenzierung +Alle in Abschnitt 5 aufgeführten Beschränkungen stehen ausschließlich dem Urheberrechtsinhaber zu, der allein befugt ist, Ausnahmen zu gewähren. Jede Person oder Organisation, die eine dieser Nutzungen vornehmen möchte, kann beim Urheberrechtsinhaber (Abdussamed ULUTAŞ) eine vorherige schriftliche Genehmigung beantragen; nach deren Erteilung wird die betreffende Nutzung gestattet. +Kontakt (Anfragen für kommerzielle Lizenzen): saqutsoftware+gitea@gmail.com + +#### 7. Namensnennung-Bedingung +Der ursprüngliche Urheberrechtshinweis und dieser Genehmigungshinweis müssen in allen Kopien oder wesentlichen Teilen der Software enthalten sein. + +#### 8. Haftungsausschluss +DIE SOFTWARE WIRD „WIE BESEHEN" (AS IS) OHNE JEGLICHE AUSDRÜCKLICHE ODER STILLSCHWEIGENDE GEWÄHRLEISTUNG ZUR VERFÜGUNG GESTELLT, EINSCHLIESSLICH, ABER NICHT BESCHRÄNKT AUF DIE GEWÄHRLEISTUNG DER MARKTGÄNGIGKEIT, DER EIGNUNG FÜR EINEN BESTIMMTEN ZWECK UND DER NICHTVERLETZUNG VON RECHTEN DRITTER. IN KEINEM FALL SIND DIE AUTOREN ODER URHEBERRECHTSINHABER FÜR ANSPRÜCHE, SCHÄDEN ODER ANDERE HAFTUNGEN HAFTBAR, SEI ES IN FOLGE EINES VERTRAGES, EINER UNERLAUBTEN HANDLUNG ODER AUF ANDERE WEISE, DIE SICH AUS ODER IM ZUSAMMENHANG MIT DER SOFTWARE ODER DER NUTZUNG ODER DEM UMGANG MIT DER SOFTWARE ERGEBEN. From e2a82f9bb9950c21ed48b8b30af174b399eac029 Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Sun, 14 Jun 2026 23:58:52 +0300 Subject: [PATCH 06/28] =?UTF-8?q?docs:=20lisansa=20katk=C4=B1,=20patent,?= =?UTF-8?q?=20marka=20ve=20fesih=20maddeleri=20ekle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Katkı (§7): PR herkese açık, birleştirme kararı yalnızca Abdussamed ULUTAŞ'a ait; katkı sahipleri ticari lisanslama dâhil hakları telif sahibine verir (ticari lisans modelinin önünü açar) - Patent (§8): açık patent lisansı + patent davasında otomatik fesih - Marka/İsim (§9): "saQut" adı/markası üzerinde hak verilmez - Fesih (§11): ihlalde otomatik fesih + 30 gün düzeltme; edinilmiş Çıktı hakları fesihten etkilenmez - Bölümler yeniden numaralandırıldı (3 dilde) Co-Authored-By: Claude Opus 4.8 --- LICENSE.md | 78 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 6 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index e64b715..13718f8 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -53,10 +53,32 @@ Aşağıdaki kullanımlar, Yazılımın bizzat kendisinden gelir elde edilmesi a Bölüm 5'te sayılan kısıtlamaların tamamı yalnızca telif hakkı sahibine aittir ve istisna tanıma yetkisi münhasıran ona aittir. Bu kullanımlardan herhangi birini gerçekleştirmek isteyen kişi veya kurum, telif hakkı sahibinden (Abdussamed ULUTAŞ) önceden yazılı izin talep edebilir; izin verildiği takdirde ilgili kullanım serbest hâle gelir. İletişim (ticari lisans talepleri): saqutsoftware+gitea@gmail.com -#### 7. Atıf Şartı +#### 7. Katkılar (Contributions) +saQut'a katkı herkese açık bir öneri sürecidir; ancak nihai karar münhasıran telif hakkı sahibine aittir. +- Herhangi biri değişiklik önerisi (Pull Request / PR) açabilir. Bir katkının projeye dâhil edilip edilmeyeceğine ve birleştirilip (merge) birleştirilmeyeceğine **yalnızca Abdussamed ULUTAŞ karar verir.** Hiç kimsenin, bir katkısını projeye dâhil ettirme yönünde bir hakkı yoktur. +- Bir katkıyı (kod, belge, tasarım veya başka bir materyal) gönderen kişi, bu katkıyı göndermekle telif hakkı sahibine (Abdussamed ULUTAŞ); katkı üzerinde **dünya çapında, süresiz, geri alınamaz, ücretsiz ve alt-lisans verilebilir** bir kullanma, çoğaltma, değiştirme, dağıtma ve **ticari olarak lisanslama** hakkı tanır. Bu hak, telif hakkı sahibinin katkıyı içeren Yazılımı Bölüm 6 kapsamında ticari olarak lisanslayabilmesini güvence altına alır. +- Katkıda bulunan; gönderdiği materyalin kendi eseri olduğunu veya gerekli haklara sahip bulunduğunu ve bu izni vermeye yetkili olduğunu beyan eder. Katkıda bulunanlar, kendi katkıları üzerindeki telif haklarını korur; yukarıdaki izin bu haklara ek olarak verilir. + +#### 8. Patent Hakları +- **Patent lisansı:** İşbu lisans kapsamında Yazılımı kullanma hakkına sahip olan her kişiye; telif hakkı sahibi ve katkıda bulunanlar tarafından sahip olunan ve Yazılımın bu lisansça izin verilen biçimde kullanılması için zorunlu olarak ihlal edilen patent istemleri bakımından, ücretsiz ve (aşağıdaki fesih hükmü saklı kalmak kaydıyla) geri alınamaz bir patent lisansı tanınır. +- **Patent misillemesi (otomatik fesih):** Eğer bir kişi veya kurum, Yazılımın bu lisansça izin verilen kullanımının bir patenti ihlal ettiğini ileri sürerek telif hakkı sahibine veya herhangi bir katkıda bulunana karşı **patent davası** açarsa, işbu lisans kapsamında o kişiye/kuruma tanınan tüm haklar (patent lisansı dâhil) **otomatik olarak sona erer.** + +#### 9. Marka ve İsim Hakları +İşbu lisans; "saQut" adı, logosu veya ilgili marka unsurları üzerinde **hiçbir hak tanımaz.** Özellikle: +- Yazılımın değiştirilmiş bir sürümünü dağıtırsanız, bu sürümü "saQut" adıyla veya bu adı çağrıştıracak ya da karıştırılmaya yol açabilecek bir adla adlandıramazsınız. +- Telif hakkı sahibinin önceden yazılı izni olmadan, "saQut" adını ürünlerinizde, hizmetlerinizde veya tanıtımlarınızda bir onay/destek ima edecek biçimde kullanamazsınız. +- Yazılımın kaynağına ve telif hakkı sahibine yapılan dürüst ve tanımlayıcı atıflar (örneğin "saQut tabanlıdır") bu maddenin kapsamı dışındadır. + +#### 10. Atıf Şartı Orijinal telif hakkı bildirimi ile işbu izin bildirimi, Yazılımın tüm kopyalarına veya önemli parçalarına dâhil edilmelidir. -#### 8. Garanti Reddi +#### 11. Fesih (Termination) +- İşbu lisansın koşullarından herhangi birini ihlal etmeniz hâlinde, lisans kapsamında size tanınan tüm haklar **otomatik olarak sona erer.** +- İhlaliniz düzeltilebilir nitelikteyse ve ihlali öğrendikten sonra **30 (otuz) gün** içinde giderirseniz — telif hakkı sahibi bu süre içinde lisansı açıkça feshetmemiş olmak kaydıyla — haklarınız yeniden yürürlüğe girer. Aynı kişinin tekrarlayan ihlallerinde bu düzeltme imkânı uygulanmaz. +- Haklarınızın sona ermesi, daha önce işbu lisansa uygun olarak edindiğiniz Çıktı (Bölüm 4) üzerindeki haklarınızı etkilemez. +- Garanti reddi ve sorumluluk sınırlamaları, fesihten sonra da yürürlükte kalmaya devam eder. + +#### 12. Garanti Reddi YAZILIM "OLDUĞU GİBİ" SUNULMAKTADIR; TİCARETE UYGUNLUK, BELİRLİ BİR AMACA UYGUNLUK VE İHLAL ETMEME GARANTİLERİ DAHİL ANCAK BUNLARLA SINIRLI OLMAMAK ÜZERE, AÇIK VEYA ZIMNİ HİÇBİR GARANTİ VERİLMEMEKTEDİR. YAZARLAR VEYA TELİF HAKKI SAHİPLERİ, YAZILIMLA VEYA YAZILIMIN KULLANIMIYLA YA DA DİĞER İŞLEMLERLE BAĞLANTILI OLARAK ORTAYA ÇIKAN SÖZLEŞME, HAKSIZ FİİL VEYA DİĞER DURUMLARDAKİ HİÇBİR TALEP, TAZMİNAT VEYA DİĞER YÜKÜMLÜLÜKLERDEN SORUMLU TUTULAMAZ. --- @@ -107,10 +129,32 @@ Because the following uses amount to deriving revenue from the Software itself, All restrictions listed in Section 5 belong solely to the copyright holder, who has the exclusive authority to grant exceptions. Any person or organization wishing to carry out any of these uses may request prior written permission from the copyright holder (Abdussamed ULUTAŞ); once granted, the relevant use becomes permitted. Contact (commercial-license requests): saqutsoftware+gitea@gmail.com -#### 7. Attribution Requirement +#### 7. Contributions +Contributing to saQut is an open proposal process; however, the final decision rests solely with the copyright holder. +- Anyone may open a change proposal (a Pull Request / PR). Whether a contribution is included in the project and whether it is merged is decided **solely by Abdussamed ULUTAŞ.** No one has any right to have their contribution included in the project. +- By submitting a contribution (code, documentation, design, or other material), the contributor grants the copyright holder (Abdussamed ULUTAŞ) a **worldwide, perpetual, irrevocable, royalty-free, and sublicensable** right to use, reproduce, modify, distribute, and **license commercially** that contribution. This right ensures that the copyright holder may license the Software including the contribution on a commercial basis under Section 6. +- The contributor represents that the submitted material is their own work or that they hold the necessary rights, and that they are authorized to grant this permission. Contributors retain copyright in their own contributions; the permission above is granted in addition to those rights. + +#### 8. Patent Rights +- **Patent license:** Subject to this license, each person who has the right to use the Software is granted a royalty-free and (except as stated in the termination provision below) irrevocable patent license, under those patent claims owned by the copyright holder and contributors that are necessarily infringed by using the Software in the manner permitted by this license. +- **Patent retaliation (automatic termination):** If any person or entity initiates **patent litigation** against the copyright holder or any contributor, alleging that the use of the Software as permitted by this license infringes a patent, then all rights granted to that person or entity under this license (including the patent license) **terminate automatically.** + +#### 9. Trademark and Name Rights +This license grants **no rights** in the "saQut" name, logo, or related trademark elements. In particular: +- If you distribute a modified version of the Software, you may not name that version "saQut" or use a name that evokes or is confusingly similar to it. +- You may not use the "saQut" name in your products, services, or promotions in a way that implies endorsement, without the prior written permission of the copyright holder. +- Honest, descriptive references to the origin of the Software and to the copyright holder (for example, "based on saQut") fall outside the scope of this section. + +#### 10. Attribution Requirement The original copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -#### 8. Disclaimer of Warranty +#### 11. Termination +- Upon your breach of any of the terms of this license, all rights granted to you under it **terminate automatically.** +- If your breach is curable and you cure it within **30 (thirty) days** of becoming aware of it — provided the copyright holder has not expressly terminated the license during that period — your rights are reinstated. This cure opportunity does not apply to repeated breaches by the same person. +- Termination of your rights does not affect your rights in any Output (Section 4) you previously obtained in compliance with this license. +- The disclaimer of warranty and the limitations of liability survive termination. + +#### 12. Disclaimer of Warranty THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --- @@ -161,8 +205,30 @@ Da die folgenden Nutzungen darauf hinauslaufen, Einnahmen aus der Software selbs Alle in Abschnitt 5 aufgeführten Beschränkungen stehen ausschließlich dem Urheberrechtsinhaber zu, der allein befugt ist, Ausnahmen zu gewähren. Jede Person oder Organisation, die eine dieser Nutzungen vornehmen möchte, kann beim Urheberrechtsinhaber (Abdussamed ULUTAŞ) eine vorherige schriftliche Genehmigung beantragen; nach deren Erteilung wird die betreffende Nutzung gestattet. Kontakt (Anfragen für kommerzielle Lizenzen): saqutsoftware+gitea@gmail.com -#### 7. Namensnennung-Bedingung +#### 7. Beiträge (Contributions) +Das Beitragen zu saQut ist ein offener Vorschlagsprozess; die endgültige Entscheidung liegt jedoch ausschließlich beim Urheberrechtsinhaber. +- Jede Person kann einen Änderungsvorschlag (einen Pull Request / PR) einreichen. Ob ein Beitrag in das Projekt aufgenommen und ob er zusammengeführt (gemerged) wird, entscheidet **allein Abdussamed ULUTAŞ.** Niemand hat ein Recht darauf, dass sein Beitrag in das Projekt aufgenommen wird. +- Mit der Einreichung eines Beitrags (Code, Dokumentation, Entwurf oder sonstiges Material) gewährt der Beitragende dem Urheberrechtsinhaber (Abdussamed ULUTAŞ) ein **weltweites, unbefristetes, unwiderrufliches, gebührenfreies und unterlizenzierbares** Recht, diesen Beitrag zu nutzen, zu vervielfältigen, zu verändern, zu verbreiten und **kommerziell zu lizenzieren.** Dieses Recht stellt sicher, dass der Urheberrechtsinhaber die Software einschließlich des Beitrags gemäß Abschnitt 6 kommerziell lizenzieren kann. +- Der Beitragende sichert zu, dass das eingereichte Material sein eigenes Werk ist oder dass er über die erforderlichen Rechte verfügt und befugt ist, diese Genehmigung zu erteilen. Die Beitragenden behalten das Urheberrecht an ihren eigenen Beiträgen; die obige Genehmigung wird zusätzlich zu diesen Rechten erteilt. + +#### 8. Patentrechte +- **Patentlizenz:** Im Rahmen dieser Lizenz wird jeder Person, die zur Nutzung der Software berechtigt ist, eine gebührenfreie und (vorbehaltlich der nachstehenden Kündigungsbestimmung) unwiderrufliche Patentlizenz an denjenigen Patentansprüchen gewährt, die im Eigentum des Urheberrechtsinhabers und der Beitragenden stehen und die durch die nach dieser Lizenz gestattete Nutzung der Software notwendigerweise verletzt werden. +- **Patentvergeltung (automatische Kündigung):** Leitet eine Person oder Organisation einen **Patentrechtsstreit** gegen den Urheberrechtsinhaber oder einen Beitragenden ein und macht dabei geltend, dass die nach dieser Lizenz gestattete Nutzung der Software ein Patent verletzt, so **erlöschen automatisch** alle dieser Person oder Organisation nach dieser Lizenz gewährten Rechte (einschließlich der Patentlizenz). + +#### 9. Marken- und Namensrechte +Diese Lizenz gewährt **keinerlei Rechte** an dem Namen „saQut", dem Logo oder verwandten Markenbestandteilen. Insbesondere: +- Wenn Sie eine veränderte Version der Software verbreiten, dürfen Sie diese Version nicht „saQut" nennen oder einen Namen verwenden, der daran erinnert oder verwechslungsfähig ähnlich ist. +- Sie dürfen den Namen „saQut" ohne vorherige schriftliche Genehmigung des Urheberrechtsinhabers nicht in Ihren Produkten, Diensten oder Werbemaßnahmen in einer Weise verwenden, die eine Billigung suggeriert. +- Ehrliche, beschreibende Hinweise auf den Ursprung der Software und auf den Urheberrechtsinhaber (zum Beispiel „basiert auf saQut") fallen nicht unter diesen Abschnitt. + +#### 10. Namensnennung-Bedingung Der ursprüngliche Urheberrechtshinweis und dieser Genehmigungshinweis müssen in allen Kopien oder wesentlichen Teilen der Software enthalten sein. -#### 8. Haftungsausschluss +#### 11. Kündigung (Termination) +- Bei einem Verstoß gegen eine der Bedingungen dieser Lizenz **erlöschen automatisch** alle Ihnen darunter gewährten Rechte. +- Ist Ihr Verstoß heilbar und beheben Sie ihn innerhalb von **30 (dreißig) Tagen**, nachdem Sie davon Kenntnis erlangt haben — sofern der Urheberrechtsinhaber die Lizenz in diesem Zeitraum nicht ausdrücklich gekündigt hat —, so werden Ihre Rechte wiederhergestellt. Diese Heilungsmöglichkeit gilt nicht für wiederholte Verstöße derselben Person. +- Das Erlöschen Ihrer Rechte berührt nicht Ihre Rechte an einer Ausgabe (Abschnitt 4), die Sie zuvor in Übereinstimmung mit dieser Lizenz erlangt haben. +- Der Haftungsausschluss und die Haftungsbeschränkungen gelten auch nach der Kündigung fort. + +#### 12. Haftungsausschluss DIE SOFTWARE WIRD „WIE BESEHEN" (AS IS) OHNE JEGLICHE AUSDRÜCKLICHE ODER STILLSCHWEIGENDE GEWÄHRLEISTUNG ZUR VERFÜGUNG GESTELLT, EINSCHLIESSLICH, ABER NICHT BESCHRÄNKT AUF DIE GEWÄHRLEISTUNG DER MARKTGÄNGIGKEIT, DER EIGNUNG FÜR EINEN BESTIMMTEN ZWECK UND DER NICHTVERLETZUNG VON RECHTEN DRITTER. IN KEINEM FALL SIND DIE AUTOREN ODER URHEBERRECHTSINHABER FÜR ANSPRÜCHE, SCHÄDEN ODER ANDERE HAFTUNGEN HAFTBAR, SEI ES IN FOLGE EINES VERTRAGES, EINER UNERLAUBTEN HANDLUNG ODER AUF ANDERE WEISE, DIE SICH AUS ODER IM ZUSAMMENHANG MIT DER SOFTWARE ODER DER NUTZUNG ODER DEM UMGANG MIT DER SOFTWARE ERGEBEN. From cbc7a3ddb5e73ba44d00c9a4e769158f0dd51579 Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Tue, 16 Jun 2026 00:06:54 +0300 Subject: [PATCH 07/28] =?UTF-8?q?docs:=20readme'ye=20"Tasar=C4=B1m=20felse?= =?UTF-8?q?fesi"=20b=C3=B6l=C3=BCm=C3=BC=20ekle=20(cam=20+=20kafes=20+=20r?= =?UTF-8?q?ecord-replay)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit saQut'un farklılaştırıcı tezini belgele: derleyiciyi platform olarak ele alan iki taahhüt (cam = her aşama gör/sorgula/müdahale; kafes = deterministik + yetenek-güvenli VM) ve bunların ödülü olan kayıt-tekrar (record-replay) vizyonu. Determinizm + tek kapı FFI disiplininin v0'dan korunması gerektiği not edildi. Co-Authored-By: Claude Opus 4.8 --- readme.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/readme.md b/readme.md index aa29342..01498b3 100644 --- a/readme.md +++ b/readme.md @@ -92,6 +92,46 @@ VM)** ile çalıştırır. --- +## Tasarım felsefesi — neden saQut farklı? + +saQut "daha iyi bir dil" iddiasında değil. Farkı, **derleyiciyi bir platform** +olarak ele almasında. İki taahhüt üstüne kuruludur: + +**1. Cam (gör + sorgula + içine müdahale et).** Her aşama — token, AST, sembol +tablosu, tip, IR — kararlı, makine-okur ve **çift yönlü** bir arayüzden +erişilebilir olmalıdır. Sadece "dök ve göster" değil: kendi AST'ini verip tip +kontrolü isteyebilmeli, IR verip çalıştırabilmelisin. **Turnusol testi:** bir +yabancı, yalnızca `saqut ast` + `saqut symbols` çıktısından, bizden habersiz bir +LSP yazabiliyor mu? Cevap "evet" ise platform gerçektir. + +**2. Kafes (deterministik + yetenek-güvenli çalıştırma).** Pointer yok, value +semantics, scope-tabanlı bellek ve **tek dış-dünya kapısı olan FFI seam** +(ADR-016) sayesinde saQut kodu, host'un açıkça izin verdiği fonksiyonlar dışında +dünyaya dokunamaz. Bytecode VM deterministiktir (ADR-015): aynı girdi → aynı +çıktı → aynı çalışma. "Sadelik" diye tasarlanan bu kararlar aslında bir +**yetenek-güvenliği (capability sandbox)** kurar — güvenilmeyen veya +AI-üretimi kodu güvenle çalıştırmak için biçilmiş kaftan. + +**Bu ikisinin ödülü — kayıt & tekrar (record-replay).** 🚧 *(vizyon, v0 değil; +bkz. issue #94.)* Belirsizliğin tek kaynağı (kullanıcı girdisi, zaman, IO, +GC/thread kararları) FFI kapısından geçtiği için, mükemmel tekrar oynatma için +**her değişkeni her adımda kaydetmek gerekmez** — yalnızca kapıdan geçen değerler +kaydedilir, gerisi VM deterministik olarak yeniden çalıştırılarak üretilir. Boyut +gigabayttan kilobayta düşer. Replay modunda FFI çağrıları gerçekten çalışmaz, +kaydedilmiş değeri döndürür (dosyayı tekrar silmez, sunucuya tekrar istek atmaz). +Böylece "benim makinemde çalışıyor, müşteride patlıyor" sorunu: müşteri bir dump +yollar, sen çöküşü adım adım, aynı verilerle geri sararsın. + +> Log, önceden sormayı akıl ettiğin sorulara cevap verir; **tekrar-oynatma, +> çöküşten *sonra* aklına gelen sorulara.** Zaman-yolculuğu hata ayıklama ayrı +> bir altyapı değildir — cam sorgularına bir **zaman koordinatı** eklemektir. + +⚠️ Bu ödülün bedeli v0'da ödenir: **determinizm kutsaldır ve her belirsizlik +kaynağı kayıt-altına-alınabilir tek kapıdan geçmelidir.** Sonradan eklenemez; +baştan korunur. + +--- + ## Mimari hatlar ``` From 63ad3e2dcf6342e6d0ae324be949075edfb7716c Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Tue, 16 Jun 2026 00:22:47 +0300 Subject: [PATCH 08/28] =?UTF-8?q?chore:=20scripts/gitea.py'yi=20gitignore'?= =?UTF-8?q?la=20(parola=20s=C4=B1z=C4=B1nt=C4=B1s=C4=B1n=C4=B1=20=C3=B6nle?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Yerel API istemcisi kimlik bilgisini ~/.git-credentials'tan okur; asla commit edilmemeli. Co-Authored-By: Claude Opus 4.8 --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 6d074f8..d7a80e4 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ saqut *.swp *.swo *~ + +# Parola içerebilen yerel API istemcisi - asla commit edilmez +scripts/gitea.py From f3358473ac2899a1aaa7221094eb8b5e2e5e6aaf Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Tue, 16 Jun 2026 00:31:44 +0300 Subject: [PATCH 09/28] =?UTF-8?q?feat(faz0):=20tip=20sistemi=20+=20tan?= =?UTF-8?q?=C4=B1lama=20motoru=20(Type=20+=20DiagnosticEngine)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Faz 0 (#69) — frontend'in iki temel veri yapısı: - src/core/type.hpp: Type (Primitive/Array/Struct/Function/Error), equals() (katı yapısal, gizli dönüşüm yok — ADR-010), toString(), toJson() (cam ilkesi), factory'ler ve fromName() yardımcısı. - src/diagnostic/diagnostic.hpp: DiagLevel, Diagnostic (veri birincil), hata kataloğu (E001-E010, W001-W003) + jsonEscape + makeDiagnostic. - src/diagnostic/diagnostic_engine.hpp: toplar (ilk hatada durmaz, ADR-013), printAll() (insan-okur, sıralı) + toJson() (makine-okur). - tests/: çerçevesiz birim testleri + run.sh. Header-only (ADR-003). -Wall -Wextra temiz. Henüz pipeline'a bağlı değil; Faz 2/3 (sembol tablosu, tip denetleyici) bunları tüketecek. Co-Authored-By: Claude Opus 4.8 --- src/core/type.hpp | 250 +++++++++++++++++++++++++++ src/diagnostic/diagnostic.hpp | 178 +++++++++++++++++++ src/diagnostic/diagnostic_engine.hpp | 114 ++++++++++++ tests/run.sh | 16 ++ tests/test_diagnostic.cpp | 43 +++++ tests/test_type.cpp | 49 ++++++ 6 files changed, 650 insertions(+) create mode 100644 src/core/type.hpp create mode 100644 src/diagnostic/diagnostic.hpp create mode 100644 src/diagnostic/diagnostic_engine.hpp create mode 100755 tests/run.sh create mode 100644 tests/test_diagnostic.cpp create mode 100644 tests/test_type.cpp diff --git a/src/core/type.hpp b/src/core/type.hpp new file mode 100644 index 0000000..260a129 --- /dev/null +++ b/src/core/type.hpp @@ -0,0 +1,250 @@ +// ============================================================================ +// saQut Compiler — Tip Sistemi (Type System) +// ============================================================================ +// +// DİZİN: src/core/type.hpp +// KATMAN: Katman 0 — Tüm analiz katmanları tarafından kullanılır +// BAĞIMLI: Yok (sadece , , ) +// KULLANAN: Sembol tablosu (Faz 2), tip denetleyici (Faz 3), optimizasyon (Faz 4) +// +// AMAÇ: +// Kaynak koddaki her ifadenin/sembolün veri tipini temsil eder. Derleyicinin +// "bu değer ne?" sorusuna verdiği yapısal cevaptır. Tip, makine-okur (toJson) +// ve insan-okur (toString) olarak dışa açıktır — "veri birincil, metin bir +// görünümdür" ilkesine uyar (bkz. readme → Tasarım felsefesi). +// +// TİP TÜRLERİ (TypeKind): +// Primitive : int, float, double, char, string, bool, void +// Array : eleman tipi taşır (örn. int[]) +// Struct : struct adı taşır (örn. struct Point) +// Function : dönüş tipi + parametre tipleri taşır +// Error : hatalı/çözümlenememiş tip — ardışık sahte hataları bastırmak için +// (tip denetleyici, operandı Error olan ifadede yeni hata üretmez) +// +// NOT (kasıtlı sadelik): Gizli tip dönüşümü YOKTUR (ADR-010). equals() yapısal +// ve katıdır; "int, float'a uyar mı?" gibi kurallar tip denetleyicinin işidir, +// bu dosyanın değil. Tamsayı literalinin bağlama-göre tiplenmesi de (ADR-010) +// Faz 3'te ele alınır. +// +// ============================================================================ + +#ifndef SAQUT_CORE_TYPE +#define SAQUT_CORE_TYPE + +#include +#include +#include + +// ============================================================================ +// Enum'lar +// ============================================================================ + +enum class PrimitiveKind { Int, Float, Double, Char, String, Bool, Void }; + +enum class TypeKind { Primitive, Array, Struct, Function, Error }; + +// ============================================================================ +// Type — Bir veri tipi +// ============================================================================ +// +// KULLANIM: +// Type a = Type::Int(); // int +// Type b = Type::array(Type::Int()); // int[] +// Type c = Type::function(Type::Int(), {Type::Int(), Type::Int()}); // fn(int,int)->int +// Type d = Type::structType("Point"); // struct Point +// Type e = Type::error(); // +// +// a.equals(Type::Int()); // true +// a.equals(b); // false +// a.toString(); // "int" +// b.toString(); // "int[]" +// c.toJson(); // {"kind":"function",...} +// +// İç içe tipler (array elemanı, fonksiyon dönüşü) shared_ptr ile tutulur: +// Type değer-semantiğiyle kopyalanabilir kalır ama özyinelemeli olabilir. +// ============================================================================ + +struct Type { + TypeKind kind = TypeKind::Error; + + PrimitiveKind prim = PrimitiveKind::Void; // kind == Primitive + std::shared_ptr elementType; // kind == Array + std::shared_ptr returnType; // kind == Function + std::vector paramTypes; // kind == Function + std::string structName; // kind == Struct + + // ------------------------------------------------------------------ // + // Factory'ler + // ------------------------------------------------------------------ // + static Type primitive(PrimitiveKind p) { + Type t; + t.kind = TypeKind::Primitive; + t.prim = p; + return t; + } + static Type Int() { return primitive(PrimitiveKind::Int); } + static Type Float() { return primitive(PrimitiveKind::Float); } + static Type Double() { return primitive(PrimitiveKind::Double); } + static Type Char() { return primitive(PrimitiveKind::Char); } + static Type String() { return primitive(PrimitiveKind::String); } + static Type Bool() { return primitive(PrimitiveKind::Bool); } + static Type Void() { return primitive(PrimitiveKind::Void); } + + static Type array(Type elem) { + Type t; + t.kind = TypeKind::Array; + t.elementType = std::make_shared(std::move(elem)); + return t; + } + static Type function(Type ret, std::vector params) { + Type t; + t.kind = TypeKind::Function; + t.returnType = std::make_shared(std::move(ret)); + t.paramTypes = std::move(params); + return t; + } + static Type structType(std::string name) { + Type t; + t.kind = TypeKind::Struct; + t.structName = std::move(name); + return t; + } + static Type error() { + return Type{}; // varsayılan = Error + } + + // ------------------------------------------------------------------ // + // Yüklemler (predicates) + // ------------------------------------------------------------------ // + bool isError() const { return kind == TypeKind::Error; } + bool isPrimitive() const { return kind == TypeKind::Primitive; } + bool isArray() const { return kind == TypeKind::Array; } + bool isStruct() const { return kind == TypeKind::Struct; } + bool isFunction() const { return kind == TypeKind::Function; } + bool isVoid() const { return kind == TypeKind::Primitive && prim == PrimitiveKind::Void; } + + // Aritmetik/karşılaştırma operatörlerine uygun sayısal tip mi? + bool isNumeric() const { + return kind == TypeKind::Primitive && + (prim == PrimitiveKind::Int || + prim == PrimitiveKind::Float || + prim == PrimitiveKind::Double); + } + + // ------------------------------------------------------------------ // + // equals — Yapısal eşitlik (katı; gizli dönüşüm yok, ADR-010) + // ------------------------------------------------------------------ // + bool equals(const Type& o) const { + if (kind != o.kind) return false; + switch (kind) { + case TypeKind::Primitive: + return prim == o.prim; + case TypeKind::Array: + return elementType && o.elementType && + elementType->equals(*o.elementType); + case TypeKind::Struct: + return structName == o.structName; + case TypeKind::Function: { + if (!returnType || !o.returnType) return false; + if (!returnType->equals(*o.returnType)) return false; + if (paramTypes.size() != o.paramTypes.size()) return false; + for (size_t i = 0; i < paramTypes.size(); ++i) + if (!paramTypes[i].equals(o.paramTypes[i])) return false; + return true; + } + case TypeKind::Error: + // Error == Error: ardışık sahte hataların bastırılması tip + // denetleyicinin sorumluluğundadır (operandı Error ise hata üretme). + return true; + } + return false; // erişilemez (tüm enum değerleri kapsandı) + } + + // ------------------------------------------------------------------ // + // İsim yardımcıları + // ------------------------------------------------------------------ // + static const char* primName(PrimitiveKind p) { + switch (p) { + case PrimitiveKind::Int: return "int"; + case PrimitiveKind::Float: return "float"; + case PrimitiveKind::Double: return "double"; + case PrimitiveKind::Char: return "char"; + case PrimitiveKind::String: return "string"; + case PrimitiveKind::Bool: return "bool"; + case PrimitiveKind::Void: return "void"; + } + return "?"; + } + + // Bir tip adından (parser tipleri string olarak tutar) primitif Type üretir. + // Bilinen primitif değilse Error döner — bilinmeyen tip adının teşhisi + // (E007) çağıranın (Faz 2/3) işidir; bu fonksiyon sessizce Error verir. + static Type fromName(const std::string& n) { + if (n == "int") return Int(); + if (n == "float") return Float(); + if (n == "double") return Double(); + if (n == "char") return Char(); + if (n == "string") return String(); + if (n == "bool") return Bool(); + if (n == "void") return Void(); + return error(); + } + + // ------------------------------------------------------------------ // + // toString — İnsan-okur ("int", "int[]", "fn(int,int)->int") + // ------------------------------------------------------------------ // + std::string toString() const { + switch (kind) { + case TypeKind::Primitive: + return primName(prim); + case TypeKind::Array: + return (elementType ? elementType->toString() : "") + "[]"; + case TypeKind::Struct: + return "struct " + structName; + case TypeKind::Function: { + std::string s = "fn("; + for (size_t i = 0; i < paramTypes.size(); ++i) { + if (i) s += ","; + s += paramTypes[i].toString(); + } + s += ")->"; + s += returnType ? returnType->toString() : ""; + return s; + } + case TypeKind::Error: + return ""; + } + return ""; + } + + // ------------------------------------------------------------------ // + // toJson — Makine-okur (cam ilkesi: her tip dışarıdan sorgulanabilir) + // ------------------------------------------------------------------ // + std::string toJson() const { + switch (kind) { + case TypeKind::Primitive: + return std::string("{\"kind\":\"primitive\",\"name\":\"") + primName(prim) + "\"}"; + case TypeKind::Array: + return std::string("{\"kind\":\"array\",\"element\":") + + (elementType ? elementType->toJson() : "null") + "}"; + case TypeKind::Struct: + return "{\"kind\":\"struct\",\"name\":\"" + structName + "\"}"; + case TypeKind::Function: { + std::string s = "{\"kind\":\"function\",\"returns\":"; + s += returnType ? returnType->toJson() : "null"; + s += ",\"params\":["; + for (size_t i = 0; i < paramTypes.size(); ++i) { + if (i) s += ","; + s += paramTypes[i].toJson(); + } + s += "]}"; + return s; + } + case TypeKind::Error: + return "{\"kind\":\"error\"}"; + } + return "null"; + } +}; + +#endif // SAQUT_CORE_TYPE diff --git a/src/diagnostic/diagnostic.hpp b/src/diagnostic/diagnostic.hpp new file mode 100644 index 0000000..43e296b --- /dev/null +++ b/src/diagnostic/diagnostic.hpp @@ -0,0 +1,178 @@ +// ============================================================================ +// 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 diff --git a/src/diagnostic/diagnostic_engine.hpp b/src/diagnostic/diagnostic_engine.hpp new file mode 100644 index 0000000..baa7a10 --- /dev/null +++ b/src/diagnostic/diagnostic_engine.hpp @@ -0,0 +1,114 @@ +// ============================================================================ +// saQut Compiler — Tanılama Motoru (DiagnosticEngine) +// ============================================================================ +// +// DİZİN: src/diagnostic/diagnostic_engine.hpp +// KATMAN: Katman 0 — Tüm analiz katmanları tarafından kullanılır +// BAĞIMLI: src/diagnostic/diagnostic.hpp +// KULLANAN: sembol toplayıcı (Faz 2), tip denetleyici (Faz 3), pipeline (main) +// +// AMAÇ: +// Derleme boyunca üretilen tüm Diagnostic'leri EKLENME SIRASIYLA biriktirir. +// İlk hatada DURMAZ (ADR-013): bütün hatalar toplanır, faz sonunda topluca +// raporlanır; durdurma kararını pipeline verir (hasErrors()). +// +// İki çıktı yüzü vardır — aynı veriden: +// printAll() → insan-okur (terminal) +// toJson() → makine-okur (LSP / AI / araçlar) +// +// ============================================================================ + +#ifndef SAQUT_DIAGNOSTIC_ENGINE +#define SAQUT_DIAGNOSTIC_ENGINE + +#include +#include +#include +#include "diagnostic/diagnostic.hpp" + +// ============================================================================ +// DiagnosticEngine +// ============================================================================ +// +// KULLANIM: +// DiagnosticEngine diag; +// diag.report(makeDiagnostic("E001", loc, "x tanımsız")); +// diag.report(DiagLevel::Warning, "W001", loc2, "y kullanılmıyor"); +// if (diag.hasErrors()) diag.printAll(std::cerr); +// ============================================================================ + +class DiagnosticEngine { +public: + // --- Ekleme --- + void report(const Diagnostic& d) { + diagnostics_.push_back(d); + } + + // Kolaylık: koddan üret + ekle (seviye kataloğdan çözülür) + void report(const std::string& code, + const SourceLocation& loc, + const std::string& message, + const std::string& hint = "") { + diagnostics_.push_back(makeDiagnostic(code, loc, message, hint)); + } + + // Kolaylık: seviyeyi açıkça vererek + void report(DiagLevel level, + const std::string& code, + const SourceLocation& loc, + const std::string& message, + const std::string& hint = "") { + Diagnostic d; + d.level = level; d.code = code; d.loc = loc; d.message = message; d.hint = hint; + diagnostics_.push_back(d); + } + + // --- Sorgu --- + bool hasErrors() const { return errorCount() > 0; } + + int errorCount() const { return countLevel(DiagLevel::Error); } + int warningCount() const { return countLevel(DiagLevel::Warning); } + int count() const { return static_cast(diagnostics_.size()); } + bool empty() const { return diagnostics_.empty(); } + + const std::vector& all() const { return diagnostics_; } + + void clear() { diagnostics_.clear(); } + + // --- İnsan-okur çıktı (ekleme sırasıyla) --- + void printAll(std::ostream& os) const { + for (const auto& d : diagnostics_) { + os << d.loc.toString() << ": " + << diagLevelNameTr(d.level) << " [" << d.code << "]: " + << d.message << "\n"; + if (!d.hint.empty()) + os << " ipucu: " << d.hint << "\n"; + } + os << "— " << errorCount() << " hata, " << warningCount() << " uyarı\n"; + } + + // --- Makine-okur çıktı --- + std::string toJson() const { + std::string s = "{\"diagnostics\":["; + for (size_t i = 0; i < diagnostics_.size(); ++i) { + if (i) s += ","; + s += diagnostics_[i].toJson(); + } + s += "],\"errorCount\":" + std::to_string(errorCount()); + s += ",\"warningCount\":" + std::to_string(warningCount()); + s += "}"; + return s; + } + +private: + std::vector diagnostics_; + + int countLevel(DiagLevel level) const { + int n = 0; + for (const auto& d : diagnostics_) + if (d.level == level) ++n; + return n; + } +}; + +#endif // SAQUT_DIAGNOSTIC_ENGINE diff --git a/tests/run.sh b/tests/run.sh new file mode 100755 index 0000000..f694d23 --- /dev/null +++ b/tests/run.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# saQut birim testleri — çerçevesiz (assert tabanlı), tek komutla. +# Kullanım: bash tests/run.sh +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +CXX="${CXX:-g++}" +FLAGS=(-std=c++20 -Wall -Wextra -I"$ROOT/src") + +for t in test_type test_diagnostic; do + echo "=== $t ===" + "$CXX" "${FLAGS[@]}" "$ROOT/tests/$t.cpp" -o "/tmp/saqut_$t" + "/tmp/saqut_$t" +done + +echo "=== TUM TESTLER GECTI ===" diff --git a/tests/test_diagnostic.cpp b/tests/test_diagnostic.cpp new file mode 100644 index 0000000..dcb28c0 --- /dev/null +++ b/tests/test_diagnostic.cpp @@ -0,0 +1,43 @@ +// Faz 0 — DiagnosticEngine birim testleri (çerçevesiz; assert + çıktı). +// Koşmak için: tests/run.sh +#include "diagnostic/diagnostic_engine.hpp" +#include +#include + +int main() { + DiagnosticEngine diag; + SourceLocation l1{"test.sqt", 3, 5, 40}; + SourceLocation l2{"test.sqt", 7, 9, 88}; + SourceLocation l3{"test.sqt", 12, 1, 150}; + + // Üç tanı — ekleme sırası korunmalı (ADR-013: ilk hatada durma, topla) + diag.report("E001", l1, "x tanımsız"); + diag.report("E003", l2, "int'e string atanamaz", "açık dönüşüm gerekiyor"); + diag.report("W001", l3, "y kullanılmıyor"); + + assert(diag.count() == 3); + assert(diag.hasErrors()); + assert(diag.errorCount() == 2); + assert(diag.warningCount() == 1); + + // Sıra korunmuş mu? + assert(diag.all()[0].code == "E001"); + assert(diag.all()[1].code == "E003"); + assert(diag.all()[2].code == "W001"); + + // Seviye kataloğdan çözülmüş mü? + assert(diag.all()[0].level == DiagLevel::Error); + assert(diag.all()[2].level == DiagLevel::Warning); + + // Katalog erişimi + assert(findDiag("E010") != nullptr); + assert(findDiag("E999") == nullptr); + + std::cout << "--- printAll ---\n"; + diag.printAll(std::cout); + std::cout << "--- toJson ---\n"; + std::cout << diag.toJson() << "\n"; + + std::cout << "test_diagnostic: TUM TESTLER GECTI\n"; + return 0; +} diff --git a/tests/test_type.cpp b/tests/test_type.cpp new file mode 100644 index 0000000..fcbf805 --- /dev/null +++ b/tests/test_type.cpp @@ -0,0 +1,49 @@ +// Faz 0 — Type birim testleri (çerçevesiz; assert + çıktı). +// Koşmak için: tests/run.sh (veya g++ -std=c++20 -Wall -Wextra -Isrc ...) +#include "core/type.hpp" +#include +#include + +int main() { + Type i = Type::Int(); + Type i2 = Type::Int(); + Type f = Type::Float(); + Type arrI = Type::array(Type::Int()); + Type arrI2 = Type::array(Type::Int()); + Type arrF = Type::array(Type::Float()); + Type fn = Type::function(Type::Int(), {Type::Int(), Type::Int()}); + Type st = Type::structType("Point"); + Type err = Type::error(); + + // equals — yapısal, katı (gizli dönüşüm yok) + assert(i.equals(i2)); + assert(!i.equals(f)); + assert(arrI.equals(arrI2)); + assert(!arrI.equals(arrF)); + assert(!arrI.equals(i)); + assert(fn.equals(Type::function(Type::Int(), {Type::Int(), Type::Int()}))); + assert(!fn.equals(Type::function(Type::Int(), {Type::Int()}))); + assert(st.equals(Type::structType("Point"))); + assert(!st.equals(Type::structType("Vec"))); + assert(err.equals(Type::error())); + + // yüklemler + assert(i.isNumeric() && !st.isNumeric()); + assert(Type::Void().isVoid()); + assert(err.isError()); + + // toString + assert(i.toString() == "int"); + assert(arrI.toString() == "int[]"); + assert(fn.toString() == "fn(int,int)->int"); + assert(st.toString() == "struct Point"); + assert(err.toString() == ""); + + // fromName + assert(Type::fromName("int").equals(Type::Int())); + assert(Type::fromName("bool").equals(Type::Bool())); + assert(Type::fromName("bogus").isError()); + + std::cout << "test_type: TUM TESTLER GECTI\n"; + return 0; +} From 6b5a67343b9db37b8b1af5748d542082062b1ba1 Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Tue, 16 Jun 2026 00:32:29 +0300 Subject: [PATCH 10/28] chore: __pycache__ gitignore Co-Authored-By: Claude Opus 4.8 --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index d7a80e4..ea8e157 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ saqut # Parola içerebilen yerel API istemcisi - asla commit edilmez scripts/gitea.py + +# Python bytecode cache +__pycache__/ From ea5bcee4908371f46c88eb50306596721838b901 Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Tue, 16 Jun 2026 00:47:50 +0300 Subject: [PATCH 11/28] =?UTF-8?q?feat(faz1):=20AST'i=20Expression/Statemen?= =?UTF-8?q?t=20olarak=20ay=C4=B1r=20+=20analiz=20alanlar=C4=B1=20(#70)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ast_node.hpp: ExpressionNode (resolvedType + isConstant/foldedValue TODO) ve StatementNode (isReachable) ara taban sınıfları; core/type.hpp dahil. - İfade düğümleri (Literal, Identifier, Binary, Postfix, Call, Member, Index) → ExpressionNode; toJson'a resolvedType (çözülmemişse null). - Deyim düğümleri (Block/If/While/For/DoWhile/Return/Break/Continue/ ExpressionStatement + VariableDecl) → StatementNode; toJson'a isReachable. - IdentifierNode'a Symbol* resolvedSymbol (TODO faz-2, ileri bildirim). - Faz 0 düzeltmesi: diagnostic.hpp kendi jsonEscape'ini kaldırdı, tools.hpp' dekini kullanıyor (ODR çakışması önlendi). Doğrulama: -Wall -Wextra temiz; saqut ast fibonacci.sqt geçerli JSON (48 resolvedType:null, 20 isReachable:true); parser-stress regresyon temiz; Faz 0 birim testleri geçiyor. Co-Authored-By: Claude Opus 4.8 --- src/diagnostic/diagnostic.hpp | 18 ++----------- src/parser/ast_node.hpp | 42 +++++++++++++++++++++++++++++++ src/parser/nodes/binary_expr.cpp | 1 + src/parser/nodes/binary_expr.hpp | 2 +- src/parser/nodes/declarations.cpp | 1 + src/parser/nodes/declarations.hpp | 2 +- src/parser/nodes/expressions.cpp | 4 +++ src/parser/nodes/expressions.hpp | 8 +++--- src/parser/nodes/identifier.cpp | 1 + src/parser/nodes/identifier.hpp | 7 +++++- src/parser/nodes/literal.cpp | 1 + src/parser/nodes/literal.hpp | 2 +- src/parser/nodes/statements.cpp | 9 +++++++ src/parser/nodes/statements.hpp | 18 ++++++------- 14 files changed, 83 insertions(+), 33 deletions(-) diff --git a/src/diagnostic/diagnostic.hpp b/src/diagnostic/diagnostic.hpp index 43e296b..c9e3e9a 100644 --- a/src/diagnostic/diagnostic.hpp +++ b/src/diagnostic/diagnostic.hpp @@ -37,6 +37,7 @@ #include #include #include "core/location.hpp" +#include "tools.hpp" // jsonEscape — TEK tanım (tools.hpp); çakışmayı önler // ============================================================================ // DiagLevel — Tanı seviyesi @@ -65,22 +66,7 @@ inline const char* diagLevelNameTr(DiagLevel l) { 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; -} +// NOT: jsonEscape() tools.hpp'de tanımlıdır (tek tanım — ODR çakışması olmaz). // ============================================================================ // Diagnostic — Tek bir tanı (hata/uyarı/not/ipucu) diff --git a/src/parser/ast_node.hpp b/src/parser/ast_node.hpp index 3739c70..d41053a 100644 --- a/src/parser/ast_node.hpp +++ b/src/parser/ast_node.hpp @@ -31,6 +31,7 @@ #include #include #include "core/location.hpp" +#include "core/type.hpp" #include "parser/token.hpp" #include "tools.hpp" @@ -247,6 +248,47 @@ protected: std::vector children; }; +// ============================================================================ +// ExpressionNode — Değer Üreten Düğümlerin Tabanı (Faz 1, ADR-012) +// ============================================================================ +// +// Bir DEĞER üreten her düğüm (Literal, Identifier, BinaryExpression, Call, +// Postfix, MemberAccess, IndexExpression) buradan türer. Bir ifadenin bir +// TİPİ vardır; analiz/optimizasyon alanları burada toplanır. +// +class ExpressionNode : public ASTNode { +public: + // TODO(faz-3): tip denetleyici doldurur. Şimdilik Error = "henüz çözülmedi". + Type resolvedType; + + // TODO(faz-4): sabit katlama (constant folding) bayrağı. + bool isConstant = false; + // TODO(faz-4): foldedValue — katlanmış sabit değer (temsil Faz 4'te netleşir). + + // resolvedType'ın JSON karşılığı (henüz çözülmemişse null gösterilir). + std::string resolvedTypeJson() const { + return resolvedType.isError() ? std::string("null") : resolvedType.toJson(); + } +}; + +// ============================================================================ +// StatementNode — Eylem/Kontrol Akışı Yürüten Düğümlerin Tabanı (Faz 1) +// ============================================================================ +// +// Değer üretmeyen, bir iş/kontrol akışı yürüten her düğüm (Block, If, For, +// While, DoWhile, Return, Break, Continue, ExpressionStatement ve şimdilik +// VariableDecl) buradan türer. Tipi yoktur; akış-analizi alanları taşır. +// +// TODO(faz-1 gözden geçirme): VariableDecl/FunctionDecl/StructDecl'in tam +// sınıflandırması provizyonel — VariableDecl burada (blok içinde erişilebilirliğe +// tabi), Function/StructDecl doğrudan ASTNode altında kaldı. +// +class StatementNode : public ASTNode { +public: + // TODO(faz-3/4): erişilebilirlik (dead-code) analizi günceller. + bool isReachable = true; +}; + // ============================================================================ // childrenToJson — Düğümün çocuklarını JSON array olarak yaz // ============================================================================ diff --git a/src/parser/nodes/binary_expr.cpp b/src/parser/nodes/binary_expr.cpp index d15731b..fc3daa9 100644 --- a/src/parser/nodes/binary_expr.cpp +++ b/src/parser/nodes/binary_expr.cpp @@ -18,6 +18,7 @@ std::string BinaryExpressionNode::toJson(int depth) { obj.add("operator", std::string(OPERATOR_MAP_REV.count(Operator) ? OPERATOR_MAP_REV.at(Operator) : "?")); if (Left) obj.addRaw("left", Left->toJson(depth + 1)); if (Right) obj.addRaw("right", Right->toJson(depth + 1)); + obj.addRaw("resolvedType", resolvedTypeJson()); obj.addRaw("location", loc.toJson()); return obj.str(); } diff --git a/src/parser/nodes/binary_expr.hpp b/src/parser/nodes/binary_expr.hpp index c760937..b67ee35 100644 --- a/src/parser/nodes/binary_expr.hpp +++ b/src/parser/nodes/binary_expr.hpp @@ -3,7 +3,7 @@ #include "parser/ast_node.hpp" -class BinaryExpressionNode : public ASTNode { +class BinaryExpressionNode : public ExpressionNode { public: TokenType Operator; ASTNode* Left = nullptr; diff --git a/src/parser/nodes/declarations.cpp b/src/parser/nodes/declarations.cpp index 4edc7d2..e4357fb 100644 --- a/src/parser/nodes/declarations.cpp +++ b/src/parser/nodes/declarations.cpp @@ -30,6 +30,7 @@ std::string VariableDeclNode::toJson(int depth) { obj.add("kind", "VariableDecl"); obj.add("name", name); obj.add("varType", varType); + obj.add("isReachable", isReachable); if (initExpr) obj.addRaw("init", initExpr->toJson(depth + 1)); obj.addRaw("location", loc.toJson()); return obj.str(); diff --git a/src/parser/nodes/declarations.hpp b/src/parser/nodes/declarations.hpp index 2638eda..20bf751 100644 --- a/src/parser/nodes/declarations.hpp +++ b/src/parser/nodes/declarations.hpp @@ -12,7 +12,7 @@ public: std::string toJson(int depth = 0) override; }; -class VariableDeclNode : public ASTNode { +class VariableDeclNode : public StatementNode { public: std::string varType; std::string name; diff --git a/src/parser/nodes/expressions.cpp b/src/parser/nodes/expressions.cpp index 5cab82a..9c68517 100644 --- a/src/parser/nodes/expressions.cpp +++ b/src/parser/nodes/expressions.cpp @@ -12,6 +12,7 @@ std::string PostfixNode::toJson(int depth) { obj.add("kind", "Postfix"); obj.add("operator", std::string(OPERATOR_MAP_REV.count(Operator) ? OPERATOR_MAP_REV.at(Operator) : "?")); if (operand) obj.addRaw("operand", operand->toJson(depth + 1)); + obj.addRaw("resolvedType", resolvedTypeJson()); obj.addRaw("location", loc.toJson()); return obj.str(); } @@ -30,6 +31,7 @@ std::string CallExpressionNode::toJson(int depth) { obj.addArray("arguments", [&]() { for (auto* arg : arguments) obj.addItem(arg->toJson(depth + 2)); }); + obj.addRaw("resolvedType", resolvedTypeJson()); obj.addRaw("location", loc.toJson()); return obj.str(); } @@ -46,6 +48,7 @@ std::string MemberAccessNode::toJson(int depth) { obj.add("member", member); obj.add("arrow", arrow); if (object) obj.addRaw("object", object->toJson(depth + 1)); + obj.addRaw("resolvedType", resolvedTypeJson()); obj.addRaw("location", loc.toJson()); return obj.str(); } @@ -62,6 +65,7 @@ std::string IndexExpressionNode::toJson(int depth) { obj.add("kind", "IndexExpression"); if (object) obj.addRaw("object", object->toJson(depth + 1)); if (index) obj.addRaw("index", index->toJson(depth + 1)); + obj.addRaw("resolvedType", resolvedTypeJson()); obj.addRaw("location", loc.toJson()); return obj.str(); } diff --git a/src/parser/nodes/expressions.hpp b/src/parser/nodes/expressions.hpp index 0efae4f..731a6a3 100644 --- a/src/parser/nodes/expressions.hpp +++ b/src/parser/nodes/expressions.hpp @@ -3,7 +3,7 @@ #include "parser/ast_node.hpp" -class PostfixNode : public ASTNode { +class PostfixNode : public ExpressionNode { public: ASTNode* operand = nullptr; TokenType Operator; @@ -12,7 +12,7 @@ public: std::string toJson(int depth = 0) override; }; -class CallExpressionNode : public ASTNode { +class CallExpressionNode : public ExpressionNode { public: ASTNode* callee = nullptr; std::vector arguments; @@ -21,7 +21,7 @@ public: std::string toJson(int depth = 0) override; }; -class MemberAccessNode : public ASTNode { +class MemberAccessNode : public ExpressionNode { public: ASTNode* object = nullptr; std::string member; @@ -31,7 +31,7 @@ public: std::string toJson(int depth = 0) override; }; -class IndexExpressionNode : public ASTNode { +class IndexExpressionNode : public ExpressionNode { public: ASTNode* object = nullptr; ASTNode* index = nullptr; diff --git a/src/parser/nodes/identifier.cpp b/src/parser/nodes/identifier.cpp index 55e3df4..f2286de 100644 --- a/src/parser/nodes/identifier.cpp +++ b/src/parser/nodes/identifier.cpp @@ -17,6 +17,7 @@ std::string IdentifierNode::toJson(int depth) { ss << "{\n" << in << " \"kind\": \"Identifier\",\n" << in << " \"name\": \"" << jsonEscape(name) << "\",\n" + << in << " \"resolvedType\": " << resolvedTypeJson() << ",\n" << in << " \"location\": " << loc.toJson() << "\n" << in << "}"; return ss.str(); diff --git a/src/parser/nodes/identifier.hpp b/src/parser/nodes/identifier.hpp index f993096..4d4b80d 100644 --- a/src/parser/nodes/identifier.hpp +++ b/src/parser/nodes/identifier.hpp @@ -3,11 +3,16 @@ #include "parser/ast_node.hpp" -class IdentifierNode : public ASTNode { +struct Symbol; // TODO(faz-2): sembol tablosu (Symbol) tanımlandığında bağlanacak + +class IdentifierNode : public ExpressionNode { public: Token* lexerToken = nullptr; ParserToken parserToken; + // TODO(faz-2): isim çözümlemede sembol tablosundaki tanıma bağlanır. + Symbol* resolvedSymbol = nullptr; + IdentifierNode(); void log(int indent = 0) override; std::string toJson(int depth = 0) override; diff --git a/src/parser/nodes/literal.cpp b/src/parser/nodes/literal.cpp index 94e32b8..1cd578f 100644 --- a/src/parser/nodes/literal.cpp +++ b/src/parser/nodes/literal.cpp @@ -28,6 +28,7 @@ std::string LiteralNode::toJson(int depth) { if (literalType == LiteralType::FLOAT) { ss << ",\n" << in << " \"isFloat\": true"; } + ss << ",\n" << in << " \"resolvedType\": " << resolvedTypeJson(); ss << ",\n" << in << " \"location\": " << loc.toJson() << "\n" << in << "}"; return ss.str(); diff --git a/src/parser/nodes/literal.hpp b/src/parser/nodes/literal.hpp index 850dc5a..dee1207 100644 --- a/src/parser/nodes/literal.hpp +++ b/src/parser/nodes/literal.hpp @@ -3,7 +3,7 @@ #include "parser/ast_node.hpp" -class LiteralNode : public ASTNode { +class LiteralNode : public ExpressionNode { public: Token* lexerToken = nullptr; ParserToken parserToken; diff --git a/src/parser/nodes/statements.cpp b/src/parser/nodes/statements.cpp index 99e2038..a395bbe 100644 --- a/src/parser/nodes/statements.cpp +++ b/src/parser/nodes/statements.cpp @@ -13,6 +13,7 @@ std::string BlockNode::toJson(int depth) { obj.addArray("children", [&]() { for (auto* child : children) obj.addItem(child->toJson(depth + 2)); }); + obj.add("isReachable", isReachable); obj.addRaw("location", loc.toJson()); return obj.str(); } @@ -31,6 +32,7 @@ std::string IfStatementNode::toJson(int depth) { if (condition) obj.addRaw("condition", condition->toJson(depth + 1)); if (thenBranch) obj.addRaw("then", thenBranch->toJson(depth + 1)); if (elseBranch) obj.addRaw("else", elseBranch->toJson(depth + 1)); + obj.add("isReachable", isReachable); obj.addRaw("location", loc.toJson()); return obj.str(); } @@ -47,6 +49,7 @@ std::string WhileStatementNode::toJson(int depth) { obj.add("kind", "WhileStatement"); if (condition) obj.addRaw("condition", condition->toJson(depth + 1)); if (body) obj.addRaw("body", body->toJson(depth + 1)); + obj.add("isReachable", isReachable); obj.addRaw("location", loc.toJson()); return obj.str(); } @@ -67,6 +70,7 @@ std::string ForStatementNode::toJson(int depth) { if (condition) obj.addRaw("condition", condition->toJson(depth + 1)); if (update) obj.addRaw("update", update->toJson(depth + 1)); if (body) obj.addRaw("body", body->toJson(depth + 1)); + obj.add("isReachable", isReachable); obj.addRaw("location", loc.toJson()); return obj.str(); } @@ -83,6 +87,7 @@ std::string DoWhileStatementNode::toJson(int depth) { obj.add("kind", "DoWhileStatement"); if (condition) obj.addRaw("condition", condition->toJson(depth + 1)); if (body) obj.addRaw("body", body->toJson(depth + 1)); + obj.add("isReachable", isReachable); obj.addRaw("location", loc.toJson()); return obj.str(); } @@ -97,6 +102,7 @@ std::string ReturnStatementNode::toJson(int depth) { JsonObject obj(depth); obj.add("kind", "ReturnStatement"); if (value) obj.addRaw("value", value->toJson(depth + 1)); + obj.add("isReachable", isReachable); obj.addRaw("location", loc.toJson()); return obj.str(); } @@ -109,6 +115,7 @@ void BreakStatementNode::log(int indent) { std::string BreakStatementNode::toJson(int depth) { JsonObject obj(depth); obj.add("kind", "BreakStatement"); + obj.add("isReachable", isReachable); obj.addRaw("location", loc.toJson()); return obj.str(); } @@ -121,6 +128,7 @@ void ContinueStatementNode::log(int indent) { std::string ContinueStatementNode::toJson(int depth) { JsonObject obj(depth); obj.add("kind", "ContinueStatement"); + obj.add("isReachable", isReachable); obj.addRaw("location", loc.toJson()); return obj.str(); } @@ -135,6 +143,7 @@ std::string ExpressionStatementNode::toJson(int depth) { JsonObject obj(depth); obj.add("kind", "ExpressionStatement"); if (expression) obj.addRaw("expression", expression->toJson(depth + 1)); + obj.add("isReachable", isReachable); obj.addRaw("location", loc.toJson()); return obj.str(); } diff --git a/src/parser/nodes/statements.hpp b/src/parser/nodes/statements.hpp index 9ec9662..5b68b49 100644 --- a/src/parser/nodes/statements.hpp +++ b/src/parser/nodes/statements.hpp @@ -3,14 +3,14 @@ #include "parser/ast_node.hpp" -class BlockNode : public ASTNode { +class BlockNode : public StatementNode { public: BlockNode(); void log(int indent = 0) override; std::string toJson(int depth = 0) override; }; -class IfStatementNode : public ASTNode { +class IfStatementNode : public StatementNode { public: ASTNode* condition = nullptr; ASTNode* thenBranch = nullptr; @@ -20,7 +20,7 @@ public: std::string toJson(int depth = 0) override; }; -class WhileStatementNode : public ASTNode { +class WhileStatementNode : public StatementNode { public: ASTNode* condition = nullptr; ASTNode* body = nullptr; @@ -29,7 +29,7 @@ public: std::string toJson(int depth = 0) override; }; -class ForStatementNode : public ASTNode { +class ForStatementNode : public StatementNode { public: ASTNode* init = nullptr; ASTNode* condition = nullptr; @@ -40,7 +40,7 @@ public: std::string toJson(int depth = 0) override; }; -class DoWhileStatementNode : public ASTNode { +class DoWhileStatementNode : public StatementNode { public: ASTNode* condition = nullptr; ASTNode* body = nullptr; @@ -49,7 +49,7 @@ public: std::string toJson(int depth = 0) override; }; -class ReturnStatementNode : public ASTNode { +class ReturnStatementNode : public StatementNode { public: ASTNode* value = nullptr; ReturnStatementNode(); @@ -57,21 +57,21 @@ public: std::string toJson(int depth = 0) override; }; -class BreakStatementNode : public ASTNode { +class BreakStatementNode : public StatementNode { public: BreakStatementNode(); void log(int indent = 0) override; std::string toJson(int depth = 0) override; }; -class ContinueStatementNode : public ASTNode { +class ContinueStatementNode : public StatementNode { public: ContinueStatementNode(); void log(int indent = 0) override; std::string toJson(int depth = 0) override; }; -class ExpressionStatementNode : public ASTNode { +class ExpressionStatementNode : public StatementNode { public: ASTNode* expression = nullptr; ExpressionStatementNode(); From ba08bf45115a44f6cc88c29149230a000c284fbc Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Thu, 18 Jun 2026 15:43:26 +0300 Subject: [PATCH 12/28] =?UTF-8?q?feat(faz2):=20sembol=20tablosu=20?= =?UTF-8?q?=E2=80=94=20isim=20=C3=A7=C3=B6z=C3=BCmleme=20+=20scope=20+=20r?= =?UTF-8?q?eferans=20toplama=20(#71)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - parser: parseFunctionDecl() parametreleri artık AST'ye alıyor (FunctionDeclNode::params alanı eklendi; declarations.hpp/cpp güncellendi) - parser: parseDeclaration() kullanıcı-tanımlı tip (struct alanı) desteği - ast_json: addArray() m_hasArrayItem sıfırlama hatası düzeltildi (birden fazla dizi alanı içeren düğümlerde bozuk JSON üretimi giderildi) - src/symbol/: Symbol, Scope, SymbolTable, SymbolCollector eklendi * İki geçiş: pass1 global hoist, pass2 gövde + declare-before-use * E001 tanımsız isim, E002 çift tanım, E010 döngüsel struct * print builtin tohumlama (TODO: #89 katalog) - cli/symbols: yeni SymbolTable/Collector kullanıyor; tip + refs çıktısı - examples/symbols/: dup.sqt, undef.sqt, cyclic.sqt test fixture'ları Doğrulama: build/saqut symbols file:examples/fibonacci.sqt → 0 hata, 10 sembol examples/symbols/dup.sqt → E002 examples/symbols/undef.sqt → E001 examples/symbols/cyclic.sqt → E010 tests/run.sh → TUM TESTLER GECTI AST JSON → geçerli Co-Authored-By: Claude Opus 4.8 --- build/.ninja_deps | Bin 68992 -> 31712 bytes build/.ninja_log | 75 +---- build/CMakeCache.txt | 4 +- build/CMakeFiles/CMakeConfigureLog.yaml | 305 +++++++++++++++++++ build/build.ninja | 15 +- examples/symbols/cyclic.sqt | 12 + examples/symbols/dup.sqt | 6 + examples/symbols/undef.sqt | 5 + src/cli/commands/symbols.hpp | 34 ++- src/parser/ast_json.hpp | 3 + src/parser/nodes/declarations.cpp | 3 + src/parser/nodes/declarations.hpp | 3 + src/parser/parser.cpp | 30 +- src/symbol/scope.hpp | 37 +++ src/symbol/symbol.hpp | 34 +++ src/symbol/symbol_collector.cpp | 377 ++++++++++++++++++++++++ src/symbol/symbol_collector.hpp | 37 +++ src/symbol/symbol_table.hpp | 65 ++++ 18 files changed, 968 insertions(+), 77 deletions(-) create mode 100644 examples/symbols/cyclic.sqt create mode 100644 examples/symbols/dup.sqt create mode 100644 examples/symbols/undef.sqt create mode 100644 src/symbol/scope.hpp create mode 100644 src/symbol/symbol.hpp create mode 100644 src/symbol/symbol_collector.cpp create mode 100644 src/symbol/symbol_collector.hpp create mode 100644 src/symbol/symbol_table.hpp diff --git a/build/.ninja_deps b/build/.ninja_deps index 53faad2728db3656bb5622a00565d52e68e025f1..5664a6a25c82b6df029f6098e9d20704172860ee 100644 GIT binary patch delta 2923 zcmcImdr(wW7{3QuVAF=q@kJ5(%zPp*+YBy=;5PGB`Y5@V!w0uf@Ws_1T#O*Ip6o4@B7_z zzWu(_wk-PS1+t;Q7Tdh1+~IL=?Q+;ICB_;H5>N1KVc!`YD?PJg3DeZm^#i(Aj0r{4 z((E zioJ=u2xS43IdOcz-zeFeF3{Y@{Nz^2-_k0&Ln^c3xIZBrlGem4qPI`>2X>ZXXYMt* z+rx*!g5!SIobZ8wEbwaYp7XTbn@@*(P2@MIZB}uC>JVf}XjK$Z6106>_f4GgsvPtS z_NH^pX?kSU7wIfER51Qox&k4aeTpc$y`s-AiD5?POoWc+$336-t4#PSggF*oXr9k2 zUI*W*%KE3BhRbnue@a1$6(UV38yClk~Tmjz)Fex@m&V(N05 z$SL}0g^TX0jH6FFW5`Kbg4Lpi1bW12ASWnaTNRBb&1r!oZLW%JxijLJ}*N@o93$*rA04kDYYv%k_w3`5}V zxD2iZBnosA*8V0@M5PKdJu@qYe2EL1Ovl&7WPhO(8V(Y}%hp|Gr!qn(G`Rl>Eow+5 zpKIB&w;?tAfKFy42u$35=LJTlP$y&gAIS{-$Il5t3ffb$%t78S*^w`HnfnYy%1QRq zlJa8uuqVmzDahrcbY{|Zo;dP}R-F%dOi>^A(9XiKG+Rg_`)H9cfqcYNW?xuUL_TO& z1>r-j-0c%ghQ08?+D9h6D459yD5*nfy*I(|ey?vMuP8j45ceLOILNznw|5eGN84W} znhbCE+0Ek>KQF1=TUxN7EXiRNy~EzLM=RbTUI~kCsWs>k6;#~abiX)>ya{hE6CXxB z*M1RiP~PVxyXbOX9@$BE`y6Bk?Z*G@a50)}!*8dUPWB}vg%<`rasY0$U0dO$*bD)FkXQkJ)*BM4Ey5Q_63U(1L+|bamWfU^Z&N8fPnmls= zO%7O|s>w>Y1ClWStJP!av}T)e9A;%e`O-==d2IZxiuZpu6+#a$8*iNgZ`HuvfEgDa z=381-jIUBxAj7&5Jkzmqw1yQ&!0&Mgit0yFZlJ+{)9?zk6-d{AJ+?>&bDeZez-C>4 zqc8Xi+QafXdMuDhUZz(9HnJA;G+G>tGpvDi7R?Q280{q-_Yzj6^jO+RBQ`Y(f}MYn zwg-oi4!SjHv%YW>&jLKJrrp6zvWg~1dE|LoA`K%e!Fv>4A{if9apN9*nS?KU4)Vu2 zuI(P2hu_g|WR>w=%xi$D0Q*}Du$yDWiq#0#Ral#2C7rckR#n*}U>e5L81KV)KTr!y z2WAj%1UD0tSwI~y8>k2701dzcfE#!as6x(_{aaq*fS(27Hlz{@Rldxec@vnJ{IWB?dxAb*^slB5PJpv1uu6F AV*mgE delta 4258 zcmc&$du&r>6z{jSY_nZU%jPyl=|&5T!P-5L$I4!Wxi|;|geCF_>6$^i^|jku6wSyq zYIr7)qmiHzmWUA|$>s!#fHE1c!H}Vd@}3F^%sCzk_=oeHYfEgRxn732zx8@P94@%)w+i{ZXHCdb%(QFt-$mB&mryr1vDo!hzkSZG_E z1s#P-_8T;omcr1Y0qj1s78O8Mk&fL1ZE=Cd&)fKFceRK2n;kyiUEHl;zv9kR_6zO9 zhGI3lBVeu+>jvHay|2$Cmo@atWU@f_-V$=8EJ=~W*x8wIp;Re1du6xK*Hm^B>hi6_ zYy4gh@%AE4j<|RxlYK5fszF?`8lR((XFv;^@lrJ0nVtcgI2BAQPlJ6q3D7%5u2A3+ z4b+zxv7d#@Y%N#odqPwLaqpe^XOf9Z8=_K*Q)R&`6*~5l5YfpBoxVFnr$dV8uRlGM z=mv%8RAO{Fv#sm~-mKJU_xUiC>mjlPBq+Z-cnpyxhRB`}BdagZg52kH>>7nS`Y&}s z?jJ+MPa;`!)P^)7P6`pniV>e*P{gicz|Vwkc_l=aj0CYG=IMwmB}5h{Mn<>1Ql(>; zg$$0f>-0Z_=msN&J8xzt(WQpyV*ZgXPN*#&%UGu!qH^1u9y7*?^7$TG7hBnPkdvPc zSq=^Bf&#}#b_tp%nP7!Oskn&lra+ftEOg-R1$eo@06sQE;q;mv=joJck)P+PZEiDf zx1U3@Y^ZlC*;#0|8sGz`ik-nj7WOSPx<p-eEcR(GW~r(A+`&m#lBO>6sUuI24x*XlZEaXv5HqVB-w&CVU!>HUe!Vtl!raP9F4f)6}DJWei#tnwdd4H#qSrd>n_S!h?QWU4X~GhoRG-lyV4f zlYnoQfSQiJo^HF@_Yha0VCT5iX|gi z5dG%D!XT6+U2^AeONk7ZWya;%M=9?zU)cxYZKVGhZVo z|8c9$3b$HVq77rWuOz?ylxR4%BbD;(jx9kUHcdDSvnnr4phfzO3%Vuo#ZDV-#YL&& zqk`y~O@#y%FGxf!sk7$Jog+ZS|1*eyl7i}Y?-ZaC6-2t-9JPHiU09-SsasZ!YAYkC z#BQM;U7fRWIzh#IG$pLtuo~waPhCXN$E`+Hui8z1`=>@hVkL`!Zt3-K{#@dgo4-@nu zG}gMh_!>bUx5f(D!5;Ga2sB2?b06C9?Ca8#NAe85u+m0QiF1tdKE9{jPEhf@N6ayj zXLm(MH9;lHlbS+Psd5lhVpEVjx16&HP>J%S!Fy}q3MY9LZ;DyrITrr98Q1rD2-?3| rKln($>09G!M7qZ search starts here: + /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../include/c++/16.1.1 + /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../include/c++/16.1.1/x86_64-pc-linux-gnu + /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../include/c++/16.1.1/backward + /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/include + /usr/local/include + /usr/include + End of search list. + Compiler executable checksum: d47d0c990a24bc0dbaf3bd00656bd5f3 + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_cb4a5.dir/' + as -v --64 -o CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccE5rYpo.s + GNU assembler version 2.46.0 (x86_64-pc-linux-gnu) using BFD version (GNU Binutils) 2.46.0 + COMPILER_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.' + [2/2] : && /usr/bin/c++ -v -Wl,-v CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_cb4a5 && : + Using built-in specs. + COLLECT_GCC=/usr/bin/c++ + COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper + Target: x86_64-pc-linux-gnu + Configured with: /build/gcc/src/gcc/configure --enable-languages=ada,c,c++,d,fortran,go,lto,m2,objc,obj-c++,rust,cobol --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://gitlab.archlinux.org/archlinux/packaging/packages/gcc/-/issues --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror --disable-fixincludes + Thread model: posix + Supported LTO compression algorithms: zlib zstd + gcc version 16.1.1 20260430 (GCC) + COMPILER_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/ + LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../:/lib/:/usr/lib/ + COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_cb4a5' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_cb4a5.' + /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper -plugin-opt=-fresolution=/tmp/cc4Zp6V6.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-latomic_asneeded -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_cb4a5 /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../.. -L/lib -L/usr/lib -v CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -latomic_asneeded -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o + collect2 version 16.1.1 20260430 + /usr/bin/ld -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper -plugin-opt=-fresolution=/tmp/cc4Zp6V6.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-latomic_asneeded -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_cb4a5 /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../.. -L/lib -L/usr/lib -v CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -latomic_asneeded -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o + GNU ld (GNU Binutils) 2.46.0 + COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_cb4a5' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_cb4a5.' + + exitCode: 0 + - + kind: "message-v1" + backtrace: + - "/usr/share/cmake/Modules/CMakeDetermineCompilerABI.cmake:217 (message)" + - "/usr/share/cmake/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:2 (project)" + message: | + Parsed CXX implicit include dir info: rv=done + found start of include info + found start of implicit include info + add: [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../include/c++/16.1.1] + add: [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../include/c++/16.1.1/x86_64-pc-linux-gnu] + add: [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../include/c++/16.1.1/backward] + add: [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/include] + add: [/usr/local/include] + add: [/usr/include] + end of search list found + collapse include dir [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../include/c++/16.1.1] ==> [/usr/include/c++/16.1.1] + collapse include dir [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../include/c++/16.1.1/x86_64-pc-linux-gnu] ==> [/usr/include/c++/16.1.1/x86_64-pc-linux-gnu] + collapse include dir [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../include/c++/16.1.1/backward] ==> [/usr/include/c++/16.1.1/backward] + collapse include dir [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/include] ==> [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/include] + collapse include dir [/usr/local/include] ==> [/usr/local/include] + collapse include dir [/usr/include] ==> [/usr/include] + implicit include dirs: [/usr/include/c++/16.1.1;/usr/include/c++/16.1.1/x86_64-pc-linux-gnu;/usr/include/c++/16.1.1/backward;/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/include;/usr/local/include;/usr/include] + + + - + kind: "message-v1" + backtrace: + - "/usr/share/cmake/Modules/CMakeDetermineCompilerABI.cmake:253 (message)" + - "/usr/share/cmake/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:2 (project)" + message: | + Parsed CXX implicit link information: + link line regex: [^( *|.*[/\\])(ld[0-9]*(|\\.[a-rt-z][a-z]*|\\.s[a-np-z][a-z]*|\\.so[a-z]+)|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\\]+-)?ld|collect2)[^/\\]*( |$)] + linker tool regex: [^[ ]*(->|"|[0-9]+>[ -]*Build:[ 0-9]+ ms[ ]*)?[ ]*(([^"]*[/\\])?(ld[0-9]*(|\\.[a-rt-z][a-z]*|\\.s[a-np-z][a-z]*|\\.so[a-z]+)))("|,| |$)] + ignore line: [Change Dir: '/home/saqut/Masaüstü/saqutcompiler/build/CMakeFiles/CMakeScratch/TryCompile-OqZJyT'] + ignore line: [] + ignore line: [Run Build Command(s): /usr/bin/ninja -v cmTC_cb4a5] + ignore line: [[1/2] /usr/bin/c++ -v -o CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [Target: x86_64-pc-linux-gnu] + ignore line: [Configured with: /build/gcc/src/gcc/configure --enable-languages=ada c c++ d fortran go lto m2 objc obj-c++ rust cobol --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://gitlab.archlinux.org/archlinux/packaging/packages/gcc/-/issues --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror --disable-fixincludes] + ignore line: [Thread model: posix] + ignore line: [Supported LTO compression algorithms: zlib zstd] + ignore line: [gcc version 16.1.1 20260430 (GCC) ] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_cb4a5.dir/'] + ignore line: [ /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/cc1plus -quiet -v -D_GNU_SOURCE /usr/share/cmake/Modules/CMakeCXXCompilerABI.cpp -quiet -dumpdir CMakeFiles/cmTC_cb4a5.dir/ -dumpbase CMakeCXXCompilerABI.cpp.cpp -dumpbase-ext .cpp -mtune=generic -march=x86-64 -version -o /tmp/ccE5rYpo.s] + ignore line: [GNU C++20 (GCC) version 16.1.1 20260430 (x86_64-pc-linux-gnu)] + ignore line: [ compiled by GNU C version 16.1.1 20260430 GMP version 6.3.0 MPFR version 4.2.2 MPC version 1.4.1 isl version isl-0.27-GMP] + ignore line: [] + ignore line: [GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/include-fixed"] + ignore line: [ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../x86_64-pc-linux-gnu/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../include/c++/16.1.1] + ignore line: [ /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../include/c++/16.1.1/x86_64-pc-linux-gnu] + ignore line: [ /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../include/c++/16.1.1/backward] + ignore line: [ /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/include] + ignore line: [ /usr/local/include] + ignore line: [ /usr/include] + ignore line: [End of search list.] + ignore line: [Compiler executable checksum: d47d0c990a24bc0dbaf3bd00656bd5f3] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_cb4a5.dir/'] + ignore line: [ as -v --64 -o CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.o /tmp/ccE5rYpo.s] + ignore line: [GNU assembler version 2.46.0 (x86_64-pc-linux-gnu) using BFD version (GNU Binutils) 2.46.0] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.'] + ignore line: [[2/2] : && /usr/bin/c++ -v -Wl -v CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.o -o cmTC_cb4a5 && :] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper] + ignore line: [Target: x86_64-pc-linux-gnu] + ignore line: [Configured with: /build/gcc/src/gcc/configure --enable-languages=ada c c++ d fortran go lto m2 objc obj-c++ rust cobol --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://gitlab.archlinux.org/archlinux/packaging/packages/gcc/-/issues --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror --disable-fixincludes] + ignore line: [Thread model: posix] + ignore line: [Supported LTO compression algorithms: zlib zstd] + ignore line: [gcc version 16.1.1 20260430 (GCC) ] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTC_cb4a5' '-shared-libgcc' '-mtune=generic' '-march=x86-64' '-dumpdir' 'cmTC_cb4a5.'] + link line: [ /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/collect2 -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper -plugin-opt=-fresolution=/tmp/cc4Zp6V6.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-latomic_asneeded -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_cb4a5 /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../.. -L/lib -L/usr/lib -v CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -latomic_asneeded -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o] + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/collect2] ==> ignore + arg [-plugin] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/liblto_plugin.so] ==> ignore + arg [-plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper] ==> ignore + arg [-plugin-opt=-fresolution=/tmp/cc4Zp6V6.res] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [-plugin-opt=-pass-through=-latomic_asneeded] ==> ignore + arg [-plugin-opt=-pass-through=-lc] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc_s] ==> ignore + arg [-plugin-opt=-pass-through=-lgcc] ==> ignore + arg [--build-id] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-pie] ==> ignore + arg [-o] ==> ignore + arg [cmTC_cb4a5] ==> ignore + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o] ==> obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o] + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o] ==> obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o] + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o] ==> obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o] + arg [-L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1] ==> dir [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1] + arg [-L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib] + arg [-L/lib/../lib] ==> dir [/lib/../lib] + arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] + arg [-L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../..] ==> dir [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../..] + arg [-L/lib] ==> dir [/lib] + arg [-L/usr/lib] ==> dir [/usr/lib] + arg [-v] ==> ignore + arg [CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore + arg [-lstdc++] ==> lib [stdc++] + arg [-lm] ==> lib [m] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [-latomic_asneeded] ==> lib [atomic_asneeded] + arg [-lc] ==> lib [c] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o] ==> obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o] + arg [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o] ==> obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o] + ignore line: [collect2 version 16.1.1 20260430] + ignore line: [/usr/bin/ld -plugin /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper -plugin-opt=-fresolution=/tmp/cc4Zp6V6.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-latomic_asneeded -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o cmTC_cb4a5 /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1 -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../.. -L/lib -L/usr/lib -v CMakeFiles/cmTC_cb4a5.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -latomic_asneeded -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o /usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o] + linker tool for 'CXX': /usr/bin/ld + collapse obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/Scrt1.o] ==> [/usr/lib/Scrt1.o] + collapse obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crti.o] ==> [/usr/lib/crti.o] + collapse obj [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib/crtn.o] ==> [/usr/lib/crtn.o] + collapse library dir [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1] ==> [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1] + collapse library dir [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../../../lib] ==> [/usr/lib] + collapse library dir [/lib/../lib] ==> [/lib] + collapse library dir [/usr/lib/../lib] ==> [/usr/lib] + collapse library dir [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/../../..] ==> [/usr/lib] + collapse library dir [/lib] ==> [/lib] + collapse library dir [/usr/lib] ==> [/usr/lib] + implicit libs: [stdc++;m;gcc_s;gcc;atomic_asneeded;c;gcc_s;gcc] + implicit objs: [/usr/lib/Scrt1.o;/usr/lib/crti.o;/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtbeginS.o;/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1/crtendS.o;/usr/lib/crtn.o] + implicit dirs: [/usr/lib/gcc/x86_64-pc-linux-gnu/16.1.1;/usr/lib;/lib] + implicit fwks: [] + + + - + kind: "message-v1" + backtrace: + - "/usr/share/cmake/Modules/Internal/CMakeDetermineLinkerId.cmake:38 (message)" + - "/usr/share/cmake/Modules/CMakeDetermineCompilerABI.cmake:299 (cmake_determine_linker_id)" + - "/usr/share/cmake/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:2 (project)" + message: | + Running the CXX compiler's linker: "/usr/bin/ld" "-v" + GNU ld (GNU Binutils) 2.46.0 +... diff --git a/build/build.ninja b/build/build.ninja index e1adc35..3bf1809 100644 --- a/build/build.ninja +++ b/build/build.ninja @@ -148,6 +148,15 @@ build CMakeFiles/saqut.dir/src/parser/parser.cpp.o: CXX_COMPILER__saqut_unscanne OBJECT_FILE_DIR = CMakeFiles/saqut.dir/src/parser TARGET_SUPPORT_DIR = CMakeFiles/saqut.dir +build CMakeFiles/saqut.dir/src/symbol/symbol_collector.cpp.o: CXX_COMPILER__saqut_unscanned_Debug /home/saqut/Masaüstü/saqutcompiler/src/symbol/symbol_collector.cpp || cmake_object_order_depends_target_saqut + CONFIG = Debug + DEP_FILE = CMakeFiles/saqut.dir/src/symbol/symbol_collector.cpp.o.d + FLAGS = -g -std=gnu++20 -Wall -Wextra -g -O0 + INCLUDES = -I/home/saqut/Masaüstü/saqutcompiler/src + OBJECT_DIR = CMakeFiles/saqut.dir + OBJECT_FILE_DIR = CMakeFiles/saqut.dir/src/symbol + TARGET_SUPPORT_DIR = CMakeFiles/saqut.dir + build CMakeFiles/saqut.dir/src/tokenizer/tokenizer.cpp.o: CXX_COMPILER__saqut_unscanned_Debug /home/saqut/Masaüstü/saqutcompiler/src/tokenizer/tokenizer.cpp || cmake_object_order_depends_target_saqut CONFIG = Debug DEP_FILE = CMakeFiles/saqut.dir/src/tokenizer/tokenizer.cpp.o.d @@ -165,7 +174,7 @@ build CMakeFiles/saqut.dir/src/tokenizer/tokenizer.cpp.o: CXX_COMPILER__saqut_un ############################################# # Link the executable saqut -build saqut: CXX_EXECUTABLE_LINKER__saqut_Debug CMakeFiles/saqut.dir/src/core/sourcefile.cpp.o CMakeFiles/saqut.dir/src/lexer/lexer.cpp.o CMakeFiles/saqut.dir/src/main.cpp.o CMakeFiles/saqut.dir/src/parser/nodes/binary_expr.cpp.o CMakeFiles/saqut.dir/src/parser/nodes/declarations.cpp.o CMakeFiles/saqut.dir/src/parser/nodes/expressions.cpp.o CMakeFiles/saqut.dir/src/parser/nodes/identifier.cpp.o CMakeFiles/saqut.dir/src/parser/nodes/literal.cpp.o CMakeFiles/saqut.dir/src/parser/nodes/program.cpp.o CMakeFiles/saqut.dir/src/parser/nodes/statements.cpp.o CMakeFiles/saqut.dir/src/parser/parser.cpp.o CMakeFiles/saqut.dir/src/tokenizer/tokenizer.cpp.o +build saqut: CXX_EXECUTABLE_LINKER__saqut_Debug CMakeFiles/saqut.dir/src/core/sourcefile.cpp.o CMakeFiles/saqut.dir/src/lexer/lexer.cpp.o CMakeFiles/saqut.dir/src/main.cpp.o CMakeFiles/saqut.dir/src/parser/nodes/binary_expr.cpp.o CMakeFiles/saqut.dir/src/parser/nodes/declarations.cpp.o CMakeFiles/saqut.dir/src/parser/nodes/expressions.cpp.o CMakeFiles/saqut.dir/src/parser/nodes/identifier.cpp.o CMakeFiles/saqut.dir/src/parser/nodes/literal.cpp.o CMakeFiles/saqut.dir/src/parser/nodes/program.cpp.o CMakeFiles/saqut.dir/src/parser/nodes/statements.cpp.o CMakeFiles/saqut.dir/src/parser/parser.cpp.o CMakeFiles/saqut.dir/src/symbol/symbol_collector.cpp.o CMakeFiles/saqut.dir/src/tokenizer/tokenizer.cpp.o CONFIG = Debug DEP_FILE = CMakeFiles/saqut.dir/link.d FLAGS = -g @@ -221,14 +230,14 @@ build all: phony saqut ############################################# # Re-run CMake if any of its inputs changed. -build build.ninja /home/saqut/Masaüstü/saqutcompiler/build/cmake_install.cmake: RERUN_CMAKE | /home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt /usr/share/cmake/Modules/CMakeCXXInformation.cmake /usr/share/cmake/Modules/CMakeCommonLanguageInclude.cmake /usr/share/cmake/Modules/CMakeGenericSystem.cmake /usr/share/cmake/Modules/CMakeInitializeConfigs.cmake /usr/share/cmake/Modules/CMakeLanguageInformation.cmake /usr/share/cmake/Modules/CMakeSystemSpecificInformation.cmake /usr/share/cmake/Modules/CMakeSystemSpecificInitialize.cmake /usr/share/cmake/Modules/Compiler/CMakeCommonCompilerMacros.cmake /usr/share/cmake/Modules/Compiler/GNU-CXX.cmake /usr/share/cmake/Modules/Compiler/GNU.cmake /usr/share/cmake/Modules/Internal/CMakeCXXLinkerInformation.cmake /usr/share/cmake/Modules/Internal/CMakeCommonLinkerInformation.cmake /usr/share/cmake/Modules/Linker/GNU-CXX.cmake /usr/share/cmake/Modules/Linker/GNU.cmake /usr/share/cmake/Modules/Platform/Linker/GNU.cmake /usr/share/cmake/Modules/Platform/Linker/Linux-GNU-CXX.cmake /usr/share/cmake/Modules/Platform/Linker/Linux-GNU.cmake /usr/share/cmake/Modules/Platform/Linux-GNU-CXX.cmake /usr/share/cmake/Modules/Platform/Linux-GNU.cmake /usr/share/cmake/Modules/Platform/Linux-Initialize.cmake /usr/share/cmake/Modules/Platform/Linux.cmake /usr/share/cmake/Modules/Platform/UnixPaths.cmake CMakeCache.txt CMakeFiles/4.3.2/CMakeCXXCompiler.cmake CMakeFiles/4.3.2/CMakeSystem.cmake +build build.ninja /home/saqut/Masaüstü/saqutcompiler/build/cmake_install.cmake: RERUN_CMAKE | /home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt /usr/share/cmake/Modules/CMakeCXXInformation.cmake /usr/share/cmake/Modules/CMakeCommonLanguageInclude.cmake /usr/share/cmake/Modules/CMakeGenericSystem.cmake /usr/share/cmake/Modules/CMakeInitializeConfigs.cmake /usr/share/cmake/Modules/CMakeLanguageInformation.cmake /usr/share/cmake/Modules/CMakeSystemSpecificInformation.cmake /usr/share/cmake/Modules/CMakeSystemSpecificInitialize.cmake /usr/share/cmake/Modules/Compiler/CMakeCommonCompilerMacros.cmake /usr/share/cmake/Modules/Compiler/GNU-CXX.cmake /usr/share/cmake/Modules/Compiler/GNU.cmake /usr/share/cmake/Modules/Internal/CMakeCXXLinkerInformation.cmake /usr/share/cmake/Modules/Internal/CMakeCommonLinkerInformation.cmake /usr/share/cmake/Modules/Linker/GNU-CXX.cmake /usr/share/cmake/Modules/Linker/GNU.cmake /usr/share/cmake/Modules/Platform/Linker/GNU.cmake /usr/share/cmake/Modules/Platform/Linker/Linux-GNU-CXX.cmake /usr/share/cmake/Modules/Platform/Linker/Linux-GNU.cmake /usr/share/cmake/Modules/Platform/Linux-GNU-CXX.cmake /usr/share/cmake/Modules/Platform/Linux-GNU.cmake /usr/share/cmake/Modules/Platform/Linux-Initialize.cmake /usr/share/cmake/Modules/Platform/Linux.cmake /usr/share/cmake/Modules/Platform/UnixPaths.cmake CMakeCache.txt CMakeFiles/4.3.3/CMakeCXXCompiler.cmake CMakeFiles/4.3.3/CMakeSystem.cmake pool = console ############################################# # A missing CMake input file is not an error. -build /home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt /usr/share/cmake/Modules/CMakeCXXInformation.cmake /usr/share/cmake/Modules/CMakeCommonLanguageInclude.cmake /usr/share/cmake/Modules/CMakeGenericSystem.cmake /usr/share/cmake/Modules/CMakeInitializeConfigs.cmake /usr/share/cmake/Modules/CMakeLanguageInformation.cmake /usr/share/cmake/Modules/CMakeSystemSpecificInformation.cmake /usr/share/cmake/Modules/CMakeSystemSpecificInitialize.cmake /usr/share/cmake/Modules/Compiler/CMakeCommonCompilerMacros.cmake /usr/share/cmake/Modules/Compiler/GNU-CXX.cmake /usr/share/cmake/Modules/Compiler/GNU.cmake /usr/share/cmake/Modules/Internal/CMakeCXXLinkerInformation.cmake /usr/share/cmake/Modules/Internal/CMakeCommonLinkerInformation.cmake /usr/share/cmake/Modules/Linker/GNU-CXX.cmake /usr/share/cmake/Modules/Linker/GNU.cmake /usr/share/cmake/Modules/Platform/Linker/GNU.cmake /usr/share/cmake/Modules/Platform/Linker/Linux-GNU-CXX.cmake /usr/share/cmake/Modules/Platform/Linker/Linux-GNU.cmake /usr/share/cmake/Modules/Platform/Linux-GNU-CXX.cmake /usr/share/cmake/Modules/Platform/Linux-GNU.cmake /usr/share/cmake/Modules/Platform/Linux-Initialize.cmake /usr/share/cmake/Modules/Platform/Linux.cmake /usr/share/cmake/Modules/Platform/UnixPaths.cmake CMakeCache.txt CMakeFiles/4.3.2/CMakeCXXCompiler.cmake CMakeFiles/4.3.2/CMakeSystem.cmake: phony +build /home/saqut/Masaüstü/saqutcompiler/CMakeLists.txt /usr/share/cmake/Modules/CMakeCXXInformation.cmake /usr/share/cmake/Modules/CMakeCommonLanguageInclude.cmake /usr/share/cmake/Modules/CMakeGenericSystem.cmake /usr/share/cmake/Modules/CMakeInitializeConfigs.cmake /usr/share/cmake/Modules/CMakeLanguageInformation.cmake /usr/share/cmake/Modules/CMakeSystemSpecificInformation.cmake /usr/share/cmake/Modules/CMakeSystemSpecificInitialize.cmake /usr/share/cmake/Modules/Compiler/CMakeCommonCompilerMacros.cmake /usr/share/cmake/Modules/Compiler/GNU-CXX.cmake /usr/share/cmake/Modules/Compiler/GNU.cmake /usr/share/cmake/Modules/Internal/CMakeCXXLinkerInformation.cmake /usr/share/cmake/Modules/Internal/CMakeCommonLinkerInformation.cmake /usr/share/cmake/Modules/Linker/GNU-CXX.cmake /usr/share/cmake/Modules/Linker/GNU.cmake /usr/share/cmake/Modules/Platform/Linker/GNU.cmake /usr/share/cmake/Modules/Platform/Linker/Linux-GNU-CXX.cmake /usr/share/cmake/Modules/Platform/Linker/Linux-GNU.cmake /usr/share/cmake/Modules/Platform/Linux-GNU-CXX.cmake /usr/share/cmake/Modules/Platform/Linux-GNU.cmake /usr/share/cmake/Modules/Platform/Linux-Initialize.cmake /usr/share/cmake/Modules/Platform/Linux.cmake /usr/share/cmake/Modules/Platform/UnixPaths.cmake CMakeCache.txt CMakeFiles/4.3.3/CMakeCXXCompiler.cmake CMakeFiles/4.3.3/CMakeSystem.cmake: phony ############################################# diff --git a/examples/symbols/cyclic.sqt b/examples/symbols/cyclic.sqt new file mode 100644 index 0000000..4a1b373 --- /dev/null +++ b/examples/symbols/cyclic.sqt @@ -0,0 +1,12 @@ +// E010 — döngüsel struct (by-value çevrim → sonsuz boyut) +struct A { + B b; +} + +struct B { + A a; +} + +int main() { + return 0; +} diff --git a/examples/symbols/dup.sqt b/examples/symbols/dup.sqt new file mode 100644 index 0000000..ae8f5e6 --- /dev/null +++ b/examples/symbols/dup.sqt @@ -0,0 +1,6 @@ +// E002 — aynı scope'ta çift tanım +int main() { + int x = 1; + int x = 2; + return 0; +} diff --git a/examples/symbols/undef.sqt b/examples/symbols/undef.sqt new file mode 100644 index 0000000..2efc0e0 --- /dev/null +++ b/examples/symbols/undef.sqt @@ -0,0 +1,5 @@ +// E001 — tanımsız isim +int main() { + int x = y + 1; + return 0; +} diff --git a/src/cli/commands/symbols.hpp b/src/cli/commands/symbols.hpp index 0eeb865..90b4b4b 100644 --- a/src/cli/commands/symbols.hpp +++ b/src/cli/commands/symbols.hpp @@ -1,5 +1,5 @@ // ============================================================================ -// saQut CLI — symbols komutu (sembol tablosu) +// saQut CLI — symbols komutu (sembol tablosu — Faz 2) // ============================================================================ #ifndef SAQUT_CLI_SYMBOLS @@ -9,7 +9,9 @@ #include "cli/args.hpp" #include "tokenizer/tokenizer.hpp" #include "parser/parser.hpp" -#include "json.hpp" +#include "symbol/symbol_table.hpp" +#include "symbol/symbol_collector.hpp" +#include "diagnostic/diagnostic_engine.hpp" inline int cmdSymbols(const CliArgs& args) { std::string source = readSource(args); @@ -27,7 +29,11 @@ inline int cmdSymbols(const CliArgs& args) { return 1; } - auto symbols = collectSymbols(ast); + SymbolTable table; + DiagnosticEngine diag; + SymbolCollector(table, diag).collect(ast); + + auto symbols = table.allSymbols(); std::cout << "Sembol Tablosu (" << symbols.size() << " sembol):\n"; std::cout << "────────────────────────────────────────────\n"; @@ -36,23 +42,27 @@ inline int cmdSymbols(const CliArgs& args) { std::cout << " (sembol bulunamadı)\n"; } - for (auto& s : symbols) { - std::cout << " [" << s.kind << "] " << s.type << " " << s.name << "\n"; + for (Symbol* s : symbols) { + if (s->isBuiltin) continue; // builtinleri çıktıda gösterme + std::cout << " [" << symbolKindName(s->kind) << "] " + << s->type.toString() << " " << s->name + << " @" << s->definitionLoc.shortString() + << " refs(" << s->references.size() << "):"; + for (auto& r : s->references) + std::cout << " " << r.shortString(); + std::cout << "\n"; } std::cout << "────────────────────────────────────────────\n"; - int fnCount = 0, varCount = 0; - for (auto& s : symbols) { - if (s.kind == "function") fnCount++; - else if (s.kind == "variable") varCount++; + if (diag.hasErrors()) { + std::cerr << "\n"; + diag.printAll(std::cerr); } - std::cout << "Fonksiyon: " << fnCount - << " | Değişken: " << varCount << "\n"; delete ast; for (auto* t : tokens) delete t; - return 0; + return diag.hasErrors() ? 1 : 0; } #endif // SAQUT_CLI_SYMBOLS diff --git a/src/parser/ast_json.hpp b/src/parser/ast_json.hpp index b7130a7..a4d0a91 100644 --- a/src/parser/ast_json.hpp +++ b/src/parser/ast_json.hpp @@ -187,7 +187,10 @@ public: if (m_hasFields) m_ss << ",\n"; m_ss << m_indentInner << "\"" << jsonEscape(key) << "\": ["; m_arrayDepth++; + bool saved = m_hasArrayItem; + m_hasArrayItem = false; // her dizi kendi virgül sayacıyla başlar callback(); + m_hasArrayItem = saved; m_arrayDepth--; m_ss << "\n" << m_indentInner << "]"; m_hasFields = true; diff --git a/src/parser/nodes/declarations.cpp b/src/parser/nodes/declarations.cpp index e4357fb..994f81e 100644 --- a/src/parser/nodes/declarations.cpp +++ b/src/parser/nodes/declarations.cpp @@ -12,6 +12,9 @@ std::string FunctionDeclNode::toJson(int depth) { obj.add("kind", "FunctionDecl"); obj.add("name", name); obj.add("returnType", returnType); + obj.addArray("params", [&]() { + for (auto* p : params) obj.addItem(p->toJson(depth + 2)); + }); obj.addArray("children", [&]() { for (auto* child : children) obj.addItem(child->toJson(depth + 2)); }); diff --git a/src/parser/nodes/declarations.hpp b/src/parser/nodes/declarations.hpp index 20bf751..8779b82 100644 --- a/src/parser/nodes/declarations.hpp +++ b/src/parser/nodes/declarations.hpp @@ -3,10 +3,13 @@ #include "parser/ast_node.hpp" +class VariableDeclNode; // fwd — FunctionDeclNode::params için + class FunctionDeclNode : public ASTNode { public: std::string name; std::string returnType; + std::vector params; // TODO(faz2): parametreler FunctionDeclNode(); void log(int indent = 0) override; std::string toJson(int depth = 0) override; diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp index 7f0e7e7..398abde 100644 --- a/src/parser/parser.cpp +++ b/src/parser/parser.cpp @@ -91,6 +91,16 @@ ASTNode* Parser::parseDeclaration() { if (ct.type == TokenType::KW_STRUCT) return parseStructDecl(); + // Kullanıcı tanımlı tip adı (struct tipi) ile değişken/fonksiyon bildirimi + if (ct.type == TokenType::IDENTIFIER) { + auto la1 = lookahead(1); + auto la2 = lookahead(2); + if (la1.type == TokenType::IDENTIFIER && la2.type == TokenType::LPAREN) + return parseFunctionDecl(); + if (la1.type == TokenType::IDENTIFIER) + return parseVariableDecl(); + } + return parseStatement(); } @@ -293,8 +303,26 @@ ASTNode* Parser::parseFunctionDecl() { if (currentToken().type == TokenType::LPAREN) { nextToken(); while (currentToken().type != TokenType::RPAREN && - currentToken().type != TokenType::SVR_VOID) + currentToken().type != TokenType::SVR_VOID) { + auto typeTok = currentToken(); + bool isTypeKw = typeTok.is({ + TokenType::KW_VOID, TokenType::KW_INT, TokenType::KW_FLOAT_TYPE, + TokenType::KW_DOUBLE, TokenType::KW_BOOL, TokenType::KW_CHAR, + TokenType::KW_STRING_TYPE, TokenType::KW_AUTO + }) || typeTok.type == TokenType::IDENTIFIER; + if (!isTypeKw || !typeTok.token) break; + std::string paramType = typeTok.token->token; nextToken(); + if (currentToken().type != TokenType::IDENTIFIER || !currentToken().token) break; + VariableDeclNode* param = new VariableDeclNode(); + param->loc = currentToken().token->loc; + param->varType = paramType; + param->name = currentToken().token->token; + nextToken(); + fn->params.push_back(param); + if (currentToken().type == TokenType::COMMA) + nextToken(); + } if (currentToken().type == TokenType::RPAREN) nextToken(); } diff --git a/src/symbol/scope.hpp b/src/symbol/scope.hpp new file mode 100644 index 0000000..74d0ad4 --- /dev/null +++ b/src/symbol/scope.hpp @@ -0,0 +1,37 @@ +#ifndef SAQUT_SYMBOL_SCOPE +#define SAQUT_SYMBOL_SCOPE + +#include +#include +#include "symbol/symbol.hpp" + +class Scope { +public: + Scope* parent = nullptr; + explicit Scope(Scope* p = nullptr) : parent(p) {} + + // Bu scope'a ekle. Aynı adda varsa nullptr (duplicate → çağıran E002 verir). + Symbol* defineLocal(Symbol* s) { + if (table.count(s->name)) return nullptr; + table[s->name] = s; + order.push_back(s); + s->scope = this; + return s; + } + + Symbol* lookupLocal(const std::string& n) { + auto it = table.find(n); + return it == table.end() ? nullptr : it->second; + } + + Symbol* resolve(const std::string& n) { + for (Scope* s = this; s; s = s->parent) + if (auto* r = s->lookupLocal(n)) return r; + return nullptr; + } + + std::unordered_map table; // non-owning + std::vector order; // ekleme sırası +}; + +#endif // SAQUT_SYMBOL_SCOPE diff --git a/src/symbol/symbol.hpp b/src/symbol/symbol.hpp new file mode 100644 index 0000000..4328d7d --- /dev/null +++ b/src/symbol/symbol.hpp @@ -0,0 +1,34 @@ +#ifndef SAQUT_SYMBOL_SYMBOL +#define SAQUT_SYMBOL_SYMBOL + +#include +#include +#include "core/type.hpp" +#include "core/location.hpp" + +enum class SymbolKind { Variable, Function, Parameter, Struct, Field }; + +inline const char* symbolKindName(SymbolKind k) { + switch (k) { + case SymbolKind::Variable: return "variable"; + case SymbolKind::Function: return "function"; + case SymbolKind::Parameter: return "parameter"; + case SymbolKind::Struct: return "struct"; + case SymbolKind::Field: return "field"; + } + return "?"; +} + +class Scope; + +struct Symbol { + std::string name; + SymbolKind kind = SymbolKind::Variable; + Type type; + SourceLocation definitionLoc; + std::vector references; + Scope* scope = nullptr; + bool isBuiltin = false; +}; + +#endif // SAQUT_SYMBOL_SYMBOL diff --git a/src/symbol/symbol_collector.cpp b/src/symbol/symbol_collector.cpp new file mode 100644 index 0000000..c4295b6 --- /dev/null +++ b/src/symbol/symbol_collector.cpp @@ -0,0 +1,377 @@ +#include "symbol/symbol_collector.hpp" +#include +#include "parser/nodes/program.hpp" +#include "parser/nodes/declarations.hpp" +#include "parser/nodes/statements.hpp" +#include "parser/nodes/expressions.hpp" +#include "parser/nodes/binary_expr.hpp" +#include "parser/nodes/identifier.hpp" + +// ───────────────────────────────────────────────────────────────────────────── +// collect — dört aşamalı toplama +// ───────────────────────────────────────────────────────────────────────────── + +void SymbolCollector::collect(ASTNode* program) { + if (!program) return; + seedBuiltins(); + pass1Globals(program); + checkStructCycles(); + pass2Bodies(program); +} + +// ───────────────────────────────────────────────────────────────────────────── +// seedBuiltins — global scope'a yerleşik fonksiyonları ekle +// ───────────────────────────────────────────────────────────────────────────── + +void SymbolCollector::seedBuiltins() { + // TODO(#89 builtin kataloğu): geçici; ileride gerçek katalog gelecek. + Symbol* s = table_.define("print", SymbolKind::Function, + Type::function(Type::Void(), {}), + SourceLocation{}); + if (s) s->isBuiltin = true; +} + +// ───────────────────────────────────────────────────────────────────────────── +// typeFromName — tip adından Type üret; bilinmiyorsa E007 +// ───────────────────────────────────────────────────────────────────────────── + +Type SymbolCollector::typeFromName(const std::string& n, const SourceLocation& loc) { + Type t = Type::fromName(n); + if (!t.isError()) return t; + if (structFields_.count(n)) return Type::structType(n); + // TODO(faz2/faz3): bilinmeyen tip tam E007 tanısı + diag_.report("E007", loc, "Bilinmeyen tip: '" + n + "'"); + return Type::error(); +} + +// ───────────────────────────────────────────────────────────────────────────── +// pass1Globals — üst-seviye isimleri hoist eder (gövdelere girmez) +// ───────────────────────────────────────────────────────────────────────────── + +void SymbolCollector::pass1Globals(ASTNode* program) { + for (ASTNode* child : program->getChildren()) { + switch (child->kind) { + + case ASTKind::FunctionDecl: { + auto* fn = (FunctionDeclNode*)child; + // parametre tiplerini topla + std::vector paramTypes; + for (auto* p : fn->params) + paramTypes.push_back(typeFromName(p->varType, p->loc)); + Type retType = typeFromName(fn->returnType, fn->loc); + Symbol* s = table_.define(fn->name, SymbolKind::Function, + Type::function(retType, paramTypes), + fn->loc); + if (!s) + diag_.report("E002", fn->loc, + "'" + fn->name + "' zaten bu kapsamda tanımlı"); + break; + } + + case ASTKind::StructDecl: { + auto* st = (StructDeclNode*)child; + Symbol* s = table_.define(st->name, SymbolKind::Struct, + Type::structType(st->name), st->loc); + if (!s) { + diag_.report("E002", st->loc, + "'" + st->name + "' zaten bu kapsamda tanımlı"); + break; + } + // struct alan isimlerini cycle check için kaydet + for (ASTNode* fieldNode : st->getChildren()) { + if (fieldNode->kind == ASTKind::VariableDecl) { + auto* vd = (VariableDeclNode*)fieldNode; + // yalnızca struct tipindeki alanları izle + Type ft = Type::fromName(vd->varType); + if (ft.isError()) // primitif değilse struct tipi olabilir + structFields_[st->name].push_back(vd->varType); + } + } + break; + } + + case ASTKind::VariableDecl: { + auto* vd = (VariableDeclNode*)child; + Symbol* s = table_.define(vd->name, SymbolKind::Variable, + typeFromName(vd->varType, vd->loc), + vd->loc); + if (!s) + diag_.report("E002", vd->loc, + "'" + vd->name + "' zaten bu kapsamda tanımlı"); + // Sibling VariableDecl'ler (int a, b;) + for (ASTNode* sib : vd->getChildren()) { + if (sib->kind == ASTKind::VariableDecl) { + auto* sv = (VariableDeclNode*)sib; + Symbol* ss = table_.define(sv->name, SymbolKind::Variable, + typeFromName(sv->varType, sv->loc), + sv->loc); + if (!ss) + diag_.report("E002", sv->loc, + "'" + sv->name + "' zaten bu kapsamda tanımlı"); + } + } + break; + } + + default: + break; + } + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// checkStructCycles — E010 döngüsel struct (by-value çevrim → sonsuz boyut) +// ───────────────────────────────────────────────────────────────────────────── + +void SymbolCollector::checkStructCycles() { + // white=0 / gray=1 / black=2 + std::unordered_map color; + for (auto& kv : structFields_) color[kv.first] = 0; + + std::function dfs = [&](const std::string& name) -> bool { + auto it = color.find(name); + if (it == color.end()) return false; // primitif / bilinmeyen → çevrim değil + if (it->second == 1) return true; // gray → back-edge → çevrim! + if (it->second == 2) return false; // black → zaten işlendi + + it->second = 1; // gri yap + auto fit = structFields_.find(name); + if (fit != structFields_.end()) { + for (const std::string& dep : fit->second) { + if (dfs(dep)) return true; + } + } + it->second = 2; // siyah yap + return false; + }; + + for (auto& kv : structFields_) { + if (color[kv.first] == 0) { + // DFS başlat + color[kv.first] = 1; + for (const std::string& dep : kv.second) { + if (dfs(dep)) { + // tanımlama konumunu bulmak için global scope'ta ara + Symbol* s = table_.global()->lookupLocal(kv.first); + SourceLocation loc = s ? s->definitionLoc : SourceLocation{}; + diag_.report("E010", loc, + "Döngüsel struct: '" + kv.first + "' by-value sonsuz boyut oluşturur"); + break; + } + } + color[kv.first] = 2; + } + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// pass2Bodies — fonksiyon gövdelerini gez; isim çözümle + referans topla +// ───────────────────────────────────────────────────────────────────────────── + +void SymbolCollector::pass2Bodies(ASTNode* program) { + for (ASTNode* child : program->getChildren()) { + switch (child->kind) { + + case ASTKind::FunctionDecl: { + auto* fn = (FunctionDeclNode*)child; + table_.enterScope(); + // parametreleri tanımla + for (auto* p : fn->params) { + Symbol* s = table_.define(p->name, SymbolKind::Parameter, + typeFromName(p->varType, p->loc), p->loc); + if (!s) + diag_.report("E002", p->loc, + "Parametre '" + p->name + "' zaten tanımlı"); + } + // gövdeyi gez (children[0] = BlockNode) + auto& ch = fn->getChildren(); + if (!ch.empty()) walkStmt(ch[0]); + table_.exitScope(); + break; + } + + case ASTKind::VariableDecl: { + // global değişken başlatıcısı (declare-before-use) + auto* vd = (VariableDeclNode*)child; + if (vd->initExpr) walkExpr(vd->initExpr); + // TODO(faz2): global init sırası kontrolü (fibonacci'de global var yok) + for (ASTNode* sib : vd->getChildren()) { + if (sib->kind == ASTKind::VariableDecl) { + auto* sv = (VariableDeclNode*)sib; + if (sv->initExpr) walkExpr(sv->initExpr); + } + } + break; + } + + case ASTKind::StructDecl: + break; // pass2'de gövde gezme gerekmez + + default: + break; + } + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// walkStmt — ifade bloğunu gez +// ───────────────────────────────────────────────────────────────────────────── + +void SymbolCollector::walkStmt(ASTNode* node) { + if (!node) return; + + switch (node->kind) { + + case ASTKind::Block: { + table_.enterScope(); + for (ASTNode* child : node->getChildren()) walkStmt(child); + table_.exitScope(); + break; + } + + case ASTKind::VariableDecl: { + auto* vd = (VariableDeclNode*)node; + // Önce başlatıcıyı gez (kendini görmesin) + if (vd->initExpr) walkExpr(vd->initExpr); + // Sonra tanımla + Symbol* s = table_.define(vd->name, SymbolKind::Variable, + typeFromName(vd->varType, vd->loc), vd->loc); + if (!s) + diag_.report("E002", vd->loc, + "'" + vd->name + "' zaten bu kapsamda tanımlı"); + // Sibling VariableDecl'ler (int a, b;) — TODO: fibonacci'de yok + for (ASTNode* sib : vd->getChildren()) { + if (sib->kind == ASTKind::VariableDecl) { + auto* sv = (VariableDeclNode*)sib; + if (sv->initExpr) walkExpr(sv->initExpr); + Symbol* ss = table_.define(sv->name, SymbolKind::Variable, + typeFromName(sv->varType, sv->loc), sv->loc); + if (!ss) + diag_.report("E002", sv->loc, + "'" + sv->name + "' zaten bu kapsamda tanımlı"); + } + } + break; + } + + case ASTKind::IfStatement: { + auto* ifn = (IfStatementNode*)node; + if (ifn->condition) walkExpr(ifn->condition); + if (ifn->thenBranch) walkStmt(ifn->thenBranch); + if (ifn->elseBranch) walkStmt(ifn->elseBranch); + break; + } + + case ASTKind::WhileStatement: { + auto* ws = (WhileStatementNode*)node; + if (ws->condition) walkExpr(ws->condition); + if (ws->body) walkStmt(ws->body); + break; + } + + case ASTKind::ForStatement: { + auto* fs = (ForStatementNode*)node; + table_.enterScope(); // init değişkeni döngüye ait + if (fs->init) { + if (fs->init->kind == ASTKind::VariableDecl) walkStmt(fs->init); + else walkExpr(fs->init); + } + if (fs->condition) walkExpr(fs->condition); + if (fs->update) walkExpr(fs->update); + if (fs->body) walkStmt(fs->body); + table_.exitScope(); + break; + } + + case ASTKind::DoWhileStatement: { + auto* dw = (DoWhileStatementNode*)node; + if (dw->body) walkStmt(dw->body); + if (dw->condition) walkExpr(dw->condition); + break; + } + + case ASTKind::ReturnStatement: { + auto* rs = (ReturnStatementNode*)node; + if (rs->value) walkExpr(rs->value); + break; + } + + case ASTKind::ExpressionStatement: { + auto* es = (ExpressionStatementNode*)node; + if (es->expression) walkExpr(es->expression); + break; + } + + case ASTKind::BreakStatement: + case ASTKind::ContinueStatement: + break; // yaprak + + default: + break; + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// walkExpr — ifade ağacında isimleri çöz +// ───────────────────────────────────────────────────────────────────────────── + +void SymbolCollector::walkExpr(ASTNode* node) { + if (!node) return; + + switch (node->kind) { + + case ASTKind::Identifier: { + auto* id = (IdentifierNode*)node; + if (!id->parserToken.token) break; + std::string name = id->parserToken.token->token; + Symbol* s = table_.resolve(name); + if (s) { + id->resolvedSymbol = s; + table_.addReference(s, id->loc); + } else { + diag_.report("E001", id->loc, + "'" + name + "' tanımlı değil"); + } + break; + } + + case ASTKind::BinaryExpression: { + auto* bin = (BinaryExpressionNode*)node; + if (bin->Left) walkExpr(bin->Left); + if (bin->Right) walkExpr(bin->Right); + break; + } + + case ASTKind::Call: { + auto* call = (CallExpressionNode*)node; + if (call->callee) walkExpr(call->callee); + for (ASTNode* arg : call->arguments) walkExpr(arg); + break; + } + + case ASTKind::Postfix: { + auto* pf = (PostfixNode*)node; + if (pf->operand) walkExpr(pf->operand); + break; + } + + case ASTKind::MemberAccess: { + auto* ma = (MemberAccessNode*)node; + if (ma->object) walkExpr(ma->object); // member çözümü Faz 3 → TODO + break; + } + + case ASTKind::IndexExpression: { + auto* ie = (IndexExpressionNode*)node; + if (ie->object) walkExpr(ie->object); + if (ie->index) walkExpr(ie->index); + break; + } + + case ASTKind::Literal: + break; // yaprak + + default: + break; + } +} diff --git a/src/symbol/symbol_collector.hpp b/src/symbol/symbol_collector.hpp new file mode 100644 index 0000000..ec267e3 --- /dev/null +++ b/src/symbol/symbol_collector.hpp @@ -0,0 +1,37 @@ +#ifndef SAQUT_SYMBOL_COLLECTOR +#define SAQUT_SYMBOL_COLLECTOR + +#include +#include +#include +#include "symbol/symbol_table.hpp" +#include "diagnostic/diagnostic_engine.hpp" +#include "core/type.hpp" +#include "core/location.hpp" +#include "parser/ast_node.hpp" + +class SymbolCollector { +public: + SymbolCollector(SymbolTable& t, DiagnosticEngine& d) : table_(t), diag_(d) {} + + // seedBuiltins → pass1 → structCycles(E010) → pass2 + void collect(ASTNode* program); + +private: + void seedBuiltins(); + void pass1Globals(ASTNode* program); + void checkStructCycles(); + void pass2Bodies(ASTNode* program); + void walkStmt(ASTNode* node); + void walkExpr(ASTNode* node); + + Type typeFromName(const std::string& n, const SourceLocation& loc); + + SymbolTable& table_; + DiagnosticEngine& diag_; + + // struct adı → içerdiği struct-tip alan adları (cycle check için) + std::unordered_map> structFields_; +}; + +#endif // SAQUT_SYMBOL_COLLECTOR diff --git a/src/symbol/symbol_table.hpp b/src/symbol/symbol_table.hpp new file mode 100644 index 0000000..8ff6624 --- /dev/null +++ b/src/symbol/symbol_table.hpp @@ -0,0 +1,65 @@ +#ifndef SAQUT_SYMBOL_TABLE +#define SAQUT_SYMBOL_TABLE + +#include +#include +#include "symbol/scope.hpp" + +class SymbolTable { +public: + SymbolTable() { + global_ = newScope(nullptr); + current_ = global_; + } + + Scope* global() { return global_; } + Scope* current() { return current_; } + + Scope* enterScope() { + current_ = newScope(current_); + return current_; + } + + void exitScope() { + if (current_->parent) current_ = current_->parent; + } + + // current scope'ta tanımla; duplicate → nullptr döner + Symbol* define(const std::string& name, SymbolKind k, Type t, SourceLocation loc) { + auto s = std::make_unique(); + s->name = name; + s->kind = k; + s->type = std::move(t); + s->definitionLoc = loc; + Symbol* raw = s.get(); + if (!current_->defineLocal(raw)) return nullptr; // duplicate + pool_.push_back(std::move(s)); + return raw; + } + + Symbol* resolve(const std::string& n) { return current_->resolve(n); } + + void addReference(Symbol* s, SourceLocation loc) { + if (s) s->references.push_back(loc); + } + + std::vector allSymbols() const { + std::vector result; + result.reserve(pool_.size()); + for (const auto& s : pool_) result.push_back(s.get()); + return result; + } + +private: + Scope* newScope(Scope* p) { + scopes_.push_back(std::make_unique(p)); + return scopes_.back().get(); + } + + std::vector> scopes_; + std::vector> pool_; + Scope* global_ = nullptr; + Scope* current_ = nullptr; +}; + +#endif // SAQUT_SYMBOL_TABLE From e223995f204ed20f7d23b87a1eb52738bae9e863 Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Thu, 18 Jun 2026 16:11:34 +0300 Subject: [PATCH 13/28] =?UTF-8?q?feat(symbols):=20JSON=20=C3=A7=C4=B1kt?= =?UTF-8?q?=C4=B1=20+=20syntax=20hata=20tolerans=C4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - symbols komutu artık JSON üretiyor: file, symbols[], diagnostics Her sembol: name, kind, type, typeDetail, definition (file+satır+sütun), references[], isBuiltin — LSP tüketimine hazır format - parser: parseProgram() ilerleme olmayana token atla (guard ekle) Bozuk top-level syntax (ör: `}`, eksik parametre listesi) artık ayrıştırmayı durdurmak yerine sonraki geçerli bildirimi bulmaya devam eder Co-Authored-By: Claude Opus 4.8 --- build/.ninja_deps | Bin 31712 -> 34236 bytes build/.ninja_log | 3 ++ src/cli/commands/symbols.hpp | 98 ++++++++++++++++++++++++----------- src/parser/parser.cpp | 6 ++- 4 files changed, 75 insertions(+), 32 deletions(-) diff --git a/build/.ninja_deps b/build/.ninja_deps index 5664a6a25c82b6df029f6098e9d20704172860ee..3e9c5c6dcc87b42eaedc43f2841fb84104fbc66d 100644 GIT binary patch delta 68 zcmaFxopDb$(}oAtd>JeZ4Ida780;*r-}?;hjOU@L#>n@A9s( X@O3aSH24C=6iqW^|LRSiR8|K7fcqGe delta 9 Qcmdnf&Gg_q +#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 "tools.hpp" + +// ───────────────────────────────────────────────────────────────────────────── +// symbolsToJson — sembol tablosunu JSON olarak serileştir +// ───────────────────────────────────────────────────────────────────────────── + +inline std::string symbolsToJson(const std::string& filePath, + const SymbolTable& table, + const DiagnosticEngine& diag) { + auto symbols = table.allSymbols(); + std::ostringstream ss; + + ss << "{\n"; + ss << " \"file\": \"" << jsonEscape(filePath) << "\",\n"; + ss << " \"symbols\": ["; + + bool firstSym = true; + for (Symbol* s : symbols) { + if (s->isBuiltin) continue; + + if (!firstSym) ss << ","; + firstSym = false; + + ss << "\n {\n"; + ss << " \"name\": \"" << jsonEscape(s->name) << "\",\n"; + ss << " \"kind\": \"" << symbolKindName(s->kind) << "\",\n"; + ss << " \"type\": \"" << jsonEscape(s->type.toString()) << "\",\n"; + ss << " \"typeDetail\": " << s->type.toJson() << ",\n"; + ss << " \"definition\": " << s->definitionLoc.toJson() << ",\n"; + ss << " \"isBuiltin\": " << (s->isBuiltin ? "true" : "false") << ",\n"; + + // referanslar + ss << " \"references\": ["; + bool firstRef = true; + for (const SourceLocation& ref : s->references) { + if (!firstRef) ss << ", "; + firstRef = false; + ss << ref.toJson(); + } + ss << "]\n"; + + ss << " }"; + } + + if (!firstSym) ss << "\n "; + ss << "],\n"; + + // tanılar (diagnostic engine'den hazır JSON al, iç kısmını sar) + ss << " \"diagnostics\": " << diag.toJson() << "\n"; + ss << "}\n"; + + return ss.str(); +} + +// ───────────────────────────────────────────────────────────────────────────── +// cmdSymbols — giriş noktası +// ───────────────────────────────────────────────────────────────────────────── inline int cmdSymbols(const CliArgs& args) { - std::string source = readSource(args); + std::string filePath = inputFilePath(args); + std::string source = readSource(args); if (source.empty()) return 1; Tokenizer tokenizer; - auto tokens = tokenizer.scan(source, inputFilePath(args)); + auto tokens = tokenizer.scan(source, filePath); Parser parser; ASTNode* ast = parser.parse(tokens); if (!ast) { - std::cerr << "Hata: AST üretilemedi\n"; + // AST null olursa boş ama geçerli bir JSON çıktısı üret + DiagnosticEngine diag; + diag.report("E000", SourceLocation{}, "AST üretilemedi"); + SymbolTable empty; + std::cout << symbolsToJson(filePath, empty, diag); for (auto* t : tokens) delete t; return 1; } @@ -33,32 +96,7 @@ inline int cmdSymbols(const CliArgs& args) { DiagnosticEngine diag; SymbolCollector(table, diag).collect(ast); - auto symbols = table.allSymbols(); - - std::cout << "Sembol Tablosu (" << symbols.size() << " sembol):\n"; - std::cout << "────────────────────────────────────────────\n"; - - if (symbols.empty()) { - std::cout << " (sembol bulunamadı)\n"; - } - - for (Symbol* s : symbols) { - if (s->isBuiltin) continue; // builtinleri çıktıda gösterme - std::cout << " [" << symbolKindName(s->kind) << "] " - << s->type.toString() << " " << s->name - << " @" << s->definitionLoc.shortString() - << " refs(" << s->references.size() << "):"; - for (auto& r : s->references) - std::cout << " " << r.shortString(); - std::cout << "\n"; - } - - std::cout << "────────────────────────────────────────────\n"; - - if (diag.hasErrors()) { - std::cerr << "\n"; - diag.printAll(std::cerr); - } + std::cout << symbolsToJson(filePath, table, diag); delete ast; for (auto* t : tokens) delete t; diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp index 398abde..714ef48 100644 --- a/src/parser/parser.cpp +++ b/src/parser/parser.cpp @@ -63,11 +63,13 @@ ASTNode* Parser::parseProgram() { ProgramNode* program = new ProgramNode(); while (currentToken().type != TokenType::SVR_VOID) { + int prevPos = current; ASTNode* decl = parseDeclaration(); if (decl) program->addChild(decl); - else - break; + // İlerleme olmadıysa token atla — syntax hatasında sonsuz döngüyü önler + if (current == prevPos) + nextToken(); } return program; From dc41a5df59bb282bd19bda89eececa8d5b72414c Mon Sep 17 00:00:00 2001 From: abdussamedulutas Date: Thu, 18 Jun 2026 16:21:58 +0300 Subject: [PATCH 14/28] =?UTF-8?q?refactor:=20nlohmann/json=20entegrasyonu?= =?UTF-8?q?=20=E2=80=94=20string=20birle=C5=9Ftirme=20yerine=20nesne=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - src/vendor/nlohmann/json.hpp eklendi (single-header, MIT) - SourceLocation → toJsonObj() + toJson() (nlohmann) - Type → toJsonObj() + toJson() (nlohmann, özyinelemeli) - Diagnostic → toJsonObj() + toJson() (nlohmann) - DiagnosticEngine→ toJsonObj() + toJson() (nlohmann) - symbols.hpp → tamamen nlohmann ile yeniden yazıldı Tüm toJson() imzaları std::string döndürmeye devam eder; AST JsonObject builder'ı dokunulmadı (ayrı katman). Co-Authored-By: Claude Opus 4.8 --- build/.ninja_deps | Bin 34236 -> 59228 bytes build/.ninja_log | 49 +- src/cli/commands/symbols.hpp | 103 +- src/core/location.hpp | 19 +- src/core/type.hpp | 39 +- src/diagnostic/diagnostic.hpp | 21 +- src/diagnostic/diagnostic_engine.hpp | 22 +- src/vendor/nlohmann/json.hpp | 26085 +++++++++++++++++++++++++ 8 files changed, 26204 insertions(+), 134 deletions(-) create mode 100644 src/vendor/nlohmann/json.hpp diff --git a/build/.ninja_deps b/build/.ninja_deps index 3e9c5c6dcc87b42eaedc43f2841fb84104fbc66d..e3f62fafc2edd8aab497471d1385eaffd4eda93f 100644 GIT binary patch literal 59228 zcmeI*2b>c{|M>Bh-fY;gqoAUgL=+Ge=}im$bX#iv#V*}5=XAHGIc$nj+pf!7<5KP1`THz_>}sea2}-1(nE&!iDfvy%Lqoo z9}}*1mhx74m1FZnjF27)gq+f7sI#oj??=S9tQVzmsZVOJcK3(G%T@=~euI%v=}91u zALJ4zr2C7Fu+!xWs`LGR#g4Bi>UXK*doP!L#tzHravQFpcJ~g8IE6+*wAi7C!$v4V zwO9Lj*CI~JdEn^YAx^_A=gx1GXm1n7^7=DI$XQWW;9I%mgM^)C9970|634O*lJLNK4c6~I%p^=DJ0Gd7W?q{ zJrR%YrQZxWy`FI7d5iF+_0?_YawR@Tc*{Bx^?Ql}A)nLZk2nk23GtrI!GtK(2%sJCX>J&-xA(y`nT*B zw-Gi=9vw33lz{hIq$%O(7*(CSCu5paWUeC{v!||d zOCWun3Lg#{E_Hl26DNJ$2}ax@S|YV8yZffhc~QY^VK>9WLR&1jwkc!y#B^E^&PN2&(QVa|myD-$vXxehZ=US$68zhmgBTg&gmg%z+@~rM(i@i}p4T#jthzvT_Ib25EZ0AG8 zHAWaNb{6oLM$@h(Ubb?gmU{ffnzqy;eO0GI#;~Y|`3$E!5RMo!{L+>X&$8Uiou~oZ z;#|V}3|}BLQiWecc*}Bj(KaO9a4pPbA3+X5dVdb$8p3BQBUg#+K+~=!T!ZBEr?%PM z3)oh{F_a!+9%?@E8z!f%3O%+1w#`eI&xH23M8=7-*>ujGC)A=0#5@+xuY*#aeY_tad%o5M*}*QXG^T?LQLOvdh>Od471 zvKdgDM7Wf`D4qy;n8@~q$$3!)xhK#Bi+yb=K(YfSP^|wyl-@%ati>vZd3H3*F6k}nDD zRO5YBewaxAhvMr?? zRe_srztdSn&u88%1ab=7vbluz6E>x;C8W#o$k;#LtZP2Pr<|jN@UB2$sE2wPaK=xR znJF*vQp!NZQwPW#j!&JJq3OaU)EAc#3i&CkA%sgQE49t;_OLB|8y5?}b?HtQMmGbi6;yo6OV1^qIlgl;l2p$(<%A97y?9avNXDqBa zb4foMW{jH9ag(n>#ItOh%f@puFjHgiffjj-M1x+sFKvKDxZ&LN2N*~8&*d0oZjgD! z(&wUK%jH-@Mo~#f zO$Tc|37^9`C@gK(I185&CtKZ?mf7Pk3S5#)+A8yV9%5Wp6-6wC7trp$|EqUL^r~%1C#BzyO+QMZwPAb8*dxrtR@(A&+14;Q52~`o0PJ#MH13SI6MWNfX@IcqgSIzwOwaZ-*=#bMEmjmH7x z#7>x$`X{sbY_qW~r9PPZQ~^%Sn7$;y#5c#;lrSk}lA7;`jMz^hY!1iB!&;sZ#hxCV zoG}j^-w<=5L=(cKw1ug8a5@PuorW`_t2%d5#(1#{m|I{Tdpms|zpZejU*{2lI_49J zSE05e{+NO8SQ0vcbW+MrJsV;=Rvt#Gryk}UYvXizP445&X&I->E9*1NzO7LO;>mdK z_;h(o*dN*CskKwxUK~f*Zq$Wxx25LI33nTmv)^2E)zE6c@hKPfcdSL&(q$WjJ%+F; zbuZy~RCOth;AHiV-F-B1Ec?pXypasjW9v%PT9l)Rn^Gr}_s2s=rqC0kX-DP~kNcq5 zyi@5Q@Q7TFue5`f84681oH!|cOF|yaTQp5;Ksd{Ckb91hUcx042@k0;-kEzGBl7T>7dS*R+TuV_#XO7Y&6B)*!0$UZb4(GrJzUySl}`%cj_NR0+1SKY?4j)6e`UXpW6NK)zX)epZ&e#=c;oB%{v?iN+s0TszFzbX!e?u1 zdA1=-_|zJ>-*d@NVgydgZ^X$~Myei^iK8w*?N{PuYjb5*;upeL9;=iOx3qEv?9Mej ziA#OjMfjY`-^YEO$Bgtdak911EQnFJ`9E2NbNTcLSQw1*n_=CCmpeaOe9BG@ zY`-F2%DE{UPfok`We$1qa~9=U?H3u-^n_iyKj8O}A5#6Ca4F{?dCVdAFXUJ<@tH;V zNT`{kSoisKb6BQ*O89K;n1qkdW5o-_8CziT32{@(Ga+vhw}3~7hIh~Gq+F#R=M*oZ zmyM-q9}zFxbtU^Vyez?IO;vG-;$vqY<`QQ_uuPl}a>$>X0aK{h;H4-Qw7AT|e4lt$ zW$86|2vZm`l8^1Z9OC){g`OghOh)c0RN3>69FCDm&yh~I5n}a`A#vW#;TTmMR?|kg zcT$n4~lFDmgTc7iz%YgV$fb9UP>F8&=$z^G_FhSMZ%Si@5;CKo9K4;3&c;kM={e@<@9{I ze3&QBT<5En&D!11S%vc&s)KnpUATnfiakx&p0Nn$GGAlSo+eyM{>^PF|4&(^!+o_Z zpnEc1I_5T&&J&rpt3K^}D9 z?WCqXK)7sug33#odrzly{;FW^CvGQ>C)4~v#^(l74hc`4?jxOU6-kGeJHyPcgcH)* zMp`NLm+P2|Q>{6@m+h8y#l`b2*Kl?3br0byR6aEHTZwCVo?~SjTV|l$O`L3X%@d&O z@&vWJa!GqwG$3#ATcj0x&sJMUILrDj_pPxAQUGg-lWmN?XRaX@ zDYle*jYYn7|43~$VItMFu^gT@rR2o!(;W9S*oWV%pem}NI%=RMYN0mjpf2iRU+jnd zaR3fPeH?^?aR?5@VQ7HEaRiQpv_nVZ7#xd+I1b075u`qyfD>^Nn&4!df~JuAZ-X5U zNZB^S={N&YZY|IfXF}Skvv4-fL2I0gHfW1>Xpau)h)(E?F6atrgU>^EoR1680~g{V zT#QR_DSF~ET#jDojXvm$e&~+@7>Ge|VlZ?Rz=c9ce^>;T+-p<^&4VEr3NPfl5d4t- zHHcwg$&kh?3R(nF3`Yq@K-L+I!W9^eD{&RZU@XRAJSJcwCSfwBU@E3zI%Z%dW??qw zU@qoiJ{I6=T!V#JgvD5brMMQ$a2=N8dfb2;u>vcx3ahaOYq1XNu>l*g2{++p+=9)x z66G62FIcyj>GY2gvK}lC*mYD!O1uUO>ru0u)~4V&Oe~-&5+UnNC$$8COQW`5O6Q5;rD~R7%_MhRq zQ+T+g20b?tZZv&Le~$6^sqNcHpE7{os}Oe}KL??R-)o>IYN0mjpf2iRU+jndaR3g4 zly$t$U&+6V;l@E2f}!xDCC8Nc+?gogwYirRa&va5;LRH>CZ#21k#-R}oK~tQH zLopr`P#uTiaGZ=&V8cYnbutN)F$GgG4bw3YgW$wq%)~4-M+>yVS!jbU=!)(*9~Ynp zE<_*nML*2O9L&W$%*O&;jcc$Fi?A3=uoTx~8Lq=}T#p-YBUWG~bQIuS?7(|?AD>_w zKE*fq7T@7}?8Fba7eC@B{ET>;BW;khJFEC?HP&D))?qz1pc?FOpczib8R(AzaG?+z zu?aU}Gj7Ee+=kn62kyjOxEot>4?e@^_yS*I7k1+p{EFZ3JO03*_zQnSBj5SHCbzz( zJpD>linbLp_AL?KNcGFtTR2L8i}x`%&~|qsZq9v7X$oc2x_)n@L!YypblO!SKeD|0 zI?|X(f8?aTHD5a{FrEHrFuzwJU7eo>KZ{TUHBk$-Q3rKV5Bp+2?2iL*Ad2C}LGWM* zhQf=MI2-5SO!(kO06`2x2w}9wxi}a{;7Bw)Jra4Z_)I2?}%q8N@6 z)W-;n#3)>W(YO*0lQ0=m zFcs4<9WyWxgW$wq%)~4-M+->ZJqvBn0UaTAvNO7%E4t%+T!0?95EtQMT!Kr{6PMv~ z^g?g+L0|O4Y|O!2%)@*vz}2`03$X}`u>?zTEtcUrEXVb@0XJd=RzgPsR$(>PU@g`m zKK@A@%Y4A+AL1k2jE`|2?#Bao5D(#DY{w&b6p!I?Jb@?i6rRR2coxs$dAxuZ@e*Ff zD|i*J;dQ)$H}MwU#yhwL?_vku!~6II+wdvA!MFGh-(x3!z`ghpKjCL2_fzZnYy+yn z4hNdybew_y7yuUvu@Rea6E@>kY{6}~9e3bP+=aWb75CsXe2y>hC3ayqe!;K!4Zq_L z{E5HtH}ZW_?)N|C?UM@jvAE|^^Z6l%`NQmymX){tPf3GowsL8x7lf9QMklIA&i!JU ze8iS}@uty|3g$(1v$1!T7L!Kn3gksS3?mPVDwqf2^I)Tp=d8it!t&-peK)BrQ8W+Y z8sfJq&oM*-0WVLzE+(xGknu=IbcT#eE=5mVhRe|ly&>b3i;!u|Vz4cOD2Ag1^)VLX&^04j>B*`PR1#)VIoe$BuvH>OvN-z$3P5%6N51mv(OwZAnn{)XoD{3itb1r zzxLs?zUYV9n1i{Phxu55t8on$Vi6W&36|noEW>qJj_Yv)Zo~?#gpLBdiyhdTW4m;7 zu*FG?vj9g*m1< z=N$a9%!Nnzy$b2d@k@E+`=Webl<$l7ZeJwN=cJ8F*S}PzU&+>&{oDJTbp8K7*$?IV zoK^Z88HdEj6;)|_WiCScpeW>CI=8+i;l3sIw>73!s=q0l-qcuMF`PU-xuw>R(pQx5 zyYv;(FXsD-{Ik>ieaqgzZ^`!+|NHB8{_}lB;=GjESxljQulQVJQhM|WlVknG2>OOy zk4$=8`iqgV{zC4d^8H1=zsUC&`TpWh+KRuBf4<3D2inE<=zxysgw9A_-?_K?i`?h2 z;?GyizG70P?kf_~;=E6c^%J8w&en~)e<%IK75pyu6*A|R?@3F7zE^w>Dk(kgAI8S|i>v4xs(#U_nyj@N6YDSJnSQ>%$oCid{vzLB zN3;jiz^~|cn7*nbKA~`+Q`NaB*vGfh~T_=1a_ZQ=0{e`Rr%l8-g{vzLBYdkaMSAB%*cEM-M%$Z{HS?-IOLLe zd|^0WDC;i_J3{g$w5p7w<;{a9rKJ)(sPXIU;jzGYBNQ}Xu? zD|Kw@EjsmX)v!vX6MvJA=Vzo-uJaUM7*1UX5Vu_Kv6VSb;gPS?ZZC!UTg5P!8#^Hwwsbwp*uIhTunD<-7r}Jm#Mhjc z_nm`(>w9bepfU%=pe%DcnzEn9p(GBd%8lAX7)f)^5=Z)u?IAR&()Yj#;Q4dKR3||4Ena7#4RLl z)@RX~`q|jCXczI1O3W+!=c~OL1>3^`J}*elGuwS^()qkWQat(G-ja7})1>L+FI>px zX2fx(iCgUA50VpLP@1^$Z4!AP+vPpo(z0cvBi&%WSxb8}dow9cLfG{I#48=&N*N>e z=i2nJ-!KaKGi-9e{nP9}_P2FZdGup@nR81za$tS=Jh?p70aG4**w!#H&k{$za@zd+ zLUx^Py$Mq`e}y*nXAEr|oQ*#^NZFlExL$-SXIx^$vYLv&z8&hocE*0 zE~XyuT(Nt#jAxec`%+vB`Ja3@pp19qxsl8T${J>Q??u+A$-9!W{y^T}Uk3T!rt7dA z*W(7-tfP}_*WhOn zYM>@+p*HHEF65ft7yDs<9DoB+3^xvf2SYFvUU0he-y=mCOaXPO^qu<|{5}wakjs1b z9SGMEG8fPp+1|syi0yK}a0xPf4?!Qc{ioj5-^{*l#TF!g@6jqgOMZV|`jpT3{0w}K zFYqP4!q@l!AL1k2jE`|2?#Bao5D(#DY{w&b6p!I?Jb@?i6rRR2coxs$dAxuZ@e*Ff zD|i*J;dQ)$H}MwU#yhwL?_vik^PL2{h`$@ZU=x1DZ%FrDPXqW|qpS+~5$}VC@b3-$ zyBh3ppc$mC><NLoewUIR5z3$;-Pbx{xL+HpCi_%(JVVT$2~wCh7K6kb%MP5*#+ zCqS;-lMuglXYhMtoQMXH{`g~fa0HG-6UdnCXdHuM(GbVsc#ObEjKUQdjjJ#QZP5rs?#du6WbsUDnaWYPU4HI!1CSfwBU@E3zItF48oEVImn1$wOfmS#RZO{c>(H-aG z0`$Oz=!3rKhuN5extNFfSb(c>4HjY%7GnvP;#w@jby$w;aRY9|3ao^V0=$bIcn|O6 z6Kun$_y*tNJA99w_yPCgNBo4J5x=(OT9@m46`!rf8mz@Stj7jaLvmYt2A}oE0JuhxC3|MF5Hc+xCfu%b9{j>u?xHL3x36K_#J=XPyB_yA$>!>O}Bnm zM%wi9wBJ=J+W6m`c;JDL?w9tLBvkt=+oV2JM-9|OE!0LG)I~k)i~X=a4#0tsYxy7? zj6)#TuUxYYa5#>@kvIxR;}{%^hByw#qY)b81e}PI&;%#r6vW#G8^6cv>}mYo45vft zZF96hOPq;TI16Xv9JI!{XoI$BhxX`zj_8EW=z^~3hV#%J$?bx)cNgOlT#BB!440!9 zdZQ2eq95Yd)Ife81SbYVhg|zE$hBsm2*q&2gCQ6SFMRMLfFOn;gfJqAVmL}L0wXaB zS70=*#8nuBu^5N(n1G3xgvpqKshEc8n1Pv?h1r;cxtNFfSb(c>4HjY%7GnvP;#w@j zby$w;aRY9|3arE`ti~Fw#X79V25dyU4Z4}%Z^35ViY>Sex8n}niMwz&w&EV#i*2|M z_u~OPh==enw&M{zipTIcp1_lM3Qyx1Jd5Y>JYK+ycnL4#6}*bq@H*bWn|KRv;~l(< z9e5A#;{$w%kMJ=*!Ke5PpW_RBiLdZAzQMQn4&P%Ze!!3T2|r^OcH$(Vwvn1<;Xh(T~-FlIv9?dE8KRyYf7&;?!59p~c$^uUGa zgTCm8*_ea5n1}gTfU9v07Ge<=V+ocbmo{G~Tmh2X#ZUN5+G}YGGqrirrYE+0$z$L6 z_-Ga3R$~p;Vjb3F1FFFe2b$q@oPqur02d0e5u0!mHse-o!ELx5ci>Lkg}bp8_aM0) z-^FLU@e6)MzHP4D-vi2Z?qUdSZ@PI3na7atqKbc4;2RxVtd#aS|6PIk_IVuFXTE*T zx6k>pGxyH4k>{cf+M*rWqXRmk6VlB)@6GmEo>BI_eZdB4pYz|Nk#C>J<=f}d`J?>! zIX}1Y-)^6;qJ2KhziEfG&tv$#3fHGR_lrL#EaKlaP!qLK8+A|@^{_AY!~Qq`2O|G$ zFF(IAg?f;m-$;G7m!IGG-(R<}H^yXnP`Qxa5m0CMV}GI=dp5~>!`}OxPbk+A!B1%+ac>X65lzIdFLR8LEb-+ z^&O-6xwFB;jimj)lHX-~E$^q~$JhDsb$)!EA7B4Tdyron{oh&N5&s^ZubzLnt+dY* zV(oK&T%8|RpUQQaUl+ai-U*z@wKWN{UTZR@U@GF{uykYSX>2d=8tCc7sp!}{zkZta z=#<~-*jr=oAy zB$}WxPQZyc2@P-*j>a)K77cM6jz~A z;|08km+&%P!K-);uj388iMQ}J-oY(+7d!AC-p41{hEMSgzQuR=9y{>^?!}Mz2|pwG z9h%C_nQSJ#Td@VV;db1CJ8>88M!ucj`|Z5+>&b0>yl*dWoBs&y@G{c7^W&q(OFO)Y z->Y!mq^&miS%ey>iCU-)t2KSagvqzV<$I^^-_#CgYd6xh(K3ekj5>7&KF1gM5?|qK ze1QMe_Iek`wi~}-6Mn^S_#J=XPyB_yF#sB6RmhL{m`mnPH}LOju)~37I34}r!baSL zI__V%$SH^g?g+L0|NP^uh6Q zvCMPF=c{EL9>2e;N*I|F_d?c;$h>w4G7mlsQ+efhF+X44`u$vK$CvQ?Qd|r9Uw?j% zhpge2bttk{a5&_hn=oYVT%LbQUm)Z1>#!Wx;|AP_6LpfKUN5*gHEeXa{u;kMiisOz6H;l^wgtVBU>!Dq5H zP>bjF77S55vj?Y?8>MobCB!k*x4_v~3c-n2X`eTyV1i zVtpY}cL)7#UTVrCZ!^F}u}nZmW;}k|76(qTCfBHN#HI%a3mD$EX~52wC1mL#7Xw-O zJc~{a3g&#srg{Nnp^$CH6In{$MuD%I2|TK^b&yGIxnM;hrvNM@3wSnN0U214mWkiZ zQA0XT308bFR{?^!@eW6puo1=y z2N1rlhl3byZAMFd0-hd{@|C2o$M8^f;wq9JAWRY#6P6H8VW7&$pC+je#}*sM^VVho zmJhGN(2xP5uwq3n6ta`mSYzaMw93lE$)g4hme)$twAAt% z`E!NF?c8;wmrkkSD#^^BYuxw`-tUyWFfauC9;%CzNUn1@xq2?Ip^oJU59Z^shG;Bp zh~{JO*C?Isem}>l*~AemEvQgPwn#feoD$FI7UHQw9u$w@vyvhqo_#?F5)_1d9;ojkbjJwz zEg=~=vBx1n!%yE~`fW`Mux#50^T;nNBh>31D~S1z@qKx^aXm_n*AYm#comeOQJ>_}z*UmWxZI_KE0HDgm>L~}+g)0?j2;@*9Iw!Hv~_fKZ*HdB zj@@0CaCdJW${Uq%5#3EoV#FQfK1NSt9bCY%#%lNo>$fbA=szS)3GR3>7XF62y;V}O z{wtZ5;9;K%onMQ#{)Lv-F6Fjg?jqQy{A09Lo;3Cm3qp5bUCj_51%!zEzQLX~1!t zh8u7C$u|?p%r`wN317W$d=yP9#fhL%!IKnC$mcM&B~5aN!+oJN^~1EhMAEiWc?-ve z^>}=RHg1|~9BF4F!p^xK`<|A`uT#SuYB8h7TLx!opR28BBCZRhmmb{m8FM|IWafGb zD+#mAbqD2iJbWN#w_-!Q_5DZ)GRW0pVeM@e0!t(Wsk1QzN4tvQJ@LF>>QZLWM!y@0 zfR()MQf;`!B9Ix0fN?fPz~gn`wMHeTJ{kk>P$a6d=vjR`5(OK1JSEd}0g6IaBnnBh zF$!^8%HU7*2Gm*q7;!zD+{`Z8JIxXxC*nFiv$O9OsCc{#{(##aud}`taXpvZT=IJ5 zr_6PG#C5}LbUm;=7k)2tgOl5pe3;x{gy)GVsGm^6X-0+Q>mqddl*nA3TBL+YtaxG> ze^Ru)`DNOr@Py;nXa2( zvtFteUuP?QoiN_?D~#(cQFix;k1-kiQXFiA20JcxeALtJ^AOSe1$A`68zL=AE!JT| zZzUWP`_gNEm!fh%r@qDTGn^pqrjAnb9Ueb-R9t3>TM0)*se`1~X>nPq4*D$gkqNEh zFx>+bg+3!3!az+PuI;+G4oJB=oWKX(0;;YC-|vBcZgULK2Gz z3kfr%;U10R8ELqI!qY}PwnEAS*+_6(WdtE?(&4|)PUAu3-X&l9M0^#r?J z8+|RV25)!B?d%%E)B!z=qG#7!MN8XyUuOf6vHchrD1&`CHeiAg43oiLyf|Qlmr0{T z!=NhlB^u6f|8O+qdat)R=nQu4!HPi>`~*FN1@L2hYS0G5I6;~rJU^(17xC7h5njN= zT^aB^7VWaZZkoIpp2KH$=~w@V#@)_wTWiS~pQ~TaF8Y-u*AZ3`*pGb?vJGT6BD)$G zIba-#J&}wivPXhZ;d&~s5G$+6OnivMhY3xDM+nV?Z(zlf)v3?Ygj*>in6dlCzPIMl zgdUO^$yzb)seMR7%q@lS*g4BceV6HRTnx!Ff*kPKp^xynkiGVP%2!2A%L$Aevi+*2 zavzl+6D|^JsLtq~Na3h{iEx=9(n`{cluu= CVVxfU diff --git a/build/.ninja_log b/build/.ninja_log index 47d2e73..ea7a311 100644 --- a/build/.ninja_log +++ b/build/.ninja_log @@ -1,20 +1,31 @@ # ninja log v7 -1 2432 1781560000479022647 CMakeFiles/saqut.dir/src/core/sourcefile.cpp.o da6f5fc90e87e6b1 -1 1218 1781560000479623743 CMakeFiles/saqut.dir/src/lexer/lexer.cpp.o 90eeec811f2137e6 -2433 3980 1781560002911027568 CMakeFiles/saqut.dir/src/tokenizer/tokenizer.cpp.o a01677f8bb4f4dbc -1 1408 1781786522326465778 CMakeFiles/saqut.dir/src/parser/parser.cpp.o 2c65b7be26cead32 -1 2454 1781786563274205322 CMakeFiles/saqut.dir/src/parser/nodes/program.cpp.o ac5bbcd74d87561a -1 2570 1781786563274005192 CMakeFiles/saqut.dir/src/parser/nodes/identifier.cpp.o eb96bb4b1eb4ad80 -1 2619 1781786563273914998 CMakeFiles/saqut.dir/src/parser/nodes/expressions.cpp.o 4057e3d63c63a1ab -1 2552 1781786563274095617 CMakeFiles/saqut.dir/src/parser/nodes/literal.cpp.o 78f2c4da7c9b2281 -1 2664 1781786563274315492 CMakeFiles/saqut.dir/src/parser/nodes/statements.cpp.o b5c20724bbf3648c -1 2656 1781786563273513379 CMakeFiles/saqut.dir/src/parser/nodes/binary_expr.cpp.o d2e2bb2f8a63c6d2 -1 2517 1781786563273824541 CMakeFiles/saqut.dir/src/parser/nodes/declarations.cpp.o b6c56f04a257f685 -1 2736 1781786295699197219 CMakeFiles/saqut.dir/src/main.cpp.o 110c26cb1d0c3a23 -2664 2825 1781786565936516467 saqut 8525928b86934b0a -0 22 1781786586571540360 build.ninja 1876a59d627a585 -0 22 1781786586571540360 /home/saqut/Masaüstü/saqutcompiler/build/cmake_install.cmake 1876a59d627a585 -1 2086 1781786305407208932 CMakeFiles/saqut.dir/src/symbol/symbol_collector.cpp.o 3348f498f369213d -10 1265 1781788264862998611 CMakeFiles/saqut.dir/src/parser/parser.cpp.o 2c65b7be26cead32 -10 2216 1781788264862423222 CMakeFiles/saqut.dir/src/main.cpp.o 110c26cb1d0c3a23 -2216 2383 1781788267068424572 saqut 8525928b86934b0a +0 5993 1781788863286900733 CMakeFiles/saqut.dir/src/core/sourcefile.cpp.o da6f5fc90e87e6b1 +1 5798 1781788863287900734 CMakeFiles/saqut.dir/src/lexer/lexer.cpp.o 90eeec811f2137e6 +8108 10913 1781788871394910212 CMakeFiles/saqut.dir/src/tokenizer/tokenizer.cpp.o a01677f8bb4f4dbc +5798 10663 1781788869086425023 CMakeFiles/saqut.dir/src/parser/parser.cpp.o 2c65b7be26cead32 +5 8301 1781788863292536727 CMakeFiles/saqut.dir/src/parser/nodes/program.cpp.o ac5bbcd74d87561a +3 8830 1781788863290580789 CMakeFiles/saqut.dir/src/parser/nodes/identifier.cpp.o eb96bb4b1eb4ad80 +2 8108 1781788863290412878 CMakeFiles/saqut.dir/src/parser/nodes/expressions.cpp.o 4057e3d63c63a1ab +3 8768 1781788863290742048 CMakeFiles/saqut.dir/src/parser/nodes/literal.cpp.o 78f2c4da7c9b2281 +8 8333 1781788863295900743 CMakeFiles/saqut.dir/src/parser/nodes/statements.cpp.o b5c20724bbf3648c +1 9121 1781788863288931744 CMakeFiles/saqut.dir/src/parser/nodes/binary_expr.cpp.o d2e2bb2f8a63c6d2 +1 8732 1781788863289045597 CMakeFiles/saqut.dir/src/parser/nodes/declarations.cpp.o b6c56f04a257f685 +1 10559 1781788863288812886 CMakeFiles/saqut.dir/src/main.cpp.o 110c26cb1d0c3a23 +11577 11832 1781788874863914253 saqut 8525928b86934b0a +0 22 1781788881496630820 build.ninja 1876a59d627a585 +0 22 1781788881495921955 /home/saqut/Masaüstü/saqutcompiler/build/cmake_install.cmake 1876a59d627a585 +5993 11577 1781788869279907744 CMakeFiles/saqut.dir/src/symbol/symbol_collector.cpp.o 3348f498f369213d +1 3694 1781788886610186419 CMakeFiles/saqut.dir/src/lexer/lexer.cpp.o 90eeec811f2137e6 +1 6106 1781788886608927872 CMakeFiles/saqut.dir/src/core/sourcefile.cpp.o da6f5fc90e87e6b1 +3 8929 1781788886610927874 CMakeFiles/saqut.dir/src/parser/nodes/identifier.cpp.o eb96bb4b1eb4ad80 +3 9947 1781788886611876031 CMakeFiles/saqut.dir/src/parser/nodes/program.cpp.o ac5bbcd74d87561a +3 10066 1781788886611770636 CMakeFiles/saqut.dir/src/parser/nodes/literal.cpp.o 78f2c4da7c9b2281 +1 10950 1781788886610366872 CMakeFiles/saqut.dir/src/parser/nodes/binary_expr.cpp.o d2e2bb2f8a63c6d2 +2 11212 1781788886610587227 CMakeFiles/saqut.dir/src/parser/nodes/expressions.cpp.o 4057e3d63c63a1ab +1 11244 1781788886610473997 CMakeFiles/saqut.dir/src/parser/nodes/declarations.cpp.o b6c56f04a257f685 +3694 11807 1781788890301932134 CMakeFiles/saqut.dir/src/parser/parser.cpp.o 2c65b7be26cead32 +7 12109 1781788886614927879 CMakeFiles/saqut.dir/src/parser/nodes/statements.cpp.o b5c20724bbf3648c +1 12570 1781788886610272711 CMakeFiles/saqut.dir/src/main.cpp.o 110c26cb1d0c3a23 +8929 12696 1781788895536938159 CMakeFiles/saqut.dir/src/tokenizer/tokenizer.cpp.o a01677f8bb4f4dbc +6106 13677 1781788892713934912 CMakeFiles/saqut.dir/src/symbol/symbol_collector.cpp.o 3348f498f369213d +13677 13929 1781788900284943608 saqut 8525928b86934b0a diff --git a/src/cli/commands/symbols.hpp b/src/cli/commands/symbols.hpp index 431a7a3..b875ce9 100644 --- a/src/cli/commands/symbols.hpp +++ b/src/cli/commands/symbols.hpp @@ -6,70 +6,13 @@ #define SAQUT_CLI_SYMBOLS #include -#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 "tools.hpp" - -// ───────────────────────────────────────────────────────────────────────────── -// symbolsToJson — sembol tablosunu JSON olarak serileştir -// ───────────────────────────────────────────────────────────────────────────── - -inline std::string symbolsToJson(const std::string& filePath, - const SymbolTable& table, - const DiagnosticEngine& diag) { - auto symbols = table.allSymbols(); - std::ostringstream ss; - - ss << "{\n"; - ss << " \"file\": \"" << jsonEscape(filePath) << "\",\n"; - ss << " \"symbols\": ["; - - bool firstSym = true; - for (Symbol* s : symbols) { - if (s->isBuiltin) continue; - - if (!firstSym) ss << ","; - firstSym = false; - - ss << "\n {\n"; - ss << " \"name\": \"" << jsonEscape(s->name) << "\",\n"; - ss << " \"kind\": \"" << symbolKindName(s->kind) << "\",\n"; - ss << " \"type\": \"" << jsonEscape(s->type.toString()) << "\",\n"; - ss << " \"typeDetail\": " << s->type.toJson() << ",\n"; - ss << " \"definition\": " << s->definitionLoc.toJson() << ",\n"; - ss << " \"isBuiltin\": " << (s->isBuiltin ? "true" : "false") << ",\n"; - - // referanslar - ss << " \"references\": ["; - bool firstRef = true; - for (const SourceLocation& ref : s->references) { - if (!firstRef) ss << ", "; - firstRef = false; - ss << ref.toJson(); - } - ss << "]\n"; - - ss << " }"; - } - - if (!firstSym) ss << "\n "; - ss << "],\n"; - - // tanılar (diagnostic engine'den hazır JSON al, iç kısmını sar) - ss << " \"diagnostics\": " << diag.toJson() << "\n"; - ss << "}\n"; - - return ss.str(); -} - -// ───────────────────────────────────────────────────────────────────────────── -// cmdSymbols — giriş noktası -// ───────────────────────────────────────────────────────────────────────────── +#include "vendor/nlohmann/json.hpp" inline int cmdSymbols(const CliArgs& args) { std::string filePath = inputFilePath(args); @@ -82,21 +25,41 @@ inline int cmdSymbols(const CliArgs& args) { Parser parser; ASTNode* ast = parser.parse(tokens); - if (!ast) { - // AST null olursa boş ama geçerli bir JSON çıktısı üret - DiagnosticEngine diag; - diag.report("E000", SourceLocation{}, "AST üretilemedi"); - SymbolTable empty; - std::cout << symbolsToJson(filePath, empty, diag); - for (auto* t : tokens) delete t; - return 1; - } - SymbolTable table; DiagnosticEngine diag; - SymbolCollector(table, diag).collect(ast); - std::cout << symbolsToJson(filePath, table, diag); + if (ast) { + SymbolCollector(table, diag).collect(ast); + } else { + diag.report("E000", SourceLocation{}, "AST üretilemedi"); + } + + // ── JSON çıktı ────────────────────────────────────────────────────────── + nlohmann::json out; + out["file"] = filePath; + + nlohmann::json symArray = nlohmann::json::array(); + for (Symbol* s : table.allSymbols()) { + if (s->isBuiltin) continue; + + nlohmann::json refs = nlohmann::json::array(); + for (const SourceLocation& r : s->references) + refs.push_back(r.toJsonObj()); + + symArray.push_back({ + {"name", s->name}, + {"kind", symbolKindName(s->kind)}, + {"type", s->type.toString()}, + {"typeDetail", s->type.toJsonObj()}, + {"definition", s->definitionLoc.toJsonObj()}, + {"references", refs}, + {"isBuiltin", s->isBuiltin} + }); + } + out["symbols"] = symArray; + out["diagnostics"] = diag.toJsonObj(); + + std::cout << out.dump(2) << "\n"; delete ast; for (auto* t : tokens) delete t; diff --git a/src/core/location.hpp b/src/core/location.hpp index e8b4ff0..13a2573 100644 --- a/src/core/location.hpp +++ b/src/core/location.hpp @@ -22,6 +22,7 @@ #define SAQUT_CORE_LOCATION #include +#include "vendor/nlohmann/json.hpp" // ============================================================================ // SourceLocation — Kaynak Koddaki Bir Nokta @@ -66,15 +67,17 @@ struct SourceLocation { } // JSON formatı: {"file":"...","line":5,"column":10,"offset":134} - std::string toJson() const { - if (!isValid()) return "null"; - return "{" - "\"file\":\"" + filePath + "\"," - "\"line\":" + std::to_string(line) + "," - "\"column\":" + std::to_string(column) + "," - "\"offset\":" + std::to_string(offset) + - "}"; + nlohmann::json toJsonObj() const { + if (!isValid()) return nullptr; + return { + {"file", filePath}, + {"line", line}, + {"column", column}, + {"offset", offset} + }; } + + std::string toJson() const { return toJsonObj().dump(); } }; #endif // SAQUT_CORE_LOCATION diff --git a/src/core/type.hpp b/src/core/type.hpp index 260a129..d8e07af 100644 --- a/src/core/type.hpp +++ b/src/core/type.hpp @@ -34,6 +34,7 @@ #include #include #include +#include "vendor/nlohmann/json.hpp" // ============================================================================ // Enum'lar @@ -220,31 +221,37 @@ struct Type { // ------------------------------------------------------------------ // // toJson — Makine-okur (cam ilkesi: her tip dışarıdan sorgulanabilir) // ------------------------------------------------------------------ // - std::string toJson() const { + nlohmann::json toJsonObj() const { + nlohmann::json j; switch (kind) { case TypeKind::Primitive: - return std::string("{\"kind\":\"primitive\",\"name\":\"") + primName(prim) + "\"}"; + j["kind"] = "primitive"; + j["name"] = primName(prim); + break; case TypeKind::Array: - return std::string("{\"kind\":\"array\",\"element\":") + - (elementType ? elementType->toJson() : "null") + "}"; + j["kind"] = "array"; + j["element"] = elementType ? elementType->toJsonObj() : nullptr; + break; case TypeKind::Struct: - return "{\"kind\":\"struct\",\"name\":\"" + structName + "\"}"; + j["kind"] = "struct"; + j["name"] = structName; + break; case TypeKind::Function: { - std::string s = "{\"kind\":\"function\",\"returns\":"; - s += returnType ? returnType->toJson() : "null"; - s += ",\"params\":["; - for (size_t i = 0; i < paramTypes.size(); ++i) { - if (i) s += ","; - s += paramTypes[i].toJson(); - } - s += "]}"; - return s; + j["kind"] = "function"; + j["returns"] = returnType ? returnType->toJsonObj() : nullptr; + nlohmann::json params = nlohmann::json::array(); + for (const auto& p : paramTypes) params.push_back(p.toJsonObj()); + j["params"] = params; + break; } case TypeKind::Error: - return "{\"kind\":\"error\"}"; + j["kind"] = "error"; + break; } - return "null"; + return j; } + + std::string toJson() const { return toJsonObj().dump(); } }; #endif // SAQUT_CORE_TYPE diff --git a/src/diagnostic/diagnostic.hpp b/src/diagnostic/diagnostic.hpp index c9e3e9a..5e9a3e8 100644 --- a/src/diagnostic/diagnostic.hpp +++ b/src/diagnostic/diagnostic.hpp @@ -85,18 +85,17 @@ struct Diagnostic { 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; + nlohmann::json toJsonObj() const { + nlohmann::json j; + j["level"] = diagLevelName(level); + j["code"] = code; + j["location"] = loc.toJsonObj(); + j["message"] = message; + if (!hint.empty()) j["hint"] = hint; + return j; } + + std::string toJson() const { return toJsonObj().dump(); } }; // ============================================================================ diff --git a/src/diagnostic/diagnostic_engine.hpp b/src/diagnostic/diagnostic_engine.hpp index baa7a10..223f57c 100644 --- a/src/diagnostic/diagnostic_engine.hpp +++ b/src/diagnostic/diagnostic_engine.hpp @@ -25,6 +25,7 @@ #include #include #include "diagnostic/diagnostic.hpp" +#include "vendor/nlohmann/json.hpp" // ============================================================================ // DiagnosticEngine @@ -88,18 +89,19 @@ public: } // --- Makine-okur çıktı --- - std::string toJson() const { - std::string s = "{\"diagnostics\":["; - for (size_t i = 0; i < diagnostics_.size(); ++i) { - if (i) s += ","; - s += diagnostics_[i].toJson(); - } - s += "],\"errorCount\":" + std::to_string(errorCount()); - s += ",\"warningCount\":" + std::to_string(warningCount()); - s += "}"; - return s; + nlohmann::json toJsonObj() const { + nlohmann::json items = nlohmann::json::array(); + for (const auto& d : diagnostics_) + items.push_back(d.toJsonObj()); + return { + {"diagnostics", items}, + {"errorCount", errorCount()}, + {"warningCount", warningCount()} + }; } + std::string toJson() const { return toJsonObj().dump(); } + private: std::vector diagnostics_; diff --git a/src/vendor/nlohmann/json.hpp b/src/vendor/nlohmann/json.hpp new file mode 100644 index 0000000..dec4811 --- /dev/null +++ b/src/vendor/nlohmann/json.hpp @@ -0,0 +1,26085 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + +/****************************************************************************\ + * Note on documentation: The source files contain links to the online * + * documentation of the public API at https://json.nlohmann.me. This URL * + * contains the most recent documentation and should also be applicable to * + * previous versions; documentation for deprecated functions is not * + * removed, but marked deprecated. See "Generate documentation" section in * + * file docs/README.md. * +\****************************************************************************/ + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +// Workaround for GCC template redefinition errors in C++ modules +// When nlohmann/json.hpp is included in a C++20 module preamble after +// other module imports, GCC may report spurious redefinition errors for +// STL templates. These pragmas suppress those false positives. +// See: https://github.com/nlohmann/json/issues/5103 +#if defined(__GNUC__) && !defined(__clang__) && __cplusplus >= 202002L + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wignored-attributes" +#endif + +#include // all_of, find, for_each +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO +#include // random_access_iterator_tag +#include // unique_ptr +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 12 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_DIAGNOSTIC_POSITIONS + #define JSON_DIAGNOSTIC_POSITIONS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_DIAGNOSTIC_POSITIONS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION + #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#endif + +// Construct the namespace ABI tags component +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) + +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT( \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS) + +// Construct the namespace version component +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ + _v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) + +#if NLOHMANN_JSON_NAMESPACE_NO_VERSION +#define NLOHMANN_JSON_NAMESPACE_VERSION +#else +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH) +#endif + +// Combine namespace components +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ + NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) + +#ifndef NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann +#endif + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // transform +#include // array +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // nullptr_t +#include // exception +#if JSON_DIAGNOSTICS + #include // accumulate +#endif +#include // runtime_error +#include // to_string +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // uint8_t +#include // string + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // declval, pair +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// https://en.cppreference.com/w/cpp/experimental/is_detected +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template class Op, class... Args> +using is_detected = typename detector::value_t; + +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + + +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson +// SPDX-License-Identifier: MIT + +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + * SPDX-License-Identifier: CC0-1.0 + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 15 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_CONCAT3_EX) + #undef JSON_HEDLEY_CONCAT3_EX +#endif +#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c + +#if defined(JSON_HEDLEY_CONCAT3) + #undef JSON_HEDLEY_CONCAT3 +#endif +#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(JSON_HEDLEY_MSVC_VERSION) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) + #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if \ + defined(__TI_COMPILER_VERSION__) && \ + ( \ + defined(__TMS470__) || defined(__TI_ARM__) || \ + defined(__MSP430__) || \ + defined(__TMS320C2000__) \ + ) +#if (__TI_COMPILER_VERSION__ >= 16000000) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #undef JSON_HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) + #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #undef JSON_HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) + #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #undef JSON_HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) + #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) + #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #undef JSON_HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) + #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #undef JSON_HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) + #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #undef JSON_HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) + #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) + #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) + #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ + !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") +# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# endif +#endif +#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ + ((T) (expr)) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) +# endif +#else +# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(JSON_HEDLEY_ASSUME) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif +#if !defined(JSON_HEDLEY_ASSUME) + #if defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) + #else + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) + #endif +#endif +#if defined(JSON_HEDLEY_UNREACHABLE) + #if \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) + #else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() + #endif +#else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ + ) +# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +# define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ + ) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC __declspec(dllexport) +# define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else +# if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + ( \ + defined(__TI_EABI__) && \ + ( \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ + ) \ + ) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +# else +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC +# endif +# define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + ( \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ + defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ + defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ + defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ + defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else + #define JSON_HEDLEY_FLAGS +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if \ + (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + + +// This file contains all internal macro definitions (except those affecting ABI) +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// #include + + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +// if the user manually specified the used C++ version, this is skipped +#if !defined(JSON_HAS_CPP_26) && !defined(JSON_HAS_CPP_23) && !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus > 202302L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202302L) + #define JSON_HAS_CPP_26 + #define JSON_HAS_CPP_23 + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus > 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L) + #define JSON_HAS_CPP_23 + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus > 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus > 201402L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus > 201103L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 +#endif + +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + +#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) + #ifdef JSON_HAS_CPP_17 + #if defined(__cpp_lib_filesystem) + #define JSON_HAS_FILESYSTEM 1 + #elif defined(__cpp_lib_experimental_filesystem) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif !defined(__has_include) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #endif + + // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ + #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__clang_major__) && __clang_major__ < 7 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support + #if defined(_MSC_VER) && _MSC_VER < 1914 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before iOS 13 + #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before macOS Catalina + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + #endif +#endif + +#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_FILESYSTEM + #define JSON_HAS_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#endif + +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has a syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifndef JSON_HAS_STATIC_RTTI + #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 + #define JSON_HAS_STATIC_RTTI 1 + #else + #define JSON_HAS_STATIC_RTTI 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE +#endif + +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#endif + +// allow disabling exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// allow overriding assert +#if !defined(JSON_ASSERT) + #include // assert + #define JSON_ASSERT(x) assert(x) +#endif + +// allow accessing some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + + + +/*! +@brief function to wrap JSON_THROW_MACRO - there can be compilation errors about + there being no arguments to JSON_THROW that depend on template arguments + if this is not used to call JSON_THROW +*/ +template +void templated_json_throw(ExceptionType exception) +{ + JSON_THROW(exception); + + /* JSON_THROW(exception) discards exception and aborts - void cast needed to supress + compilation error if compiled with -Werror and Wunused-parameter */ + (void)exception; +} + +/*! +@brief macro to briefly define a mapping between an enum and JSON with exception + on invalid input +@def NLOHMANN_JSON_SERIALIZE_ENUM_STRICT +@since version 3.12.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + if (it != std::end(m)) j = it->second; \ + else templated_json_throw(nlohmann::detail::out_of_range::create(410,"enum value out of range for " #ENUM_TYPE, nullptr)); \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + if (it != std::end(m)) e = it->first; \ + else templated_json_throw(nlohmann::detail::out_of_range::create(410,"enum value out of range for " #ENUM_TYPE ": " + j.dump(), &j)); \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer, \ + class BinaryType, \ + class CustomBaseClass> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// Macros to simplify conversion from/to types + +#define NLOHMANN_JSON_EXPAND( x ) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_PASTE64, \ + NLOHMANN_JSON_PASTE63, \ + NLOHMANN_JSON_PASTE62, \ + NLOHMANN_JSON_PASTE61, \ + NLOHMANN_JSON_PASTE60, \ + NLOHMANN_JSON_PASTE59, \ + NLOHMANN_JSON_PASTE58, \ + NLOHMANN_JSON_PASTE57, \ + NLOHMANN_JSON_PASTE56, \ + NLOHMANN_JSON_PASTE55, \ + NLOHMANN_JSON_PASTE54, \ + NLOHMANN_JSON_PASTE53, \ + NLOHMANN_JSON_PASTE52, \ + NLOHMANN_JSON_PASTE51, \ + NLOHMANN_JSON_PASTE50, \ + NLOHMANN_JSON_PASTE49, \ + NLOHMANN_JSON_PASTE48, \ + NLOHMANN_JSON_PASTE47, \ + NLOHMANN_JSON_PASTE46, \ + NLOHMANN_JSON_PASTE45, \ + NLOHMANN_JSON_PASTE44, \ + NLOHMANN_JSON_PASTE43, \ + NLOHMANN_JSON_PASTE42, \ + NLOHMANN_JSON_PASTE41, \ + NLOHMANN_JSON_PASTE40, \ + NLOHMANN_JSON_PASTE39, \ + NLOHMANN_JSON_PASTE38, \ + NLOHMANN_JSON_PASTE37, \ + NLOHMANN_JSON_PASTE36, \ + NLOHMANN_JSON_PASTE35, \ + NLOHMANN_JSON_PASTE34, \ + NLOHMANN_JSON_PASTE33, \ + NLOHMANN_JSON_PASTE32, \ + NLOHMANN_JSON_PASTE31, \ + NLOHMANN_JSON_PASTE30, \ + NLOHMANN_JSON_PASTE29, \ + NLOHMANN_JSON_PASTE28, \ + NLOHMANN_JSON_PASTE27, \ + NLOHMANN_JSON_PASTE26, \ + NLOHMANN_JSON_PASTE25, \ + NLOHMANN_JSON_PASTE24, \ + NLOHMANN_JSON_PASTE23, \ + NLOHMANN_JSON_PASTE22, \ + NLOHMANN_JSON_PASTE21, \ + NLOHMANN_JSON_PASTE20, \ + NLOHMANN_JSON_PASTE19, \ + NLOHMANN_JSON_PASTE18, \ + NLOHMANN_JSON_PASTE17, \ + NLOHMANN_JSON_PASTE16, \ + NLOHMANN_JSON_PASTE15, \ + NLOHMANN_JSON_PASTE14, \ + NLOHMANN_JSON_PASTE13, \ + NLOHMANN_JSON_PASTE12, \ + NLOHMANN_JSON_PASTE11, \ + NLOHMANN_JSON_PASTE10, \ + NLOHMANN_JSON_PASTE9, \ + NLOHMANN_JSON_PASTE8, \ + NLOHMANN_JSON_PASTE7, \ + NLOHMANN_JSON_PASTE6, \ + NLOHMANN_JSON_PASTE5, \ + NLOHMANN_JSON_PASTE4, \ + NLOHMANN_JSON_PASTE3, \ + NLOHMANN_JSON_PASTE2, \ + NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) +#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) +#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) +#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) +#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) +#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) +#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) +#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) +#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) +#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) +#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) +#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) +#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) +#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) +#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) +#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) +#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) +#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) +#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) +#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) +#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) +#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) +#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) +#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) +#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) +#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) +#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) +#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) +#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) +#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) +#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) +#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) +#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) +#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) +#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) +#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) +#define NLOHMANN_JSON_DOUBLE_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_DOUBLE_PASTE63, \ + NLOHMANN_JSON_DOUBLE_PASTE63, \ + NLOHMANN_JSON_DOUBLE_PASTE61, \ + NLOHMANN_JSON_DOUBLE_PASTE61, \ + NLOHMANN_JSON_DOUBLE_PASTE59, \ + NLOHMANN_JSON_DOUBLE_PASTE59, \ + NLOHMANN_JSON_DOUBLE_PASTE57, \ + NLOHMANN_JSON_DOUBLE_PASTE57, \ + NLOHMANN_JSON_DOUBLE_PASTE55, \ + NLOHMANN_JSON_DOUBLE_PASTE55, \ + NLOHMANN_JSON_DOUBLE_PASTE53, \ + NLOHMANN_JSON_DOUBLE_PASTE53, \ + NLOHMANN_JSON_DOUBLE_PASTE51, \ + NLOHMANN_JSON_DOUBLE_PASTE51, \ + NLOHMANN_JSON_DOUBLE_PASTE49, \ + NLOHMANN_JSON_DOUBLE_PASTE49, \ + NLOHMANN_JSON_DOUBLE_PASTE47, \ + NLOHMANN_JSON_DOUBLE_PASTE47, \ + NLOHMANN_JSON_DOUBLE_PASTE45, \ + NLOHMANN_JSON_DOUBLE_PASTE45, \ + NLOHMANN_JSON_DOUBLE_PASTE43, \ + NLOHMANN_JSON_DOUBLE_PASTE43, \ + NLOHMANN_JSON_DOUBLE_PASTE41, \ + NLOHMANN_JSON_DOUBLE_PASTE41, \ + NLOHMANN_JSON_DOUBLE_PASTE39, \ + NLOHMANN_JSON_DOUBLE_PASTE39, \ + NLOHMANN_JSON_DOUBLE_PASTE37, \ + NLOHMANN_JSON_DOUBLE_PASTE37, \ + NLOHMANN_JSON_DOUBLE_PASTE35, \ + NLOHMANN_JSON_DOUBLE_PASTE35, \ + NLOHMANN_JSON_DOUBLE_PASTE33, \ + NLOHMANN_JSON_DOUBLE_PASTE33, \ + NLOHMANN_JSON_DOUBLE_PASTE31, \ + NLOHMANN_JSON_DOUBLE_PASTE31, \ + NLOHMANN_JSON_DOUBLE_PASTE29, \ + NLOHMANN_JSON_DOUBLE_PASTE29, \ + NLOHMANN_JSON_DOUBLE_PASTE27, \ + NLOHMANN_JSON_DOUBLE_PASTE27, \ + NLOHMANN_JSON_DOUBLE_PASTE25, \ + NLOHMANN_JSON_DOUBLE_PASTE25, \ + NLOHMANN_JSON_DOUBLE_PASTE23, \ + NLOHMANN_JSON_DOUBLE_PASTE23, \ + NLOHMANN_JSON_DOUBLE_PASTE21, \ + NLOHMANN_JSON_DOUBLE_PASTE21, \ + NLOHMANN_JSON_DOUBLE_PASTE19, \ + NLOHMANN_JSON_DOUBLE_PASTE19, \ + NLOHMANN_JSON_DOUBLE_PASTE17, \ + NLOHMANN_JSON_DOUBLE_PASTE17, \ + NLOHMANN_JSON_DOUBLE_PASTE15, \ + NLOHMANN_JSON_DOUBLE_PASTE15, \ + NLOHMANN_JSON_DOUBLE_PASTE13, \ + NLOHMANN_JSON_DOUBLE_PASTE13, \ + NLOHMANN_JSON_DOUBLE_PASTE11, \ + NLOHMANN_JSON_DOUBLE_PASTE11, \ + NLOHMANN_JSON_DOUBLE_PASTE9, \ + NLOHMANN_JSON_DOUBLE_PASTE9, \ + NLOHMANN_JSON_DOUBLE_PASTE7, \ + NLOHMANN_JSON_DOUBLE_PASTE7, \ + NLOHMANN_JSON_DOUBLE_PASTE5, \ + NLOHMANN_JSON_DOUBLE_PASTE5, \ + NLOHMANN_JSON_DOUBLE_PASTE3, \ + NLOHMANN_JSON_DOUBLE_PASTE3, \ + NLOHMANN_JSON_DOUBLE_PASTE1, \ + NLOHMANN_JSON_DOUBLE_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) func(v1, v2) +#define NLOHMANN_JSON_DOUBLE_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE3(func, v3, v4) +#define NLOHMANN_JSON_DOUBLE_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE5(func, v3, v4, v5, v6) +#define NLOHMANN_JSON_DOUBLE_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE7(func, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_DOUBLE_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE9(func, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_DOUBLE_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE11(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_DOUBLE_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE13(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_DOUBLE_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE15(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_DOUBLE_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE17(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_DOUBLE_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE19(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_DOUBLE_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE21(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_DOUBLE_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE23(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_DOUBLE_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE25(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_DOUBLE_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE27(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_DOUBLE_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE29(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_DOUBLE_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE31(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_DOUBLE_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE33(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_DOUBLE_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE35(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_DOUBLE_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE37(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_DOUBLE_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE39(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_DOUBLE_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE41(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_DOUBLE_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE43(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_DOUBLE_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE45(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_DOUBLE_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE47(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_DOUBLE_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE49(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_DOUBLE_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE51(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_DOUBLE_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE53(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_DOUBLE_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE55(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_DOUBLE_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE57(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_DOUBLE_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE59(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_DOUBLE_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE61(func, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) + +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1) : nlohmann_json_default_obj.v1; + +#define NLOHMANN_JSON_TO_WITH_NAME(v1, v2) nlohmann_json_j[v1] = nlohmann_json_t.v2; +#define NLOHMANN_JSON_FROM_WITH_NAME(v1, v2) nlohmann_json_j.at(v1).get_to(nlohmann_json_t.v2); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT_WITH_NAME(v1, v2) nlohmann_json_t.v2 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(v1, nlohmann_json_default_obj.v2) : nlohmann_json_default_obj.v2; + +#define NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(...) template::value, int> = 0> __VA_ARGS__ + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE +@since version 3.9.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_NAME, __VA_ARGS__)) }) + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT +@since version 3.11.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT_WITH_NAME, __VA_ARGS__)) }) + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE +@since version 3.11.3 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE +@since version 3.9.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_NAME, __VA_ARGS__)) }) + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT +@since version 3.11.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT_WITH_NAME, __VA_ARGS__)) }) + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE +@since version 3.11.3 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(Type, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_NAME, __VA_ARGS__)) }) + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT_WITH_NAME, __VA_ARGS__)) }) + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) + + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_NAME, __VA_ARGS__)) }) + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT_WITH_NAME, __VA_ARGS__)) }) + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE +@since version 3.12.0 +@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(Type, BaseType, ...) \ + NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DOUBLE_PASTE(NLOHMANN_JSON_TO_WITH_NAME, __VA_ARGS__)) }) + +// inspired from https://stackoverflow.com/a/26745591 +// allows calling any std function as if (e.g., with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ + } + +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif + +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif + +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 1 +#endif + +#ifndef JSON_BRACE_INIT_COPY_SEMANTICS + #define JSON_BRACE_INIT_COPY_SEMANTICS 0 +#endif + +#if JSON_HAS_THREE_WAY_COMPARISON + #include // partial_ordering +#endif + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/////////////////////////// +// JSON type enumeration // +/////////////////////////// + +/*! +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. + +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type + +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function +}; + +/*! +@brief comparison operator for JSON types + +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string < binary +- furthermore, each type is not smaller than itself +- discarded values are not comparable +- binary is represented as a b"" string in python and directly comparable to a + string; however, making a binary array directly comparable with a string would + be surprising behavior in a JSON file. + +@since version 1.0.0 +*/ +#if JSON_HAS_THREE_WAY_COMPARISON + inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* +#else + inline bool operator<(const value_t lhs, const value_t rhs) noexcept +#endif +{ + static constexpr std::array order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, + 6 /* binary */ + } + }; + + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); +#if JSON_HAS_THREE_WAY_COMPARISON + if (l_index < order.size() && r_index < order.size()) + { + return order[l_index] <=> order[r_index]; // *NOPAD* + } + return std::partial_ordering::unordered; +#else + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; +#endif +} + +// GCC selects the built-in operator< over an operator rewritten from +// a user-defined spaceship operator +// Clang, MSVC, and ICC select the rewritten candidate +// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) +#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + return std::is_lt(lhs <=> rhs); // *NOPAD* +} +#endif + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/*! +@brief replace all occurrences of a substring by another string + +@param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t +@param[in] f the substring to replace with @a t +@param[in] t the string to replace @a f + +@pre The search string @a f must not be empty. **This precondition is +enforced with an assertion.** + +@since version 2.0.0 +*/ +template +inline void replace_substring(StringType& s, const StringType& f, + const StringType& t) +{ + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find the first occurrence of f + pos != StringType::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find the next occurrence of f + {} +} + +/*! + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +template +inline StringType escape(StringType s) +{ + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} + +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +inline void unescape(StringType& s) +{ + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // size_t + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; + +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; + +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static JSON_INLINE_VARIABLE constexpr T value{}; +}; + +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif + +template +constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // numeric_limits +#include // char_traits +#include // tuple +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval +#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L + #include // byte +#endif +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // random_access_iterator_tag + +// #include + +// #include + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); + +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); + +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + +#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ + #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + #include // int64_t, uint64_t + #include // map + #include // allocator + #include // string + #include // vector + + // #include + + + /*! + @brief namespace for Niels Lohmann + @see https://github.com/nlohmann + @since version 1.0.0 + */ + NLOHMANN_JSON_NAMESPACE_BEGIN + + /*! + @brief default JSONSerializer template argument + + This serializer ignores the template arguments and uses ADL + ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) + for serialization. + */ + template + struct adl_serializer; + + /// a class to store JSON values + /// @sa https://json.nlohmann.me/api/basic_json/ + template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector, // cppcheck-suppress syntaxError + class CustomBaseClass = void> + class basic_json; + + /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document + /// @sa https://json.nlohmann.me/api/json_pointer/ + template + class json_pointer; + + /*! + @brief default specialization + @sa https://json.nlohmann.me/api/json/ + */ + using json = basic_json<>; + + /// @brief a minimal map-like container that preserves insertion order + /// @sa https://json.nlohmann.me/api/ordered_map/ + template + struct ordered_map; + + /// @brief specialization that maintains the insertion order of object keys + /// @sa https://json.nlohmann.me/api/ordered_json/ + using ordered_json = basic_json; + + NLOHMANN_JSON_NAMESPACE_END + +#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + +NLOHMANN_JSON_NAMESPACE_BEGIN +/*! +@brief detail namespace with internal helper functions + +This namespace collects functions that should not be exposed, +implementations of some @ref basic_json methods, and meta-programming helpers. + +@since version 2.1.0 +*/ +namespace detail +{ + +///////////// +// helpers // +///////////// + +// Note to maintainers: +// +// Every trait in this file expects a non-CV-qualified type. +// The only exceptions are in the 'aliases for detected' section +// (i.e., those of the form: decltype(T::member_function(std::declval()))) +// +// In this case, T has to be properly CV-qualified to constraint the function arguments +// (e.g., to_json(BasicJsonType&, const T&)) + +template struct is_basic_json : std::false_type {}; + +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct is_basic_json : std::true_type {}; + +// used by exceptions create() member functions +// true_type for the pointer to possibly cv-qualified basic_json or std::nullptr_t +// false_type otherwise +template +struct is_basic_json_context : + std::integral_constant < bool, + is_basic_json::type>::type>::value + || std::is_same::value > +{}; + +////////////////////// +// json_ref helpers // +////////////////////// + +template +class json_ref; + +template +struct is_json_ref : std::false_type {}; + +template +struct is_json_ref> : std::true_type {}; + +////////////////////////// +// aliases for detected // +////////////////////////// + +template +using mapped_type_t = typename T::mapped_type; + +template +using key_type_t = typename T::key_type; + +template +using value_type_t = typename T::value_type; + +template +using difference_type_t = typename T::difference_type; + +template +using pointer_t = typename T::pointer; + +template +using reference_t = typename T::reference; + +template +using iterator_category_t = typename T::iterator_category; + +template +using to_json_function = decltype(T::to_json(std::declval()...)); + +template +using from_json_function = decltype(T::from_json(std::declval()...)); + +template +using get_template_function = decltype(std::declval().template get()); + +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json : std::false_type {}; + +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable +{ + static constexpr bool value = is_detected::value; +}; + +template +struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if JSONSerializer::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template +struct has_non_default_from_json : std::false_type {}; + +template +struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if BasicJsonType::json_serializer::to_json exists +// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. +template +struct has_to_json : std::false_type {}; + +template +struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +template +using detect_key_compare = typename T::key_compare; + +template +struct has_key_compare : std::integral_constant::value> {}; + +// obtains the actual object key comparator +template +struct actual_object_comparator +{ + using object_t = typename BasicJsonType::object_t; + using object_comparator_t = typename BasicJsonType::default_object_comparator_t; + using type = typename std::conditional < has_key_compare::value, + typename object_t::key_compare, object_comparator_t>::type; +}; + +template +using actual_object_comparator_t = typename actual_object_comparator::type; + +///////////////// +// char_traits // +///////////////// + +// Primary template of char_traits calls std char_traits +template +struct char_traits : std::char_traits +{}; + +// Explicitly define char traits for unsigned char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = unsigned char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(std::char_traits::eof()); + } +}; + +// Explicitly define char traits for signed char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = signed char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(std::char_traits::eof()); + } +}; + +#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L +template<> +struct char_traits : std::char_traits +{ + using char_type = std::byte; + using int_type = uint64_t; + + static int_type to_int_type(char_type c) noexcept + { + return static_cast(std::to_integer(c)); + } + + static char_type to_char_type(int_type i) noexcept + { + return std::byte(static_cast(i)); + } + + static constexpr int_type eof() noexcept + { + return static_cast(std::char_traits::eof()); + } +}; +#endif + +/////////////////// +// is_ functions // +/////////////////// + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B { }; +template +struct conjunction +: std::conditional(B::value), conjunction, B>::type {}; + +// https://en.cppreference.com/w/cpp/types/negation +template struct negation : std::integral_constant < bool, !B::value > { }; + +// Reimplementation of is_constructible and is_default_constructible, due to them being broken for +// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). +// This causes compile errors in e.g., Clang 3.5 or GCC 4.9. +template +struct is_default_constructible : std::is_default_constructible {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_constructible : std::is_constructible {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_iterator_traits : std::false_type {}; + +template +struct is_iterator_traits> +{ + private: + using traits = iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; +}; + +template +struct is_range +{ + private: + using t_ref = typename std::add_lvalue_reference::type; + + using iterator = detected_t; + using sentinel = detected_t; + + // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator + // and https://en.cppreference.com/w/cpp/iterator/sentinel_for + // but reimplementing these would be too much work, as a lot of other concepts are used underneath + static constexpr auto is_iterator_begin = + is_iterator_traits>::value; + + public: + static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; +}; + +template +using iterator_t = enable_if_t::value, result_of_begin())>>; + +template +using range_value_t = value_type_t>>; + +// The following implementation of is_complete_type is taken from +// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ +// and is written by Xiang Fan who agreed to use it in this library. + +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : std::true_type {}; + +template +struct is_compatible_object_type_impl : std::false_type {}; + +template +struct is_compatible_object_type_impl < + BasicJsonType, CompatibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + // macOS's is_constructible does not play well with nonesuch... + static constexpr bool value = + is_constructible::value && + is_constructible::value; +}; + +template +struct is_compatible_object_type + : is_compatible_object_type_impl {}; + +template +struct is_constructible_object_type_impl : std::false_type {}; + +template +struct is_constructible_object_type_impl < + BasicJsonType, ConstructibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + static constexpr bool value = + (is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + (is_constructible::value && + std::is_same < + typename object_t::mapped_type, + typename ConstructibleObjectType::mapped_type >::value)) || + (has_from_json::value || + has_non_default_from_json < + BasicJsonType, + typename ConstructibleObjectType::mapped_type >::value); +}; + +template +struct is_constructible_object_type + : is_constructible_object_type_impl {}; + +template +struct is_compatible_string_type +{ + static constexpr auto value = + is_constructible::value; +}; + +template +struct is_constructible_string_type +{ + // launder type through decltype() to fix compilation failure on ICPC +#ifdef __INTEL_COMPILER + using laundered_type = decltype(std::declval()); +#else + using laundered_type = ConstructibleStringType; +#endif + + static constexpr auto value = + conjunction < + is_constructible, + is_detected_exact>::value; +}; + +template +struct is_compatible_array_type_impl : std::false_type {}; + +template +struct is_compatible_array_type_impl < + BasicJsonType, CompatibleArrayType, + enable_if_t < + is_detected::value&& + is_iterator_traits>>::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 + !std::is_same>::value >> +{ + static constexpr bool value = + is_constructible>::value; +}; + +template +struct is_compatible_array_type + : is_compatible_array_type_impl {}; + +template +struct is_constructible_array_type_impl : std::false_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t::value >> + : std::true_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t < !std::is_same::value&& + !is_compatible_string_type::value&& + is_default_constructible::value&& +(std::is_move_assignable::value || + std::is_copy_assignable::value)&& +is_detected::value&& +is_iterator_traits>>::value&& +is_detected::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 +!std::is_same>::value&& +is_complete_type < +detected_t>::value >> +{ + using value_type = range_value_t; + + static constexpr bool value = + std::is_same::value || + has_from_json::value || + has_non_default_from_json < + BasicJsonType, + value_type >::value; +}; + +template +struct is_constructible_array_type + : is_constructible_array_type_impl {}; + +template +struct is_compatible_integer_type_impl : std::false_type {}; + +template +struct is_compatible_integer_type_impl < + RealIntegerType, CompatibleNumberIntegerType, + enable_if_t < std::is_integral::value&& + std::is_integral::value&& + !std::is_same::value >> +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + + static constexpr auto value = + is_constructible::value && + CompatibleLimits::is_integer && + RealLimits::is_signed == CompatibleLimits::is_signed; +}; + +template +struct is_compatible_integer_type + : is_compatible_integer_type_impl {}; + +template +struct is_compatible_type_impl: std::false_type {}; + +template +struct is_compatible_type_impl < + BasicJsonType, CompatibleType, + enable_if_t::value >> +{ + static constexpr bool value = + has_to_json::value; +}; + +template +struct is_compatible_type + : is_compatible_type_impl {}; + +template +struct is_compatible_reference_type_impl +{ + using JsonType = uncvref_t; + using CVType = typename std::remove_reference::type; + using Type = typename std::remove_cv::type; + constexpr static bool value = std::is_reference::value && + (!std::is_const::type>::value || std::is_const::value) && + (std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value); +}; + +template +struct is_compatible_reference_type + : is_compatible_reference_type_impl {}; + +template +struct is_constructible_tuple : std::false_type {}; + +template +struct is_constructible_tuple> : conjunction...> {}; + +template +struct is_json_iterator_of : std::false_type {}; + +template +struct is_json_iterator_of : std::true_type {}; + +template +struct is_json_iterator_of : std::true_type +{}; + +// checks if a given type T is a template specialization of Primary +template