diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 75ffb2a..0cf91e6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -21,14 +21,18 @@ jobs:
- name: جلب المستودع
uses: actions/checkout@v4
+ # (AR) نسخةٌ مثبَّتةٌ لا «latest»: قياساتُ الثيم (حاويةُ الجدول `.table-wrapper`،
+ # بنيةُ `print.html`، مُعرِّفاتُ العناوين العربيّة الخام) أُجريت على 0.5.4،
+ # وحرّاسُ `theme/page-toc.js` مبنيّةٌ عليها. ترقيةٌ صامتةٌ في «latest» تُبطلها
+ # بلا إنذار. الترقيةُ قرارٌ يُراجَع في PR لا حدثٌ يقع من تلقائه.
- name: تثبيت mdBook
uses: peaceiris/actions-mdbook@v2
with:
- mdbook-version: latest
+ mdbook-version: "0.5.4"
- name: تثبيت mdbook-mermaid + أصوله
run: |
- cargo install mdbook-mermaid --locked
+ cargo install mdbook-mermaid --version 0.17.0 --locked
mdbook-mermaid install .
- name: البناء
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index a3adeef..847a101 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -26,14 +26,18 @@ jobs:
- name: جلب المستودع
uses: actions/checkout@v4
+ # (AR) نسخةٌ مثبَّتةٌ لا «latest»: قياساتُ الثيم (حاويةُ الجدول `.table-wrapper`،
+ # بنيةُ `print.html`، مُعرِّفاتُ العناوين العربيّة الخام) أُجريت على 0.5.4،
+ # وحرّاسُ `theme/page-toc.js` مبنيّةٌ عليها. ترقيةٌ صامتةٌ في «latest» تُبطلها
+ # بلا إنذار. الترقيةُ قرارٌ يُراجَع في PR لا حدثٌ يقع من تلقائه.
- name: تثبيت mdBook
uses: peaceiris/actions-mdbook@v2
with:
- mdbook-version: latest
+ mdbook-version: "0.5.4"
- name: تثبيت mdbook-mermaid + أصوله
run: |
- cargo install mdbook-mermaid --locked
+ cargo install mdbook-mermaid --version 0.17.0 --locked
mdbook-mermaid install .
- name: البناء
diff --git a/.gitignore b/.gitignore
index 799eda0..ded3177 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,4 @@ mermaid-init.js
.DS_Store
Thumbs.db
*.swp
+__pycache__/
diff --git a/book.toml b/book.toml
index bdfa3c2..8236372 100644
--- a/book.toml
+++ b/book.toml
@@ -16,7 +16,7 @@ preferred-dark-theme = "navy"
git-repository-url = "https://github.com/sadlang/dev-guide"
edit-url-template = "https://github.com/sadlang/dev-guide/edit/main/{path}"
additional-css = ["theme/rtl.css", "theme/custom.css"]
-additional-js = ["theme/font-zoom.js"]
+additional-js = ["theme/font-zoom.js", "theme/page-toc.js"]
mathjax-support = false
[output.html.fold]
diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index cf54982..c40c89b 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -36,7 +36,7 @@
- [المفسّر الشجري (Interpreter)](backend/interpreter.md)
- [التمثيل الوسيط SIR](backend/sir.md)
- [توليد LLVM (المترجم sadc)](backend/llvm.md)
-- [الآلة الافتراضية (VM)](backend/vm.md)
+- [الخلفيّة الأصليّة بلا LLVM (SIR → ELF64)](backend/native.md)
- [دراسة حالة: توحيد هاش/شفّر/فك_تشفير](backend/crypto-unification.md)
- [دراسة حالة: توسيع مكتبة التشفير (٥ مراحل + Argon2id)](backend/crypto-library-expansion.md)
diff --git a/src/architecture/overview.md b/src/architecture/overview.md
index 96e1493..7ec943f 100644
--- a/src/architecture/overview.md
+++ b/src/architecture/overview.md
@@ -9,7 +9,8 @@
| النواة المشتركة | `shared/` | معجمي، نحوي، AST، نظام الأنواع `Value`، نظام الأخطاء |
| المفسّر | `interpreter/` | مفسّر شجريّ؛ `InterpreterCore` يدير المتغيّرات والدوال والنطاقات والتقييم |
| المترجم | `compiler/` | AST → SIR → LLVM IR → ملفّ تنفيذيّ (SIR يدعم تعليمات ملكية) |
-| الآلة الافتراضية | `vm/` | بايت كود مرتبط مباشرةً بالمفسّر |
+| الخلفيّة الأصليّة | `compiler/include/backend/native/` | SIR → شيفرة آلة → ELF64 ساكن بلا LLVM ولا رابطٍ أجنبيّ — [الفصل](../backend/native.md) |
+| ~~الآلة الافتراضية~~ | — | `vm/` أُزيل من الشجرة بالإيداع `bcf0a746` («ستُعاد كتابتها من الصفر») — لا فصل له حتّى تُكتب |
| المكتبة القياسية | `stdlib/` | وحدات عربية: core/io/math/string/network/graphics |
| الأدوات | `tools/` | lsp · formatter · pkg · repl · sadc CLI · sadinfo |
| مصدر الحقيقة | `language-truth/` | YAML SoT لكل بيانات اللغة + القواعد |
@@ -26,7 +27,7 @@ flowchart TD
SRC["مصدر .ص (UTF-8)"] --> LEX["LexerCore
shared/lexer"]
LEX --> PAR["ParserCore
shared/parser"]
PAR --> AST["AST
shared/ast"]
- AST --> INT["InterpreterCore / VM
(تنفيذ فوريّ)"]
+ AST --> INT["InterpreterCore
(تنفيذ فوريّ)"]
AST --> SIR["SIRBuilder
compiler/src/frontend"]
SIR --> OPT["SIROptimizer"]
OPT --> LLVM["LLVMCodeGen
compiler/src/backend/llvm"]
diff --git a/src/backend/crypto-library-expansion.md b/src/backend/crypto-library-expansion.md
index ad5033b..8447236 100644
--- a/src/backend/crypto-library-expansion.md
+++ b/src/backend/crypto-library-expansion.md
@@ -122,7 +122,8 @@ AEAD في **نفس** القطعة بعد حلّ التعارض أعاد تجاو
## الاختبار
كل مرحلة أضافت ملفّات إلى
-`tests/behavior/sections/09_المكتبة_القياسية/04_تشفير/` (14 ملفًّا إجمالًا)،
+`tests/behavior/sections/09_المكتبة_القياسية/04_تشفير/` (**20 ملفًّا** في `dev` اليوم؛
+كانت 14 عند كتابة الفصل)،
كلّ واحد يُشغَّل عبر `sad-run.exe` **و**`sadc.exe` ويُقارَن الناتج حرفيًّا —
شعاعات RFC/مسابقة رسميّة لكل معيار (BLAKE3-team، RFC 2898/5869/7748/8032/8439/
9106)، إضافة إلى حالات رفض صريحة (سرّ مشترك كلّه أصفار في X25519، توقيع/مفتاح
diff --git a/src/backend/llvm.md b/src/backend/llvm.md
index 2d544b5..1658c9f 100644
--- a/src/backend/llvm.md
+++ b/src/backend/llvm.md
@@ -37,4 +37,4 @@ flowchart LR
- **أصلِح في الطبقة الصحيحة:** خطأ تحويل أنواع يُصلَح في codegen؛ خطأ ترتيب حقول في `SIRBuilder` (BF-10).
---
-**اقرأ بعده:** [الآلة الافتراضية](vm.md).
+**اقرأ بعده:** [الخلفيّة الأصليّة بلا LLVM](native.md).
diff --git a/src/backend/native.md b/src/backend/native.md
new file mode 100644
index 0000000..377219c
--- /dev/null
+++ b/src/backend/native.md
@@ -0,0 +1,278 @@
+# الخلفيّة الأصليّة بلا LLVM (SIR → ELF64)
+
+> **ماذا ستتعلّم:** كيف تُترجَم لغة ص إلى شيفرة آلة **بلا LLVM ولا رابطٍ أجنبيّ**؛ طبقات
+> الخلفيّة الأربع (جداول SoT · المرمِّزات · المخفِّضات · كاتب ELF)؛ كيف تُقاس صحّتها
+> بدرجتَين متمايزتَين (التصريف والتنفيذ)؛ وأين تبدأ إن أردت إضافة أوپكود أو معماريّة.
+
+> 📎 **المصدر:** [`compiler/include/backend/native/`](https://github.com/sadlang/s-programming-language/tree/dev/compiler/include/backend/native) ·
+> [`language-truth/backend/`](https://github.com/sadlang/s-programming-language/tree/dev/language-truth/backend) ·
+> [`tools/compiler/compiler_driver_native.cpp`](https://github.com/sadlang/s-programming-language/blob/dev/tools/compiler/compiler_driver_native.cpp) ·
+> [`scripts/native_backend/`](https://github.com/sadlang/s-programming-language/tree/dev/scripts/native_backend)
+
+> 📌 **الخلاصة في ثلاثة أسطر:** ثلاثُ معماريّاتٍ لها مخفِّضٌ موصولٌ اليوم — x86-64 وARM64
+> بـ**١٠٤** أوپكودات، وRV64 بـ**٧** — واثنتان مخطَّطتان؛ والخانةُ المضمونة عبرها جميعًا هي
+> **ELF على لينكس/الوضع الحرّ** لا غير، فماك وويندوز يبقيان على LLVM. والصحّةُ تُقاس
+> **بدرجتَين** لا بواحدة (بصمةُ التصريف · التشغيل الحيّ)، وجداولُ اختيار التعليمات ما تزال
+> بذرةً والتخفيضُ الفعليّ يعيش في C++.
+>
+> **جئتَ لتُسهم؟** اقفز إلى [«أين تبدأ»](#أين-تبدأ). **جئتَ لسؤالٍ بعينه؟**
+> [كيف يُبلَّغ عن فشل التخفيض](#التشخيص-لا-نصَّ-رسالةٍ-في-الخلفيّة) ·
+> [كيف تُقاس الخلفيّة](#كيف-تُقاس-الخلفيّة-درجتان-لا-واحدة) ·
+> [ما الحدودُ والدَّينُ المُعلَن](#مزالق-مقيسة-لا-تكرّرها).
+
+## لماذا خلفيّةٌ ثالثة؟
+للغة ص ثلاثة مسارات تنفيذ: [المفسّر الشجريّ](interpreter.md)، و[SIR → LLVM](llvm.md)،
+وهذا. المسار الثالث ليس تحسينَ أداء بل **سيادةً**: أن تُنتَج شيفرةُ الآلة من مصدر ص
+دون أن يمرّ البرنامج بأيّ أداةٍ لا نملكها — لا `clang` ولا `ld` ولا `lld` ولا `as`.
+
+عقدُ السيادة مكتوبٌ في مصدر الحقيقة لا في نيّة أحد
+([`targets.yaml`](https://github.com/sadlang/s-programming-language/blob/dev/language-truth/backend/targets.yaml)):
+**خمس معماريّات فأكثر بلا LLVM إطلاقًا**، والخانة الإلزاميّة عبرها جميعًا هي
+**ELF + لينكس/الوضع الحرّ** (freestanding). أمّا Mach-O/darwin وPE/Win64 فخارج نواة
+السيادة صراحةً — يبقيان على LLVM حتّى قرارٍ لاحق.
+
+## الموضع في خطّ الأنابيب
+```mermaid
+flowchart TD
+ SRC["مصدر .ص"] --> AST["AST"]
+ AST --> SIR["SIRBuilder → SIR"]
+ SIR --> OPT["SIROptimizer"]
+ OPT -->|المسار الافتراضيّ| LLVM["LLVMCodeGen → ملفّ تنفيذيّ"]
+ OPT -->|"--خلفية-أصلية"| NAT["مخفِّض SIR الأصليّ
(x86-64 · ARM64 · RV64)"]
+ NAT --> ENC["المرمِّز (بايتات)"]
+ ENC --> ELF["Elf64Writer → ELF64 ساكن"]
+```
+الفارق الجوهريّ: مسار LLVM يسلّم IR إلى مكتبةٍ أجنبيّة تتولّى الترميز والربط، والمسار
+الأصليّ **يكتب البايتات بنفسه** ثمّ يلفّها في حاويةِ ELF بنفسه.
+
+## الأهداف الخمسة — والفجوة التي لا تُكتَم
+> 📎 **المصدر:** [`targets.yaml`](https://github.com/sadlang/s-programming-language/blob/dev/language-truth/backend/targets.yaml)
+
+عمود «المعلم» أدناه يستعمل الترقيم `م٠ … م٨` — و«م-» اختصارُ **معلَمٍ** في خارطة الخلفيّة.
+
+| الهدف | المعلم | الحالة | أوپكودات مخفَّضة |
+|---|---|---|---|
+| x86-64 | م٠–م٣ | `lowered` | **104** |
+| AArch64/ARM64 | م٥ | `lowered` | **104** |
+| RISC-V RV64GC | م٦ | `lowered` | **7** |
+| ARMv7-A/Thumb-2 | م٧ | `planned` | — |
+| x86 i686 | م٨ | `planned` | — |
+| استخراج الطبقة الجدوليّة | م٤ | `in_progress` | (طبقةٌ مشترَكة لا هدف) |
+
+> ⚠️ **«مدعوم» ≠ «يترجم كلّ برنامج».** `lowered` تعني «له مخفِّضٌ موصولٌ ومُبرهَنٌ
+> بالتشغيل» فحسب. الفارق مقيسٌ لا مخفيّ: حقل `native_lowered` في
+> [`sir_opcodes.yaml`](https://github.com/sadlang/s-programming-language/blob/dev/language-truth/backend/sir_opcodes.yaml)
+> يسجّل لكلّ أوپكود مَن يخفّضه فعلًا، وكتلة `stats` تجمعه:
+> `native_lowered_x86_64: 104` · `native_lowered_arm64: 104` · `native_lowered_riscv64: 7`.
+> وRV64 **يرفض ما عدا مجموعتَه صراحةً** لا يُنتِج ثنائيًّا مبتورًا.
+
+وثمّة موضعٌ واحدٌ في الشجرة ما يزال يقول غيرَ هذا الرقم، فلا تأخذه عنه:
+
+> 📌 **ترويسةُ `sir_native_lowering.h` أقدمُ من هذا الرقم:** ما تزال تصف «مجموعةً دنيا
+> من الأوپكودات (MOVE/ADD_I64/SUB_I64/المقارنات/BR/BR_COND/RET)» و«بلا انسكابٍ ولا
+> PHI/ذاكرة» — وهو وصفُ م٠. المقيسُ اليومَ ١٠٤، وفي المستودع `prove_sir_spill.sh`
+> و`prove_sir_memory.sh`. الحقيقةُ هنا كتلةُ `stats` المُولَّدة في `sir_opcodes.yaml`،
+> لا نصُّ الترويسة.
+
+وحقلٌ ثانٍ متمايزٌ عمدًا: `isel_declared` — مَن يُعلن نمطًا في `backend/*/isel.yaml`
+(٣ لكلٍّ من x86_64 وarm64، ٠ لـriscv64). **الفجوة بين الحقلَين هي الرسالة:** جداولُ
+اختيار التعليمات ما تزال بذرةً، والتخفيضُ الفعليُّ يعيش في C++.
+
+## المدخل من سطر الأوامر
+العَلَم `--خلفية-أصلية` مُعرَّف في مصدر الحقيقة
+([`cli_flags.yaml:211-218`](https://github.com/sadlang/s-programming-language/blob/dev/language-truth/cli_flags.yaml#L211-L218))
+ويقود إلى [`compiler_driver_native.cpp`](https://github.com/sadlang/s-programming-language/blob/dev/tools/compiler/compiler_driver_native.cpp).
+والمعماريّة **تُشتقّ من ثالوث `--هدف` لا من عَلَمٍ ثانٍ** — الهدف مصدرٌ واحد:
+
+| ثالوث الهدف | المخفِّض | ملاحظة |
+|---|---|---|
+| `aarch64-*` / `arm64-*` | `arm64_sir_lowering.h` | مطابقةٌ تامّة على حقل architecture بعد تفكيك الثالوث، لا مطابقةُ بادئة على نصّ خام |
+| `riscv64-*` | `riscv64_sir_lowering.h` | م٦ |
+| `x86_64-*` | `sir_native_lowering.h` | الافتراض؛ وبلا `--هدف` يكون الثالوث ثالوثَ المضيف |
+
+وما عدا هذه الثلاث **يُرفَض** لا يُخفَّض افتراضًا: `targetIsSupported` تشترط معماريّةً
+مخفَّضةً *و*نظامًا حاويتُه ELF معًا، كي لا يخرج ELF x86-64 لهدفِ wasm أو ويندوز صامتًا.
+
+نظام التشغيل يُفحَص أيضًا: `linux` و`none` (معدنٌ عارٍ/الوضع الحرّ) وحدهما يصلحان
+لكاتب ELF64 — وثالوثٌ بلا نظامٍ مذكور (`aarch64` مجرّدًا) يُعامَل معاملةَ `none`؛
+ويندوز وماك حاويتان مختلفتان لا يكتبهما هذا المسار.
+
+## الطبقات الأربع
+```mermaid
+flowchart TB
+ subgraph SoT["① مصدر الحقيقة — language-truth/backend/"]
+ I["instructions.yaml
(جدول الترميز)"]
+ R["registers.yaml"]
+ S["isel.yaml
(أنماط الاختيار)"]
+ A["abi/*.yaml
(e_machine · اتّفاقيّة النداء)"]
+ end
+ subgraph ENC["② المرمِّزات (header-only)"]
+ V["x86_variable_encoder
REX + ModRM"]
+ F["arm64/riscv64_fixed32_encoder
كلمة 32-بت ثابتة"]
+ end
+ subgraph LOW["③ المخفِّضات"]
+ C["sir_lowering_common.h
LoweringDriver<Target> · LoweringDiagnostics"]
+ X["sir_native_lowering.h"]
+ M["arm64_sir_lowering.h"]
+ W["riscv64_sir_lowering.h"]
+ end
+ E["④ elf64_writer.h
ELF64 ساكن"]
+ SoT --> ENC --> LOW --> E
+```
+
+### ① الجداول (SoT)
+`instructions.yaml` يصف الترميز بيانًا (`form` · `operands` · `encode`)، و`isel.yaml`
+يصف النمط (`sir → match → emit + cost`). **بنية النمط مشتركة عبر ISAs والمحتوى مختلف**:
+x86 يدمّر الوجهة (`add dst, src`) بينما ARM64/RISC-V ثلاثيّةُ المعاملات.
+
+### ② المرمِّزات
+محرّكٌ عامٌّ واحد لكلّ عائلة: **المنطق الضيّق يُكتَب مرّةً، والاختلاف بين التعليمات
+بياناتٌ (`EncSpec`) لا كود**. `x86_variable_encoder.h` يكتب بادئة REX وModRM؛ ونظيراه
+`arm64_fixed32_encoder.h` و`riscv64_fixed32_encoder.h` يبنيان كلمةً ثابتة الطول.
+والصحّة **مقيسةٌ بايتًا ببايت ضدّ `llvm-mc`** في `test_native_backend_m1.cpp` — أي أنّ
+LLVM حاضرٌ في *القياس* وغائبٌ عن *المنتَج*.
+
+### ③ المخفِّضات والطبقة المشتركة
+م٤ تستخرج ما لا يخصّ معماريّةً بعينها إلى
+[`sir_lowering_common.h`](https://github.com/sadlang/s-programming-language/blob/dev/compiler/include/backend/native/sir_lowering_common.h):
+
+- **مسندات تحليل SIR عديمة الحالة:** `isComparison` · `isConstInt` · `findFusedComparison`
+ · `hasResultAndArity` · عقد الشكل (نتيجةٌ موجودة + عدد معامِلات متوقَّع).
+- **`LoweringDiagnostics`** — قاعدةُ **تركيبٍ لا تعدّدِ أشكال**: مُدمِّرٌ محميٌّ غير
+ افتراضيّ عمدًا، فلا حذفَ عبر مؤشّر قاعدة. (وما الذي يُبلَّغ به فعلًا حين يفشل تخفيضٌ؟
+ انظر [§التشخيص](#التشخيص-لا-نصَّ-رسالةٍ-في-الخلفيّة).)
+- **`LoweringDriver`** بنمط CRTP — تتابعُ التخفيض يعيش **مرّةً واحدة**، والهدفُ
+ يقدّم خطّافاته الثلاثة: الثنائيّ · الأحاديّ · المقارنة.
+
+> ✅ **عقدُ الاستخراج مقيسٌ لا مُدَّعًى:** بصمةُ `sha256` لمخرَج ELF — وهي بصمةُ درجةِ
+> التصريف، تُشرَح في §«كيف تُقاس الخلفيّة» — عبر مصفوفة القواعد × `{x86_64, arm64}` ⇒
+> **صفرُ بايتةٍ مختلفة**. ومع ذلك نطاقُ البرهان محدودٌ ومُعلَن: المصفوفة لا تمثّل معامِل
+> `Any` في عمليّةٍ عشريّة، فبرهانُ تلك الحالة منفصلٌ (`prove_any_float.sh`). البصمةُ
+> حارسٌ ضدّ تغييرٍ غير مقصود، لا بديلٌ عن مراجعة.
+
+**تدفّق التحكّم بمرورين:** إزاحةُ اللصيقة لا تكون معروفةً ساعةَ بثّ القفزة التي تقصدها،
+فيُقسَم العمل مرورَين ينتهيان بترقيع كلّ `rel32`:
+
+```mermaid
+flowchart TB
+ subgraph P1["المرور ① — البثّ"]
+ B1["ابثّ بايتات الكتلة بالترتيب"]
+ B2["سجّل إزاحة لصيقة الكتلة"]
+ B3["ابثّ القفزة بإزاحةٍ نائبة
+ سجّل طلبَ ترقيع"]
+ B1 --> B2 --> B3
+ end
+ subgraph P2["المرور ② — الترقيع"]
+ F1["لكلّ ترقيعٍ مسجَّل"]
+ F2["rel32 = (هدف − نهاية القفز)"]
+ F1 --> F2
+ end
+ P1 --> P2 --> OUT[".text مكتمل"]
+```
+
+والمقارنةُ المُغذِّية لـ`BR_COND` تُدمَج أو لا تُدمَج بحسب نوعها:
+
+| المقارنة المُغذِّية | تُدمَج؟ | التفصيل |
+|---|---|---|
+| صحيحة | ✅ | `cmp` ثمّ `jCC` ثمّ `jmp` — فلا حاجة إلى `setcc`/`movzx` |
+| عوائم | ❌ | لأجل NaN |
+| معامِلٌ **معلَّب** (ملفوفٌ في تمثيلٍ عامٍّ يحمل وسمَ نوعه) | ❌ | لأنّ نوعها لا يُعرَف إلّا زمنَ التشغيل |
+
+### ④ كاتب ELF64
+[`elf64_writer.h`](https://github.com/sadlang/s-programming-language/blob/dev/compiler/include/backend/native/elf64_writer.h)
+يبني تنفيذيًّا ساكنًا دنيا: رأس ELF (64 بايت) + `program header` واحد `PT_LOAD` (R+X) +
+`.text`، ونقطةُ الدخول عند `vbase + 0x78`. وهو **محايدُ المعماريّة**: بنيةُ التنفيذيّ
+الساكن واحدةٌ عبر الأهداف، والفارقُ حقلٌ واحد (`e_machine`: ٦٢ لـx86-64، ١٨٣ لـAArch64، ٢٤٣ لـRV64)
+**يُمرَّر من جدول الـABI — بيانًا لا كودًا**.
+
+## التشخيص: لا نصَّ رسالةٍ في الخلفيّة
+كلّ فشلِ تخفيضٍ يحمل `ErrorCode` من كتالوج SoT + حمولةَ `{detail}` = **وسمُ سياق** +
+قيمةٌ تُحسَب زمنَ التشغيل. الوسوم مُوحَّدةٌ ثوابتَ مسمّاة في
+[`native_diagnostics.yaml`](https://github.com/sadlang/s-programming-language/blob/dev/language-truth/backend/native_diagnostics.yaml)
+يولّدها `gen_native_diagnostics.py` إلى هيدر C++ يستهلكه المخفِّضان — بدل حرفيّاتٍ خام.
+ووسمُ السياق **ليس نصًّا يراه المستخدم**؛ الرسالةُ من الكتالوج، والوسمُ سياقٌ لمطوّر
+الخلفيّة. أمثلة: `kMoveKind` · `kArrayGetBoxed` · `kEnumPayloadDyn` · `kObjectUnknownClass`.
+
+وبالمنطق نفسه يوحّد
+[`value_repr.yaml`](https://github.com/sadlang/s-programming-language/blob/dev/language-truth/backend/value_repr.yaml)
+وسومَ `SadDyn` ونصوصَ عرض القيم بين المحرّكات الثلاثة — وهذه **وسومُ نوعٍ زمنَ التشغيل،
+لا وسومُ السياق التشخيصيّ أعلاه**. جاء التوحيد بعد عيبٍ حقيقيّ: كان العدم يُعرَض «عدم»
+في الخلفيّة الأصليّة و«لاشيء» في المفسّر وLLVM.
+
+## كيف تُقاس الخلفيّة: درجتان لا واحدة
+صحّةُ الخلفيّة تُقاس بدرجتَين متمايزتَين: **أن تخرج البايتاتُ كما يجب** (التصريف)،
+و**أن يعمل الثنائيُّ الخارج** (التنفيذ).
+
+| الدرجة | ما تقيسه | الأداة | أين تعمل |
+|---|---|---|---|
+| ① التصريف (emit) | أنّ صورة ELF لمصدرٍ وهدفٍ بعينهما **واحدةٌ بايتًا بايتًا عبر المنصّات الثلاث** | [`prove_elf_emit_fingerprint.py`](https://github.com/sadlang/s-programming-language/blob/dev/scripts/native_backend/prove_elf_emit_fingerprint.py) + `elf_emit_fingerprints.json` | المنصّات الثلاث، التكوينان |
+| ② التنفيذ (run) | أنّ الثنائيّ المُخرَج **يعمل** ويطابق المفسّر | [`run_native_proofs.sh`](https://github.com/sadlang/s-programming-language/blob/dev/scripts/native_backend/run_native_proofs.sh) + 21 سكربت `prove_*.sh` | لينكس (+ `qemu-user-static` لـARM64 وRV64) |
+
+> ⚠️ **خلطُ الدرجتَين هو مكمنُ الأخضر الكاذب:** خطوةٌ تُسمّى «براهين الخلفيّة الأصليّة»
+> على ماك ولا تقيس إلّا وجودَ الملفّ **أسوأُ من غيابها**.
+
+البصمةُ **سِقّاطةٌ ثنائيّة الاتّجاه**: بصمةٌ تخالف المسجَّل ⇒ أحمر، وبصمةٌ مسجَّلةٌ لمدخلٍ
+لم يعد يُقاس ⇒ أحمر أيضًا. وهي تكشف ما لا يكشفه اختبار «هل خرج بـ٤٢»: اعتمادٌ على ترتيب
+جدول تجزئة، أو على حجم `size_t` المضيف، أو مسارٌ يتسرّب إلى الصورة.
+
+### حرّاسُ المُنادي الأربعة
+**المُنادي** هو السكربت الجامع `run_native_proofs.sh` الذي يشغّل سكربتاتِ البرهان كلَّها.
+كُتب لسدّ فجوةٍ بنيويّة: كانت البراهين موجودةً **بلا مُنادٍ**، فعاشت في الخلفيّة عيوبٌ
+حيّةٌ شهورًا. وهو يفعل أربعةً لا يفعلها تشغيلٌ يدويّ:
+
+1. **الإنتاجُ ثمّ البرهان** في مجلّدٍ **يُمحى أوّلًا** — مُنتِجٌ ينهار قبل الكتابة يترك
+ ثنائيَّ التشغيلة الماضية فيُبرهَن عليه ويخضرّ. **البقيّةُ أخطرُ من الغياب، لأنّ
+ الغيابَ يُرى.** ويُحكَم برمز خروج المُنتِج أيضًا.
+2. **حارسُ التغطية** — سكربتُ برهانٍ جديدٌ غيرُ مُصرَّحٍ به في المُنادي يُخفِق البوّابة،
+ فلا تعود فجوةُ «سكربتٌ بلا مُنادٍ» بالتسلّل.
+3. **التخطّي إخفاقٌ افتراضيًّا** — مجموعُ `SKIP` أصفارًا يُقرأ «نجح الكلّ» وهو أخضرُ بلا
+ قياس (يُرفَع بـ`SAD_PROOFS_ALLOW_SKIP=1` صراحةً).
+4. **غيابُ `qemu-aarch64` إخفاق** — وإلّا حُذف نصفُ البراهين (AArch64) من الحساب بلا
+ أثرٍ في المخرَج. (ما عداه يُلتقَط نصًّا: `SKIP` يُعدّ ولو خرج السكربتُ بصفر.)
+
+وفي CI تظهر الدرجتان كذلك: خطوة «🔬 براهين الخلفيّة الأصليّة (تنفيذٌ حيّ)» على لينكس،
+وبصمةُ التصريف **غيرُ مشروطةٍ بالتكوين** في الخانات الستّ كلّها. وسببُ تعميمها مقيس:
+كانت الخلفيّة محبوسةً داخل هدفٍ لا يُعرَّف إلّا مع LLVM، فعاش عيبٌ واحد **ستَّ جولات CI**
+لأنّ الخانة الكاشفة واحدة.
+
+## مزالق مقيسة (لا تكرّرها)
+كلُّ بندٍ أدناه أثرُ عطبٍ **قِيس** لا عطبٍ يُخشى — وهذه القائمةُ محضرُ ما التقطته الدرجتان
+أعلاه. وهي تخلط نوعَين: ما **سُدَّ** وبقي مكتوبًا كي لا يُعاد، وما هو **قيدٌ مُعلَنٌ باقٍ**
+يُرفَض صراحةً ولا يُبتَر صامتًا. والتمييزُ منصوصٌ في كلّ بند:
+
+- **حارسٌ مبنيٌّ على الأوپكود والفرقُ في النوع لا يراه:** طُبع `طبيعي` على RV64 **`-1`**
+ بينما المفسّر وx86-64 يطبعان القيمة الصحيحة — لأنّ الطابع موقَّعٌ حصرًا ولم يوزّع أحدٌ
+ على النوع.
+- **حالةٌ مشروطةٌ بالمُحسِّن دون أن يقول ذلك أحد:** `MOVE` لم يكن مخفَّضًا على RV64، فمرّ
+ الهدفُ في `-O2` (حيث يحذفه DCE) و**أخفق في `-O0`**. كشفه اختبارُ الجسر الوحدويّ (يبني
+ SIR بلا مُحسِّن) لا البرهانُ الحيّ الذي كان يقيس `-O2` وحده.
+- **قيدٌ باقٍ مُعلَن:** إزاحات الإطار على RV64 فوريٌّ ١٢-بت موقَّع ⇒ سقف ٢٠٤٧ بايتًا؛
+ ما فوقه **يُرفَض صراحةً** (`kFrameTooLarge`) لا يُبتَر صامتًا.
+- **دَينٌ موثَّق قبل تشغيل isel:** صيغةُ المركم القصيرة (`add=05` · `sub=2D` · `cmp=3D`
+ بلا ModRM) تخالف الشكلَ العامّ `81 /r id` بايتًا، فتفشل المطابقةُ التفاضليّة ضدّ
+ `llvm-mc` **صامتةً** إن اختارت isel المركمَ وجهةً للفوريّ.
+- **أوپكوداتٌ مقيَّدةٌ بمعماريّة** (`rdtsc` · `cli` · `outb` · `mov %crN`): كانت تُبَثّ
+ **لأيّ هدفٍ يُطلَب** بخروجٍ صفريّ — `عداد_الدورات()` بـ`--هدف=aarch64-unknown-elf` كان
+ يخرج بصفرٍ ويبثّ `rdtsc` — فيقع الإخفاق عند المُجمِّع برسالةٍ لا تدلّ على السبب، أو لا
+ يقع فيخرج ثنائيٌّ لا يعمل. **سُدَّ ذلك**: بوّابةٌ في `emitInstruction` تقرأ الجردَ من
+ [`arch_specific_opcodes.yaml`](https://github.com/sadlang/s-programming-language/blob/dev/language-truth/backend/arch_specific_opcodes.yaml)
+ عبر `findArchConstraint()` وتردّ `SEM_TARGET_ARCH_UNSUPPORTED_BUILTIN`. ودَينان
+ مُعلَنان باقيان: البوّابةُ في مسار LLVM (وهذه الأوپكودات `native_lowered: []` فلا
+ يخفّضها المسارُ الأصليّ أصلًا)، وكتلةُ «تجميع … نهاية» لا تمرّ بها.
+- **البرهانُ الذي لا يُعيد أحدٌ إنتاجَه دعوى** مهما صدق قائلُه: كان أحدُ حقول `targets.yaml`
+ يسوق تشغيلًا نصًّا بلا سكربتٍ يُعيده، فاستُبدل بسكربتٍ مُصرَّحٍ به في المُنادي.
+
+## أين تبدأ
+هذا الجدول هو بابُ المُسهِم: صفٌّ لكلّ نيّة، وكلُّ صفٍّ ينتهي بما يجعل الإسهامَ **مقيسًا**
+لا مُدَّعًى — سكربتَ برهانٍ مُصرَّحًا به، أو اختبارَ تطابقٍ، أو حقلًا في مصدر الحقيقة.
+
+| تريد أن… | ابدأ من |
+|---|---|
+| تضيف أوپكودًا مخفَّضًا | `sir_native_lowering.h` (أو نظيره) + حدّث `native_lowered` في `sir_opcodes.yaml` + سكربت برهانٍ مُصرَّحٍ به في المُنادي |
+| تضيف تعليمةً أو صيغةَ ترميز | `language-truth/backend//instructions.yaml` ثمّ اختبارُ التطابق ضدّ `llvm-mc` |
+| تضيف معماريّةً | `targets.yaml` أوّلًا — وانتظر م٤ (استخراج الطبقة الجدوليّة)، فإضافتُها قبلها تعني **مخفِّضًا يدويًّا ثالثًا** |
+| تفهم لماذا فشل تخفيضٌ عندك | وسمُ السياق في `native_diagnostics.yaml` + رسالةُ الكتالوج |
+
+---
+**اقرأ بعده:** [دراسة حالة: توحيد هاش/شفّر/فك_تشفير](crypto-unification.md) —
+الفصلُ التالي في الفهرس، وهو أخفُّ ويُري التوحيدَ نفسَه من زاويةِ مكتبةٍ لا خلفيّة ·
+أو اقفز إلى [نظام الأنواع وفاحص الأنواع](../systems/types.md).
diff --git a/src/backend/sir.md b/src/backend/sir.md
index 2f41c3b..551168f 100644
--- a/src/backend/sir.md
+++ b/src/backend/sir.md
@@ -7,7 +7,7 @@
توليد LLVM IR. يفصل دلالة لغة ص (الملكية، الأنواع، تدفّق التحكّم) عن تفاصيل LLVM.
## لماذا طبقة وسيطة؟
-- **تحسين مستقلّ:** `SIROptimizer` يطبّق تمريرات على SIR.
+- **تحسين مستقلّ:** المُحسِّن `Sad::Compiler::Optimizer::Optimizer` يطبّق تمريراتٍ على SIR.
- **تشخيص أسهل:** SIR dumps أوضح من LLVM IR الخام.
- **عزل:** تغيير الواجهة الخلفيّة (LLVM) لا يَمَسّ منطق بناء SIR.
- **دلالة الملكية:** SIR يدعم تعليمات ملكية (ownership) خاصّة بلغة ص.
@@ -16,13 +16,14 @@
| الملف | المحتوى |
|------|---------|
| `compiler/include/frontend/sir_types.h` | تعداد `SIROpcode` + أنواع SIR (الملكية) |
-| `compiler/src/frontend/` | `SIRBuilder` (AST → SIR) + `SIROptimizer` |
+| `compiler/src/frontend/` | `SIRBuilder` (AST → SIR) + بانياتُه في `builders/` |
+| `compiler/include/sir_optimizer/` · `compiler/src/sir_optimizer/` | `Optimizer` + تمريراتُه (`cse_pass` · `licm_pass` · `sroa_pass` · `dead_code_elimination_pass` · …) |
## الموضع في الخطّ
```mermaid
flowchart LR
AST --> SB["SIRBuilder"] --> SIR["وحدة SIR"]
- SIR --> SO["SIROptimizer"] --> SIR2["SIR محسَّن"]
+ SIR --> SO["Optimizer
(sir_optimizer/)"] --> SIR2["SIR محسَّن"]
SIR2 --> CG["LLVMCodeGen"] --> IR["LLVM IR"]
```
@@ -38,8 +39,8 @@ flowchart LR
## تخفيض مطابقة الأنماط (`طابق`)
-يُخفَّض `طابق` في الواجهة الأماميّة (`sir_builder_match_patterns.cpp` +
-`builders/statement_match.cpp`) — **لا** في الواجهة الخلفيّة. الملفّ الخلفيّ
+يُخفَّض `طابق` في الواجهة الأماميّة (`compiler/src/frontend/sir_builder_match_patterns.cpp` +
+`compiler/src/frontend/builders/statement_match.cpp`) — **لا** في الواجهة الخلفيّة. الملفّ الخلفيّ
`pattern_codegen*.cpp` (`generateMatchCode`) **ميّتٌ تمامًا (صفر مستدعٍ)** رغم بقائه في
البناء؛ لا تُضِف إليه.
diff --git a/src/backend/vm.md b/src/backend/vm.md
deleted file mode 100644
index 074e6e2..0000000
--- a/src/backend/vm.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# الآلة الافتراضية (VM)
-
-> **ماذا ستتعلّم:** دور الـVM في لغة ص وعلاقتها بالمفسّر.
-
-## الدور
-`vm/` آلة **بايت كود** مرتبطة مباشرةً بالمفسّر — مسار تنفيذ بديل يجمع بين سرعة أعلى من
-المشي الشجريّ الصرف ومرونة التفسير، دون المرور بـLLVM/الترجمة الكاملة.
-
-## الموضع
-```mermaid
-flowchart LR
- AST --> INT["InterpreterCore"]
- INT <-->|ربط مباشر| VM["VM (بايت كود)"]
- AST -.->|مسار منفصل| SIR["SIR → LLVM (sadc)"]
-```
-
-## وقت التشغيل والربط
-- `runtime/` يوفّر ABI/FFI مستقلّ (freestanding) + ربط VM.
-- القنوات/الخيوط الخفيفة (goroutines) آمنة للتزامن عبر mutex داخليّ في `SadChannel`.
-
-> هذه الطبقة أقلّ سطحًا للمساهمات الجديدة من المفسّر/المترجم؛ ابدأ منهما عادةً.
-> هذا الفصل **قيد التوسعة** — ساهم بتفاصيل بنية البايت كود إن عملت عليها.
-
----
-**اقرأ بعده:** [نظام الأنواع](../systems/types.md).
diff --git a/src/frontend/comprehensions.md b/src/frontend/comprehensions.md
index b773214..541b32c 100644
--- a/src/frontend/comprehensions.md
+++ b/src/frontend/comprehensions.md
@@ -69,8 +69,8 @@ flowchart TD
> **فخّ:** الترتيب البايثونيّ القديم (`[تعبير لكل …]`) لم يعد يُبنى كاستيعاب — يُحلَّل
> كمصفوفة عاديّة ثمّ يتعثّر عند `لكل`. حُذفت دالّتا `parseListComprehension`/
> `parseDictComprehension` القديمتان من **مسار المحلّل الحيّ** (`parser_helpers.cpp`).
-> (تبقى نسخة بالترتيب القديم في `shared/parser/src/specs/flow/parser_comprehension.cpp`
-> لكنّها نموذج ميت **غير مُترجَم** — لا إحالة إليه في CMake؛ يُنظَّف في طور لاحق.)
+> (وكانت تبقى نسخةٌ بالترتيب القديم في `shared/parser/src/specs/flow/parser_comprehension.cpp`
+> نموذجًا ميتًا غيرَ مُترجَم — **حُذفت من الشجرة**؛ لم يعد للمسار وجودٌ في `dev`.)
---
@@ -110,7 +110,9 @@ flowchart TD
> **لماذا بانٍ منفصل للمجموعة؟** إزالة التكرار تُدخِل حلقة مسح داخليّة متداخلة
> (كتل `scan_cond`/`scan_body`/`scan_found`/`scan_next`/`scan_done`/`append`) تضاعف
-> حجم البانِي، فلا تتقاسم بنية List/Dict المستقيمة؛ ويشارك الملفّ `buildExprGenerator`.
+> حجم البانِي، فلا تتقاسم بنية List/Dict المستقيمة. (ترويسةُ الملفّ ما زالت تذكر
+> «SetComp and Generator» تاريخيًّا، لكنّ `buildExprGenerator` حُذف في تمّوز ٢٠٢٦
+> (#205) — فالملفّ اليومَ يحمل `buildExprSetComp` وحدَها.)
نقاط تنفيذ دقيقة في بانِي المجموعة:
@@ -152,10 +154,6 @@ flowchart TD
> عدديّة النوع)، فالمجموعات الصحيحة الإزالة للأعداد؛ مجموعات النصوص/العشريّ تتباعد
> صامتًا حتى يُعمَّم النوع في الاستيعابات الثلاثة.
-> **فخّ متبقٍّ:** `buildExprGenerator` في نفس الملفّ ما زال بالنهج المكسور (`CALL
-> __sad_len`/`__sad_array_push` غير المعرَّفة) — سينهار الربط متى استُخدم مولِّد؛ خارج
-> نطاق م1ب، يُتابَع بنفس نمط الإصلاح.
-
---
## فكّ الزوج والتكرار على الخرائط (RFC 25 التعارض 1أ)
diff --git a/src/frontend/lexer.md b/src/frontend/lexer.md
index 28a8a4b..9dac93c 100644
--- a/src/frontend/lexer.md
+++ b/src/frontend/lexer.md
@@ -42,7 +42,7 @@ flowchart TD
| `ح"` (نصّ خام) | `0xD8 0xAD` + `"` | `STRING_RAW` | [L1675](https://github.com/sadlang/s-programming-language/blob/dev/shared/lexer/src/lexer_core.cpp#L1675) |
| `م"` / `ص"` (نصّ منسَّق) | `0xD9 0x85` / `0xD8 0xB5` + `"` | `STRING_FSTRING` | [L1694](https://github.com/sadlang/s-programming-language/blob/dev/shared/lexer/src/lexer_core.cpp#L1694) |
| `×` ضرب | `0xC3 0x97` | `OP_MULTIPLY` | [L1726](https://github.com/sadlang/s-programming-language/blob/dev/shared/lexer/src/lexer_core.cpp#L1726) |
-| `،` فاصلة | `0xD8 0x8C` | `ARABIC_COMMA` | [L1743](https://github.com/sadlang/s-programming-language/blob/dev/shared/lexer/src/lexer_core.cpp#L1746) |
+| `،` فاصلة | `0xD8 0x8C` | `ARABIC_COMMA` | [L1746](https://github.com/sadlang/s-programming-language/blob/dev/shared/lexer/src/lexer_core.cpp#L1746) |
| `؛` منقوطة | `0xD8 0x9B` | `ARABIC_SEMICOLON` | [L1753](https://github.com/sadlang/s-programming-language/blob/dev/shared/lexer/src/lexer_core.cpp#L1753) |
| `؟` استفهام | `0xD8 0x9F` | `QUESTION` (و`؟.`→`QUESTION_DOT`) | [L1760](https://github.com/sadlang/s-programming-language/blob/dev/shared/lexer/src/lexer_core.cpp#L1760) |
diff --git a/src/frontend/parser.md b/src/frontend/parser.md
index ea5442f..f283241 100644
--- a/src/frontend/parser.md
+++ b/src/frontend/parser.md
@@ -8,41 +8,41 @@
## البنية
`Sad::Parser::ParserCore` محلل **نزوليّ تعاوديّ** يحوّل تيار الرموز إلى AST. كل قاعدة ≈
دالة `parseXxx()`. الكود موزّع على `core/`، `statements/`، `declarations/`، `specs/`، `ui/`.
-التهيئة ([`ParserCore::ParserCore`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_main.cpp#L42)) تجلب **رمزين مسبقًا** (`current_`, `nextToken_`)
+التهيئة ([`ParserCore::ParserCore`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_main.cpp#L46)) تجلب **رمزين مسبقًا** (`current_`, `nextToken_`)
وتتخطّى الفراغات/التعليقات وتجمّع تعليقات `##` المعلّقة.
## نقطة الدخول والموزِّعات
```mermaid
flowchart TD
- P["parseProgram() — L124"] -->|while !isAtEnd| D["parseDeclaration() — L364"]
+ P["parseProgram() — L137"] -->|while !isAtEnd| D["parseDeclaration() — L343"]
D -->|كلمة تصريح| DECL["دالة/صنف/متغيّر/تعداد/استيراد/…"]
- D -->|@| DIR["tryParseDirective() — L1479"]
- D -->|غير ذلك| S["parseStatement() — L1173"]
+ D -->|@| DIR["tryParseDirective() — L1588"]
+ D -->|غير ذلك| S["parseStatement() — L1241"]
S -->|كلمة جملة| CF["إذا/بينما/لكل/طابق/حاول/…"]
S -->|افتراضي| ES["parseExpressionStmt() → parseExpression()"]
```
-- [`parseProgram()`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_main.cpp#L124) — يكرّر `parseDeclaration` حتى نهاية الملف، مع **حماية من الحلقة اللانهائيّة** (`MAX_STUCK_ITERATIONS=3`) وعدّ الدوال الرئيسيّة.
-- [`parseDeclaration()`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_main.cpp#L364) — موزّع التصريحات (~33 فرعًا): توجيهات `@`، مُزخرِفات، سمات `[[..]]`، استورد/من/صدّر/خارجي، دالة/مولد/async، قالب/فضاء، صنف/سمة/نفّذ/امتداد/ماكرو/نوع/عقد، متغير/ثابت، تصريح ببدء النوع/الصنف، اختبر/حالة/اعرض، تعداد/بنية، وأخيرًا `parseStatement`.
-- [`parseStatement()`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_main.cpp#L1173) — موزّع الجمل: إذا/بينما/لكل/حالة/طابق/ارجع/أنتج/باستخدام/أجّل/أطلق/اختر/توقف/استمر/`{`/حاول/ارمي، وافتراضيًّا جملة تعبير.
+- [`parseProgram()`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_main.cpp#L137) — يكرّر `parseDeclaration` حتى نهاية الملف، مع **حماية من الحلقة اللانهائيّة** (`MAX_STUCK_ITERATIONS=3`) وعدّ الدوال الرئيسيّة.
+- [`parseDeclaration()`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_main.cpp#L343) — موزّع التصريحات (~33 فرعًا): توجيهات `@`، مُزخرِفات، سمات `[[..]]`، استورد/من/صدّر/خارجي، دالة/مولد/async، قالب/فضاء، صنف/سمة/نفّذ/امتداد/ماكرو/نوع/عقد، متغير/ثابت، تصريح ببدء النوع/الصنف، اختبر/حالة/اعرض، تعداد/بنية، وأخيرًا `parseStatement`.
+- [`parseStatement()`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_main.cpp#L1241) — موزّع الجمل: إذا/بينما/لكل/حالة/طابق/ارجع/أنتج/باستخدام/أجّل/أطلق/اختر/توقف/استمر/`{`/حاول/ارمي، وافتراضيًّا جملة تعبير.
## سلسلة أسبقيّة التعابير
من الأدنى ربطًا (أعلى المستوى) إلى الأعلى — كل دالة تستدعي الأعلى أسبقيّةً ثم تحلّق على عاملها:
| المستوى | الدالة | العامل |
|---------|--------|--------|
-| 1 | [`parsePipeline`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L51) | `\|>` |
-| 2 | [`parseAssignment`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L103) | `= := += -= *= /= //= %=` |
-| 3 | [`parseTernary`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L378) | `? :` |
+| 1 | [`parsePipeline`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L50) | `\|>` |
+| 2 | [`parseAssignment`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L100) | `= := += -= *= /= //= %=` |
+| 3 | [`parseTernary`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L369) | `? :` |
| 4 | `parseNullCoalesce` | `??` |
| 5–10 | `parseLogicalOr/And` · `parseBitwiseOr/Xor/And` | `\|\| && \| ^ &` |
| 11–12 | `parseEquality` · `parseComparison` | `== != < <= > >= في` |
-| 13 | [`parseRange`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L594) | `..` |
+| 13 | [`parseRange`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L584) | `..` |
| 14–15 | `parseTerm` · `parseFactor` | `+ - << >>` · `* / // %` |
-| 16 | [`parseUnary`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L675) | `! - ~ ++ -- &`(استعارة) |
+| 16 | [`parseUnary`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L665) | `! - ~ ++ -- &`(استعارة) |
| 17 | `parsePower` | `**` (يمينيّ) |
-| 18 | [`parsePostfix`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L747) | `() . ?. [] ++ -- !()` |
-| 19 | [`parsePrimary`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L1116) | القيم الذريّة |
+| 18 | [`parsePostfix`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L737) | `() . ?. [] ++ -- !()` |
+| 19 | [`parsePrimary`](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L1149) | القيم الذريّة |
هذا الترتيب **يُعرّف أسبقيّة العوامل** — ومصدره `language-truth/operators.yaml`.
@@ -64,7 +64,7 @@ if (match(TT::KEYWORD_TRAIT) ||
## السكر النحوي (Desugaring)
يُحوِّل المحلل بعض الصياغة وقت التحليل:
-- الأنبوب: `أ |> د` ← `د(أ)` · `أ |> د(ب)` ← `د(أ، ب)` ([parsePipeline L70](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L70)).
+- الأنبوب: `أ |> د` ← `د(أ)` · `أ |> د(ب)` ← `د(أ، ب)` ([إزالةُ السكّر في `parsePipeline` L67](https://github.com/sadlang/s-programming-language/blob/dev/shared/parser/src/core/parser_expressions.cpp#L67)).
- الإسناد المركّب: `س += ص` ← `س = س + ص` (يعيد بناء طرف القراءة للحقول/الفهارس المتداخلة).
- القيمة المطلقة: `|تعبير|` ← `abs(تعبير)`.
diff --git a/src/getting-started/repo-map.md b/src/getting-started/repo-map.md
index 272fb27..d28a392 100644
--- a/src/getting-started/repo-map.md
+++ b/src/getting-started/repo-map.md
@@ -14,9 +14,8 @@ s-programming-language/
├── compiler/ ← المترجم: AST → SIR → LLVM IR → تنفيذيّ
│ ├── src/frontend/ ← SIRBuilder + sir_types.h (opcodes الملكية)
│ └── src/backend/llvm/ ← LLVMCodeGen + builders
-├── vm/ ← الآلة الافتراضية (بايت كود مرتبط بالمفسّر)
├── stdlib/ ← المكتبة القياسية (core/io/math/string/network/graphics)
-├── runtime/ ← ABI/FFI المستقلّ + ربط VM
+├── runtime/ ← ABI/FFI المستقلّ + الوضع الحرّ (freestanding)
├── tools/ ← sadinfo · lsp · formatter · pkg · repl · compiler(sadc CLI)
├── language-truth/ ← ⭐ مصدر الحقيقة الموحّد (YAML)
│ ├── keywords.yaml · operators.yaml · types.yaml · directives.yaml
diff --git a/src/introduction.md b/src/introduction.md
index 2337216..beaaf0b 100644
--- a/src/introduction.md
+++ b/src/introduction.md
@@ -28,7 +28,7 @@
⚡الواجهة الخلفيّة
- المفسّر · SIR · LLVM · VM.
+ المفسّر · SIR · LLVM.
🌿المساهمة
diff --git a/src/sot/codegen.md b/src/sot/codegen.md
index 23dba73..251b427 100644
--- a/src/sot/codegen.md
+++ b/src/sot/codegen.md
@@ -12,12 +12,18 @@ flowchart LR
```
## المولّدات (`scripts/codegen/`)
+
+> 📏 **المقيس على `dev`:** **79** ملفَّ بايثون في `scripts/codegen/`، منها **31** بالبادئة
+> `gen_` (مولِّد فعليّ) و**22** بالبادئة `check_` (حرّاسٌ وفاحصون)، و**5** في `_lib/`
+> (مكتباتٌ مساعدة)، والباقي (21) اختباراتُ `test_*` وسكربتاتُ ترحيلٍ لمرّةٍ واحدة.
+> الجدولُ أدناه عيّنةٌ تشرح النمط، لا جردًا كاملًا — الجردُ في المجلّد نفسِه.
+
| المولّد | المصدر → الناتج |
|--------|------------------|
| `gen_keywords.py` | `keywords.yaml` → `keywords_generated.{h,cpp}` |
| `gen_types.py` | `types.yaml` → كود الأنواع المُولَّد |
| `gen_builtins_registry.py` / `gen_all_builtins_yaml.py` | `builtins/` → `builtin_registry_generated.h` |
-| `gen_error_messages.py` / `gen_sadinfo_errors.py` | `errors/` → رسائل/تشخيص مُولَّد |
+| `gen_error_messages.py` | `errors/` → رسائل/تشخيص مُولَّد (أداةُ `sadinfo` ومولِّدُها `gen_sadinfo_errors.py` تقاعدا في تمّوز ٢٠٢٦ — #144) |
| `gen_parser_grammar_docs.py` | `grammar/*.yaml` → `docs/parser_rule/_generated/` |
| `check_grammar_conformance.py` | يفحص تغطية القواعد وتماسك وسوم الاختبارات |
diff --git a/src/sot/language-truth.md b/src/sot/language-truth.md
index e130ea6..ee2d3b6 100644
--- a/src/sot/language-truth.md
+++ b/src/sot/language-truth.md
@@ -14,9 +14,15 @@ language-truth/
├── errors/ ← رموز ورسائل الأخطاء (مصدر V5)
├── grammar/ ← ⭐ قواعد الإنتاج النحويّة (SoT) — انظر فصلها
├── _schemas/ ← مخطّطات JSON للتحقّق من كل ملف
-└── _meta/ · _notation/ · learning/ · stdlib/ · tests/
+└── _meta/ · learning/ · stdlib/ · tests/ · backend/ · dialects/ · tools/
```
+> 📏 **المقيس على `dev`:** جذرُ `language-truth/` فيه **18** ملفَّ YAML و**11** مجلّدًا
+> وملفَّي توثيق (`README.md` · `VERSIONING.md`) — 31 مدخلًا في الجملة. والشجرةُ أعلاه عيّنةُ توجيهٍ لا جردًا: `backend/` (جداولُ
+> الخلفيّة الأصليّة — انظر [فصلها](../backend/native.md)) و`dialects/` و`tools/`
+> أُضيفت بعد كتابة الفصل، وثمانيةُ ملفّات `ui_*.yaml` تعيش في الجذر أيضًا. ولا وجودَ
+> لمجلّد `_notation/` في الجذر: الترميزُ ملفٌّ واحدٌ داخل القواعد، `grammar/_notation.yaml`.
+
## أمثلة على الصيغة
**كلمة مفتاحيّة** (`keywords.yaml`):
```yaml
diff --git a/src/status.md b/src/status.md
index 4666640..a5301b3 100644
--- a/src/status.md
+++ b/src/status.md
@@ -10,18 +10,20 @@
| مصدر الحقيقة (فلسفة · language-truth · codegen · grammar SoT) | ✅ مكتمل | الميزة المميِّزة |
| الأماميّة (معجمي · نحوي · AST) | ✅ مكتمل | |
| الخلفيّة: مفسّر · SIR · LLVM | ✅ مكتمل | |
-| الخلفيّة: VM | 🚧 قيد التوسعة | يحتاج تفصيل بنية البايت كود |
+| الخلفيّة الأصليّة (بلا LLVM) | ✅ مكتمل | خمس معماريّات · درجتا القياس · حرّاس المُنادي |
+| الخلفيّة: VM | 🗑️ مُزال فصله | `vm/` حُذف من الشجرة (`bcf0a746`) «ستُعاد كتابتها من الصفر» — لا يُكتب الفصل قبل الكود |
| الأنظمة (أنواع · أخطاء · مضمنة) | ✅ مكتمل | |
| المساهمة (سير العمل · DoD · الحوكمة) | ✅ مكتمل | |
| مزامنة الدليل (Freshness + كاشف الانجراف) | ✅ مكتمل | فحص آليّ أسبوعيّ |
## خارطة الطريق (مقترَحة)
-- [ ] **توسعة VM:** تنسيق البايت كود، حلقة التنفيذ، الربط بالمفسّر.
+- [x] **الخلفيّة الأصليّة (بلا LLVM):** → [الفصل](backend/native.md).
+- [ ] **إعادة توثيق VM:** يُكتب الفصل من الكود عند إعادة كتابة الطبقة، لا قبلها.
- [x] **مزامنة الدليل مع اللغة:** بيان ربط + كاشف انجراف + فحص أسبوعيّ → [Freshness](contributing/freshness.md).
- [ ] **جسر آليّ لقواعد المحلل:** تضمين/مزامنة `docs/parser_rule/_generated/` داخل الدليل.
- [ ] **فصل الأدوات:** LSP · المنسّق · مدير الحزم (pkg) · sadinfo.
- [ ] **فصل stdlib:** بنية المكتبة القياسية ووحداتها.
-- [ ] **فصل runtime/FFI:** ABI المستقلّ وربط VM.
+- [ ] **فصل runtime/FFI:** ABI المستقلّ (`runtime/`) والوضع الحرّ (freestanding).
- [ ] **أمثلة «دراسة حالة»:** تتبّع ميزة كاملة عبر كل الطبقات (نهاية-لنهاية).
- [ ] **ترجمة إنجليزية** اختياريّة (i18n).
diff --git a/src/systems/builtins.md b/src/systems/builtins.md
index e48e3b8..826284e 100644
--- a/src/systems/builtins.md
+++ b/src/systems/builtins.md
@@ -3,7 +3,12 @@
> **ماذا ستتعلّم:** كيف تُعرَّف الدوال المضمنة كمصدر موحّد، وأين تُنفَّذ في المفسّر والمترجم.
## التصنيفان
-- **تلقائيّة (بلا استيراد، ~21):** إخراج (`اطبع`/`اطبع_سطر`)، إدخال (`اقرأ`)، طول/نوع
+> 📏 **المقيس من الكتالوج (`language-truth/builtins/`، فرع `dev`):** **1205** مضمنةً
+> إجماليًّا، منها **865** بحقل `require_import: false`. والرقمُ الأخيرُ يشمل مضمناتِ
+> العتاد والنواة (`acpi_*` · `apic_*` · `uefi_*`)، فلا تقرأه «ما يستعمله المبرمج يوميًّا».
+> العدّادُ الوحيدُ الصادقُ هو الكتالوج — لا تنسخ عددًا نثرًا في موضعٍ ثانٍ.
+
+- **تلقائيّة (بلا استيراد):** المجموعةُ اليوميّةُ منها ~21: إخراج (`اطبع`/`اطبع_سطر`)، إدخال (`اقرأ`)، طول/نوع
(`طول`/`نوع`)، تحويل (`رقم`/`عشري`/`نص`/`منطقي`)، تزامن (`قناة`/`مجموعة_انتظار`/`قفل`/`مستقبل`).
- **طرق على الأنواع:** مصفوفات (`.اضف`/`.رتب`/`.خريطة`/…)، نصوص (`.تقسيم`/`.استبدل`/…)، خرائط، قنوات.
- **وحدات تحتاج استيراد:** `رياضيات`، `نصوص`، `أساسيات`، `خرائط`، `شبكة_عالية`، `تشفير`، `مقابس`، …
diff --git a/src/systems/errors.md b/src/systems/errors.md
index 03ba3c7..8bc5945 100644
--- a/src/systems/errors.md
+++ b/src/systems/errors.md
@@ -71,6 +71,18 @@ flowchart TB
فئاتٌ إضافيّة لها ملفّاتُها: `import` · `io` · `ownership` (يربط [نظام الذاكرة](memory.md)) ·
`internal` (ICE).
+> 📏 **المقيس على `dev`:** كتالوجُ `language-truth/errors/` **ثمانيةُ ملفّات**، لكنّ
+> **خمسةً** منها فقط تحمل رموزًا: `lexical` (6) · `syntactic` (32) · `semantic` (48) ·
+> `runtime` (74) · `internal` (23) = **183** رمزًا. أمّا `import` و`io` و`ownership`
+> فملفّاتُ إحالةٍ بـ`errors: []` — أخطاؤها مُصنَّفةٌ تحت `runtime` (مثل `RUN008`
+> للاستيراد)، أُبقيت لتوثّق الإحالة لا لتُكرِّر الرمز.
+>
+> ويقابلُ الـ183 في `shared/errors/include/error_codes.h` **183** عضوًا في
+> `enum class ErrorCode`، كلُّ عضوٍ موثَّقٌ بتعليقٍ يحمل رمزَه المرقَّم
+> (`///< SEM002: …` · `///< RUN008: …` — لا وسمَ حرفيًّا اسمُه `CODE`). فلا عضوَ بلا
+> رمز، ولا رمزَ بلا عضو. النطاقاتُ أعلاه حدودٌ معماريّة لا أعدادٌ فعليّة — فئةٌ لم تبلغ
+> 099 ليست ناقصة.
+
## ③ دورة حياة الخطأ: من الإطلاق إلى العرض
الطبقة تُطلِق رمزًا + قوالبَ + موقعًا؛ يجمعها `ErrorManager` في `DiagnosticSink`، ثم يُبنى
diff --git a/src/systems/memory.md b/src/systems/memory.md
index 14edd35..eac63d4 100644
--- a/src/systems/memory.md
+++ b/src/systems/memory.md
@@ -15,7 +15,7 @@
```mermaid
flowchart TB
CODE["كود .ص نفسه"]
- CODE --> DEV["وضع التطوير (--gc)
GC تلقائيّ · بلا تفكير في الملكيّة
مثاليّ لـREPL والتجريب"]
+ CODE --> DEV["وضع التطوير (--جامع)
GC تلقائيّ · بلا تفكير في الملكيّة
مثاليّ لـREPL والتجريب"]
CODE --> PROD["وضع الإنتاج (--إنتاج)
ملكيّة صارمة كـRust · صفر overhead
فحص الاستعارة وقت الترجمة"]
DEV -. "المترجم يقترح تحويلات للملكيّة" .-> PROD
```
@@ -69,11 +69,11 @@ flowchart LR
| الإعداد المسبق | `mode` | `gcStrategy` | `ownershipMode` | اقتراحات | كشف دورات | مُعلِّم |
|----------------|--------|--------------|-----------------|:--------:|:---------:|:------:|
-| `gcDefaults()` (`--gc`) | Development | **Tracing** | Disabled | ✗ | ✓ | ✗ |
+| `gcDefaults()` (`--جامع`) | Development | **Tracing** | Disabled | ✗ | ✓ | ✗ |
| `developmentDefaults()` | Development | ReferenceCounting | Warnings | ✓ | ✓ | ✓ |
| `productionDefaults()` (`--إنتاج`) | Production | **None** | **UltraStrict** | ✗ | ✗ | ✗ |
| `learningDefaults()` (`--تعلم`) | Development | ReferenceCounting | Warnings | ✓ | ✓ | ✓ |
-| `kernelDefaults()` (`--نواة`) | Production | None | UltraStrict | ✗ | ✗ | حدّ=0 |
+| `kernelDefaults()` (`--حرّ`) | Production | None | UltraStrict | ✗ | ✗ | حدّ=0 |
> 📌 **النواة (`no_std`):** عند `#![بلا_مكتبة_قياسية]` يُفرَض `kernelDefaults` — لا GC إطلاقًا
> (`gcMemoryLimitMB = 0`)، ملكيّة `UltraStrict`، بلا اقتراحات ولا كشف دورات. ملكيّةٌ صرفة
@@ -82,35 +82,52 @@ flowchart LR
## من العلَم إلى السلوك: `MemoryModeFlag`
[`MemoryModeFlag::parse()`](https://github.com/sadlang/s-programming-language/blob/dev/shared/memory_policy/include/memory/policy/memory_mode_flag.h) يقرأ `argv` ويبني `MemoryModeSettings`.
-الأعلام مسجَّلة في `flagHandlers_` ([`initializeFlags()`](https://github.com/sadlang/s-programming-language/blob/dev/shared/memory_policy/src/memory_mode_flag.cpp#L142))، ولكلّ علَمٍ عربيٍّ مرادفاتٌ إنجليزيّة ومختصرة:
+الأعلام مسجَّلة في `flagHandlers_` ([`initializeFlags()`](https://github.com/sadlang/s-programming-language/blob/dev/shared/memory_policy/src/memory_mode_flag.cpp#L54))،
+وهي **مبنيّةٌ كلُّها من مصدر الحقيقة** ([`cli_flags.yaml`](https://github.com/sadlang/s-programming-language/blob/dev/language-truth/cli_flags.yaml)،
+عائلة `memory`) لا مكتوبةً يدويًّا: التسمية تأتي من الجدول، ولا يبقى في C++ إلّا السلوك
+(`switch` على `FlagAction`).
+
+> ⚠️ **اسمٌ عربيٌّ قانونيٌّ وحيدٌ لكلّ مفهوم — لا مرادفات ولا اختصارات ولا توافقَ خلفيّ.**
+> أُلغي 18 مرادفًا إنجليزيًّا/مختصرًا (`--gc` · `--no-std` · `--freestanding` · `--kernel` ·
+> `--production`/`-p` · `--learn`/`-l` · `--auto`/`-a` · …)؛ يضبط المُهيِّئ
+> `shortName = ""` و`longNameEnglish = longNameArabic`. فإن قرأت في وثيقةٍ أقدم علَمًا
+> لاتينيًّا لسياسة الذاكرة، فهو **لم يعد يُقبَل**.
```mermaid
flowchart TD
ARGV["argv[] / متغيّرات البيئة / ملف التهيئة"] --> PARSE["MemoryModeFlag::parse()"]
PARSE --> H{"تصنيف العلَم"}
- H -->|"--إنتاج / --production / -p"| PROD["productionDefaults"]
- H -->|"--gc / --dev*(مهجور)"| GCD["gcDefaults"]
- H -->|"--تعلم / --learn / -l"| LRN["learningDefaults"]
- H -->|"--نواة / --no-std / --kernel"| KRN["kernelDefaults"]
- H -->|"--تلقائي / --auto / -a"| AUTO["اكتشاف بالسياق"]
- H -->|"--ملكية= / --gc-strategy= / --حد_ذاكرة="| TUNE["ضبطٌ دقيقٌ فوق الإعداد المسبق"]
+ H -->|"--إنتاج"| PROD["productionDefaults"]
+ H -->|"--جامع"| GCD["gcDefaults"]
+ H -->|"--تعلم"| LRN["learningDefaults"]
+ H -->|"--حرّ"| KRN["kernelDefaults + noStdRequested"]
+ H -->|"--تلقائي"| AUTO["اكتشاف بالسياق"]
+ H -->|"--ملكية= · --جامع=استراتيجية · --حد-الذاكرة="| TUNE["ضبطٌ دقيقٌ فوق الإعداد المسبق"]
+ H -->|"علَمٌ مُزال (--dev · --hybrid · --mixed …)"| REJ["فشلُ تحليلٍ صريح
(لا تحويلَ صامت)"]
PROD & GCD & LRN & KRN & AUTO & TUNE --> OUT["MemoryModeSettings ← FlagParseResult"]
```
-**جدول الأعلام الرئيسيّة** (عربيّ ← مرادفات):
-
-| العربيّ | المرادفات | الأثر |
-|---------|-----------|-------|
-| `--إنتاج` | `--production` · `--prod` · `--release` · `-p` | ملكيّة صارمة، بلا GC |
-| `--gc` | `--dev`*، `--development`*، `--تطوير`*، `-d`* | GC (يحلّ محلّ `--dev` المهجور) |
-| `--تعلم` | `--learn` · `--learning` · `-l` | GC + تحذيرات + رسائل تعليميّة |
-| `--نواة` | `--no-std` · `--kernel` · `--freestanding` · `--بلا-مكتبة-قياسية` | ملكيّة صرفة `no_std` |
-| `--ملكية=` | `--ownership=` | يضبط `OwnershipMode` يدويًّا |
-| `--gc-strategy=` | — | يختار `GCStrategy` |
-| `--حد_ذاكرة=` | `--gc-memory-limit=` | حدّ ذاكرة الـGC بالميغابايت |
-
-> 🔁 `--dev`/`--تطوير`/`--mixed` تُحوَّل جميعها إلى `--gc` (تنبيهُ إهجار) — انظر جدول
-> الإهجار في [`memory_mode_flag.cpp`](https://github.com/sadlang/s-programming-language/blob/dev/shared/memory_policy/src/memory_mode_flag.cpp#L281).
+**عائلة `memory` كاملةً على `dev`** (عشرةُ أعلام — لا غيرها):
+
+| العلَم | النوع | الأثر (`sets`) |
+|--------|-------|-----------------|
+| `--إنتاج` | راية | `productionDefaults` — ملكيّة صارمة، بلا جامع |
+| `--جامع[=استراتيجية]` | قيمة اختياريّة | `gcDefaults`؛ ومع قيمةٍ يضبط `gcStrategy` |
+| `--تعلم` | راية | `learningDefaults` — جامع + تحذيرات + رسائل تعليميّة |
+| `--حرّ` | راية | `kernelDefaults + noStdRequested` — ملكيّة صرفة بلا مكتبة قياسيّة |
+| `--تلقائي` | راية | `MemoryMode::Auto` — اكتشافٌ بالسياق |
+| `--ملكية=` | قيمة | `ownershipMode` (`off\|warnings\|strict\|ultra`) |
+| `--حد-الذاكرة=` | قيمة | `gcMemoryLimitMB` — حدّ ذاكرة الجامع بالميغابايت |
+| `--اقتراحات` | راية | `enableOwnershipSuggestions` |
+| `--كشف-دورات` | راية | `enableCycleDetection` |
+| `--تصحيح-الذاكرة` | راية | `DebugMemory` |
+
+> 🛑 **الأعلام المُزالة تُرفَض، لا تُترجَم.** `--dev` · `--development` · `-d` · `--تطوير` ·
+> `--hybrid` · `--mixed` · `--مختلط` كلُّها في جدول `deprecatedFlags`
+> ([`memory_mode_flag.cpp`](https://github.com/sadlang/s-programming-language/blob/dev/shared/memory_policy/src/memory_mode_flag.cpp#L174))،
+> لكنّ الجدول **لا يُحوِّلها**: يضبط `result.success = false` ويُصدِر «أُزيل نهائيًّا في
+> Phase E-3، استخدم `--gc` بديلًا». الإحلالُ المذكور في الرسالة إرشادٌ للقارئ، لا
+> تحويلٌ يجريه المُحلِّل — والبديلُ القانونيُّ اليومَ `--جامع`.
## ترتيب الأولويّة في حسم الإعداد
diff --git a/src/systems/types.md b/src/systems/types.md
index f0d21cc..c3f19c3 100644
--- a/src/systems/types.md
+++ b/src/systems/types.md
@@ -24,7 +24,8 @@
## ① مصدر الحقيقة: `SadTypeKind` (مولَّد)
-التعداد `SadTypeKind` **يُولَّد آليًّا** من [`language-truth/types.yaml`](../sot/language-truth.md) (52 قيمة) —
+التعداد `SadTypeKind` **يُولَّد آليًّا** من [`language-truth/types.yaml`](../sot/language-truth.md) (**49 قيمة**، والعددُ نفسُه
+مولَّدٌ ثابتًا `SAD_TYPE_KIND_COUNT` — لا تنسخه نثرًا في موضعٍ ثانٍ) —
لا يُحرَّر يدويًّا. أيّ نوعٍ جديد يُضاف إلى الكتالوج ثم يُعاد التوليد:
```mermaid
@@ -36,7 +37,8 @@ flowchart LR
SYS --> INT["المفسّر (Value)"]
```
-القيم موزَّعة على عائلات: **أوّليّة** (Void · Integer · Float · Boolean · String · Byte · Char) ·
+القيم موزَّعة على عائلات: **أوّليّة** (Void · Integer · Float · Boolean · String) ·
+**أوّليّة محدَّدة الحجم** (Int8 · Int16 · Int32 · UInt8 · UInt16 · UInt32 · UInt64 · Float32 · Char) ·
**مركّبة** (Array · Map · Tuple · Slice) · **معرَّفة مستخدِمًا** (Class · Struct · Enum · Trait) ·
**قابلة للاستدعاء** (Function · Closure) · **جبريّة** (Union · Intersection · Optional · Result) ·
**عامّة** (Generic · TypeParameter · TypeAlias) · **مراجع** (Pointer · Reference · MutableRef) ·
@@ -95,9 +97,9 @@ classDiagram
| الدالة | تصدُق على |
|--------|-----------|
-| `isPrimitiveKind(k)` | الأوّليّات (عدد، عشريّ، منطقيّ، نصّ، بايت، حرف، فراغ) + الأوّليّات محدَّدة الحجم (`Int8…Char`) |
-| `isNumericKind(k)` | العدديّة (Integer · Float · Byte) + العدديّة محدَّدة الحجم (`Int8…Float64`) |
-| `isCompositeKind(k)` | المركّبة (Array · Map · Tuple · Struct · Class…) |
+| `isPrimitiveKind(k)` | `Void`/`Integer`/`Float`/`Boolean`/`String`/`UInt8` + المدى `Int8…Char` |
+| `isNumericKind(k)` | يُفوَّض إلى `sadTypeKindIsNumeric()` المولَّد عن حقل `numeric` في `types.yaml` — **لا مدًى على ترتيب التعداد** (كان `Int8…Float64`؛ أُزيل لأنّه يربط الدلالة بترتيب رأسٍ مولَّد) |
+| `isCompositeKind(k)` | `Array` · `Map` · `Tuple` · `Slice` **فقط** (لا `Struct` ولا `Class`) |
| `isCallableKind(k)` | القابلة للاستدعاء (Function · Closure) |
وعلى مستوى الكائن: `isNullable()` · `isCopyable()` (تَفصِل القيميّ عن المرجعيّ) · `isMutable()` ·
@@ -144,7 +146,7 @@ flowchart TD
| | `Value` | `SadValue` (وقت تشغيل الثنائيّ) |
|--|---------|-------------------------------|
| العالَم | المفسّر (`sad-run`) | الثنائيّ المُترجَم |
-| اللغة | صنف C++ (`shared/types/value.h`) | `struct` C (`compiler/.../llvm_runtime.h`) |
+| اللغة | صنف C++ (`shared/types/include/value.h`) | `struct` C (`compiler/include/backend/llvm/llvm_runtime.h`) |
| النوع | `SadTypeKind` + `SadTypePtr` | وسم `type` |
> ⚠️ لا يلتقيان في الذاكرة: برنامجٌ بالمفسّر لا يلمس `SadValue`، وثنائيٌّ مُترجَم لا يلمس
diff --git a/sync/sources.lock.json b/sync/sources.lock.json
index d9e8944..dee81bb 100644
--- a/sync/sources.lock.json
+++ b/sync/sources.lock.json
@@ -5,44 +5,59 @@
"sources": {
".github/BRANCH_PROTECTION_POLICY.md": "2cf24d5c67e9c2c9932ce7e9dae784d85216c4d2",
".github/skills/sad-lang-dev/references/governance.md": "9d6d0e8524cf7c27820fc0f6f25167ab2d702ed3",
- "compiler/include/frontend/sir_types.h": "2baeea3b731a20b960fd3253c708cb04de75d0cd",
+ "compiler/include/backend/native/elf64_writer.h": "8ebd8626f881e72be4d7b91b32598255a4fb9e0b",
+ "compiler/include/backend/native/sir_lowering_common.h": "259cceb18f6b2fc4ef0e978ee6e9c32ed406903e",
+ "compiler/include/backend/native/sir_native_lowering.h#L1-30": "sha256:9a217df04a7742ee",
+ "compiler/include/backend/native/x86_variable_encoder.h": "09ae23ed09b452c8802c7e1ca87852ed72f00d7e",
+ "compiler/include/frontend/sir_constants.h": "a194d187bc7c4298d07a1340adfc68ce9877b297",
+ "compiler/include/frontend/sir_types.h": "d7adf45f13c2aa9071f7a8bd36550abeeb5f0fcb",
"compiler/src/backend/llvm": "32d6a3cc07ebf51e3f2fa2933afb92f99143d06f",
+ "compiler/src/backend/llvm/builders/builtins/io_builtins_ops.cpp": "169fdb572efd32d02919dc09c5e94b4a621d3468",
+ "compiler/src/backend/llvm/builders/collections/map_ops.cpp": "40b02975f418d9db94ba3314f06a07d539c46472",
+ "compiler/src/frontend/builders/builtins_core.cpp": "d8de39cd2ec664fee6c13bbfb66ddedfa9ef79f4",
+ "compiler/src/frontend/builders/expression_comp2.cpp": "a857b9752d53eaa9a36c8a9f4ef4d4e03f5c260d",
+ "compiler/src/frontend/builders/expression_comprehensions.cpp": "48284a8c8ceea0663dbd250bbb9b0efa8ac787d8",
+ "compiler/src/frontend/builders/statement_for_range.cpp": "6345f89e25b5f426a8ea4f6a4ca836a50f1b28e4",
"interpreter/include/core/interpreter_core.h": "031ec8bc4b77e628b67615c7680897387fe821cc",
"interpreter/include/visitors/expression_evaluator.h": "a6e90c03cb75de00525fd7888bb61c91d57aa2fc",
- "interpreter/src/builtins": "a6699522fd97b4053bc4b6d39c8ad3ca7ba2e17c",
- "interpreter/src/builtins/builtin_module_crypto.cpp": "8b91ba562ce32776810bb508f0130087ea0fb1af",
- "language-truth": "13c2e41986f2a5d7b2e4897efd593d295d14e909",
- "language-truth/_schemas": "bca3eaef4997d6318feeeb4c80dafa44c454024c",
- "language-truth/builtins": "870a0daee27d07cac40aee70659b2afeb4884c80",
- "language-truth/builtins/crypto.yaml": "543ee1ecc79c6d42f791a8aeb77ad6f7df609d8e",
- "language-truth/errors": "1225323dae85f68a5b4658012b80ae6e58a61583",
- "language-truth/grammar": "efd940df914c0cb125e13f4ee9590fb5c7e677ec",
- "language-truth/keywords.yaml": "64bb3292e235b268228792c5e1fc49d1e220e56e",
- "language-truth/operators.yaml": "1b8aa3bc7fbf6269e7914f2e915612c1ca5ffe65",
- "language-truth/types.yaml": "23e4b8e9c136aa4f5b950dfff342fa8ffc509958",
- "scripts/codegen": "46007defa1b88d4aad0809aecb15803c896019fb",
+ "interpreter/src/builtins": "fd3f67280e1e90ba6f9aa680ea28896e9db14bde",
+ "interpreter/src/builtins/builtin_module_crypto.cpp": "7bb771626147ce04f7e43a715beec99bafeefc44",
+ "interpreter/src/visitors/expression_evaluator_members_advanced.cpp": "bd2003b66b8be9c340e4650b2b851c9348765191",
+ "language-truth": "c96c2155d17c2cae855b72b5ad371b583ea80ecc",
+ "language-truth/_schemas": "113cd3948583dfb130fe4169f18e4ff6c7e16cd7",
+ "language-truth/backend": "db97d27d4cc2407c977e6ff1b451040e03c62012",
+ "language-truth/builtins": "9ffea44f0a878cf2cb57d5ec6757ea973a1a7247",
+ "language-truth/builtins/crypto.yaml": "16862db43a802396baa7559521c6fd801c63a7bb",
+ "language-truth/cli_flags.yaml": "7694b926b12657541ccf3c4e3788223441d5dd92",
+ "language-truth/errors": "cae7885b8c004934ddde3e59fe0bfb6d7b6ac1b1",
+ "language-truth/grammar": "8b4d52ab1fa7574a13a8c0b87c8d4461de9b4d80",
+ "language-truth/keywords.yaml": "930d96448d776f20b1c7f75e96145e67e362de1d",
+ "language-truth/operators.yaml": "99c005878a137ceeb387de34bf937ad7ab2e0f22",
+ "language-truth/types.yaml": "73b5c1d165ec83f73b819c4d6af52333e2c217e4",
+ "scripts/codegen": "54744b199f588b1a93b08ad677a069b263c21233",
"scripts/codegen/gen_error_messages.py": "3a70f260e525f133b9a93f9919b3622e9056e871",
+ "scripts/codegen/gen_native_diagnostics.py": "f0accb963fc8f296e38c1f1d4226c0c5a5edee29",
"scripts/codegen/gen_parser_grammar_docs.py": "aaba9f37bd6d31cf0fcb190190c49fe742ad41c3",
+ "scripts/native_backend/run_native_proofs.sh": "84069b1cd325573c7336b131d37997788a4d1885",
"shared/ast/include/ast_visitor.h": "cee84846d4097724c8d62c13f036d6fc1686ee6f",
- "shared/errors/include/error_codes.h": "f3be2d763567d8381002ee1ed4f5ff9176b8a05a",
+ "shared/ast/include/expressions.h": "8c8ffe93587aa833c10890b9c4e12c2e9855825d",
+ "shared/errors/include/error_codes.h": "893d39e3bf05aaeb798d9ff46f64e347fb46dff1",
"shared/errors/include/error_manager.h": "63c70109de759eaedf809642d11681a1453db5d3",
- "shared/lexer/include/token.h": "932c37e4ca3027dac37877d4004526db2020256c",
- "shared/lexer/src/lexer_core.cpp#L100-1770": "sha256:0ffcbb9c3158f41d",
- "shared/lexer/src/lexer_keywords.cpp": "9daca47444923442007e3089e528f5966c6f8f91",
+ "shared/lexer/include/token.h": "b899691a3f715415d2cd1780ed0601b0d1ade52e",
+ "shared/lexer/src/lexer_core.cpp#L100-1770": "sha256:8b8d43f5e164f96e",
+ "shared/lexer/src/lexer_keywords.cpp": "e9a7574ee4075bd2811825dc8df439726395e7a1",
"shared/memory_policy/include/memory/policy/gc_mode.h": "78664e785f310b8bb53a878ec6a096f4bb2d0015",
- "shared/memory_policy/include/memory/policy/memory_mode_flag.h": "9ce053bd07b908a8aa3d6aa25e54d7269fa88597",
- "shared/memory_policy/src/memory_mode_flag.cpp": "c2a82c588a8acba08e624b47b6496a1232f3739c",
- "shared/parser/include/parser_core.h": "c11b333988e48c5b984ffe5b6c42397cc01aa575",
- "shared/parser/src/core/parser_expressions.cpp#L45-1130": "sha256:31ffeca3254dab10",
- "shared/parser/src/core/parser_main.cpp#L40-1500": "sha256:3ae6310f5ebc9df6",
- "shared/types/generated/sad_type_kind_generated.h": "fd336d51f192b64fe7e63ca25fbb2938479003a5",
- "shared/types/include/sad_type_system.h": "4e792e5b8ddb605fbb1c33200c019e9ded39f656",
- "shared/types/include/type_bridge.h": "0bf37baafc415409082a284c9b2de84d3837e4e1",
- "shared/types/include/value.h": "9b40909fd452fac4e27e41aed85852020f2af1e6",
- "tools/compiler/compiler_driver_android_linker.cpp": "e0c69cb8859b4d6b65bde3e4a4d37980c108dbd9",
- "tools/compiler/runtime/sad_embedded_runtime.c": "6fa885fb7277c79674aaab298ee5cadd6ff162b3",
- "vm/include/sad_vm_executor.h": "2a9c74f182c5d76643b58dfd036877ad03ad97c1",
- "vm/include/sad_vm_opcodes.h": "8b92d998a5a26d3b9716d25bd6dee8a61a5fca4d",
- "vm/src/sad_vm_executor.cpp": "76a1d059b635ebc6a3d55f0fb9b75c95fa2984a7"
+ "shared/memory_policy/include/memory/policy/memory_mode_flag.h": "0eb7ce0039f0e6052ed6bfa478311a9b9f1b2018",
+ "shared/memory_policy/src/memory_mode_flag.cpp": "dee66fea02ad221ad035b5654e17cc007603d447",
+ "shared/parser/include/parser_core.h": "03f3d4376191e79fc5a11e52fc8f2c53dad11ab0",
+ "shared/parser/src/core/parser_expressions.cpp#L45-1160": "sha256:a19648be018d3b95",
+ "shared/parser/src/core/parser_main.cpp#L40-1600": "sha256:61a72e3d3187d028",
+ "shared/parser/src/statements/parser_advanced.cpp": "870578af5f28eaf1e013b6f1940eb3f3277e9764",
+ "shared/types/generated/sad_type_kind_generated.h": "66a2e25e89fe3a3fc2d782fc79cbc86cab75b9bb",
+ "shared/types/include/sad_type_system.h": "abc0ace4395e26799a23ff5346efbe0714515d4b",
+ "shared/types/include/value.h": "4d16c5e5f6c17fd4393f1d1da32716582d15750d",
+ "tools/compiler/compiler_driver_android_linker.cpp": "86c4974e713923f47c0f16077b4db8ede94eef28",
+ "tools/compiler/compiler_driver_native.cpp": "74676054c3660ec7ac0df65a1da9aa8d3baab0dd",
+ "tools/compiler/runtime/sad_embedded_runtime.c": "c4465bac5594536e01b41f099a6dddf9fc80999d"
}
}
diff --git a/sync/sources.yaml b/sync/sources.yaml
index c11b419..de20e0c 100644
--- a/sync/sources.yaml
+++ b/sync/sources.yaml
@@ -22,8 +22,8 @@ chapters:
- file: src/frontend/parser.md
sources:
- - { path: shared/parser/src/core/parser_main.cpp, lines: "40-1500" } # التهيئة→الموزّعات
- - { path: shared/parser/src/core/parser_expressions.cpp, lines: "45-1130" } # سلسلة الأسبقيّة
+ - { path: shared/parser/src/core/parser_main.cpp, lines: "40-1600" } # التهيئة→الموزّعات→tryParseDirective (L1588)
+ - { path: shared/parser/src/core/parser_expressions.cpp, lines: "45-1160" } # سلسلة الأسبقيّة حتى parsePrimary (L1149)
- shared/parser/include/parser_core.h
- language-truth/operators.yaml
@@ -59,23 +59,28 @@ chapters:
sources:
- compiler/src/backend/llvm
- - file: src/backend/vm.md
+ - file: src/backend/native.md
sources:
- - vm/include/sad_vm_opcodes.h
- - vm/include/sad_vm_executor.h
- - vm/src/sad_vm_executor.cpp
+ - { path: compiler/include/backend/native/sir_native_lowering.h, lines: "1-30" } # عقد الجسر (الترويسة)
+ - compiler/include/backend/native/sir_lowering_common.h # LoweringDriver + LoweringDiagnostics
+ - compiler/include/backend/native/elf64_writer.h
+ - compiler/include/backend/native/x86_variable_encoder.h
+ - tools/compiler/compiler_driver_native.cpp # المدخل من --خلفية-أصلية
+ - language-truth/backend # targets · sir_opcodes · isel · abi · diagnostics · value_repr
+ - scripts/codegen/gen_native_diagnostics.py
+ - scripts/native_backend/run_native_proofs.sh # المُنادي وحرّاسه الأربعة
- file: src/systems/memory.md
sources:
- shared/memory_policy/include/memory/policy/gc_mode.h
- shared/memory_policy/include/memory/policy/memory_mode_flag.h
- shared/memory_policy/src/memory_mode_flag.cpp
+ - language-truth/cli_flags.yaml # عائلة memory: الأسماء القانونيّة العشرة (مصدر جدول الأعلام)
- file: src/systems/types.md
sources:
- shared/types/include/sad_type_system.h
- shared/types/generated/sad_type_kind_generated.h
- - shared/types/include/type_bridge.h
- shared/types/include/value.h
- language-truth/types.yaml
diff --git a/theme/custom.css b/theme/custom.css
index 7cf6556..d345574 100644
--- a/theme/custom.css
+++ b/theme/custom.css
@@ -62,12 +62,36 @@
}
/* ── الجداول ───────────────────────────────────────────────────────────────── */
+/* (AR) الجدولُ يُمرَّر أفقيًّا ولا يُسحَق.
+ الواقعُ المقيس: mdBook يلفّ كلَّ جدولٍ بـ`div.table-wrapper` (٦٦/٦٦ جدولًا في
+ الإخراج المبنيّ)، و`css/general-*.css:35` يعطيها `overflow-x:auto` أصلًا.
+ فالعلّةُ لم تكن غيابَ الحاوية بل `width:100%` على الجدول: يُساوي عرضَ الحاوية
+ دائمًا فلا يقعُ تجاوزٌ ولا يعملُ التمرير — فتُسحَق الأعمدة. الإصلاحُ الفعليّ هو
+ `width:auto; min-width:100%` أدناه. القاعدةُ التالية لا تُغيّر سلوكَ التمرير
+ (مكرِّرةٌ عمدًا كتوثيقٍ وحارسٍ لو تغيّر ثيمُ mdBook)، وتُضيف تدويرَ الحوافّ فقط. */
+.content .table-wrapper {
+ overflow-x: auto;
+ border-radius: var(--sad-radius);
+}
.content table {
border-collapse: collapse;
border-radius: var(--sad-radius);
overflow: hidden;
box-shadow: 0 1px 8px rgba(0,0,0,.06);
- width: 100%;
+ width: auto;
+ min-width: 100%;
+}
+/* (AR) على الشاشات الضيّقة: أرضيّةُ عرضٍ للخليّة كي يقعَ التجاوزُ فالتمريرُ بدل
+ السحق. الأرضيّةُ للخلايا النثريّة؛ الخليّةُ الأولى (المفتاح) أعرض.
+ قياسٌ: `--content-max-width: 750px` في mdBook، فعمودُ المحتوى لا يتجاوز ٧٥٠px
+ مهما اتّسعت الشاشة؛ لذا الأرضيّةُ تخصّ الهاتفَ حصرًا (أعرضُ جدولٍ في `src`
+ سبعةُ أعمدة: `src/systems/memory.md:71` — يتجاوز ٧٥٠px بمحتواه وحدَه فيُمرَّر
+ على كلّ عرض). */
+@media (max-width: 760px) {
+ .content table th,
+ .content table td { min-width: 8rem; }
+ .content table th:first-child,
+ .content table td:first-child { min-width: 10rem; }
}
.content table thead {
background: linear-gradient(90deg, var(--sad-accent), var(--sad-accent-2));
@@ -161,3 +185,51 @@
.navy .content .card,
.coal .content .card,
.ayu .content .card { background: rgba(255,255,255,.04); color: #c8d3de !important; }
+
+/* ── فهرس الصفحة (يبنيه theme/page-toc.js) ───────────────────────────────────── */
+.page-toc {
+ background: var(--sad-accent-soft);
+ border: 1px solid rgba(11,114,133,.18);
+ border-radius: var(--sad-radius);
+ padding: .6rem .9rem;
+ margin: 0 0 1.6rem;
+ font-size: .92em;
+}
+.page-toc > summary {
+ cursor: pointer;
+ font-weight: 700;
+ color: var(--sad-accent);
+ list-style: none;
+}
+.page-toc > summary::-webkit-details-marker { display: none; }
+.page-toc > summary::before { content: "☰ "; }
+.page-toc ul {
+ margin: .6rem 0 .2rem;
+ padding-right: 1.2rem;
+ padding-left: 0;
+ list-style: none;
+ columns: 2;
+ column-gap: 1.6rem;
+}
+.page-toc li { margin: .18rem 0; break-inside: avoid; }
+.page-toc .page-toc-l3 { padding-right: 1rem; opacity: .85; font-size: .95em; }
+/* (AR) الرفعُ إلى `.content .page-toc a` ضروريّ: `.content a:not(.header)` أعلاه
+ خصوصيّتُه (٠,٢,١) وتهزم (٠,١,١) لو كُتبت `.page-toc a` وحدَها. */
+.content .page-toc a { color: var(--sad-ink); text-decoration: none; }
+.content .page-toc a:hover { color: var(--sad-accent); text-decoration: underline; }
+@media (max-width: 760px) { .page-toc ul { columns: 1; } }
+@media print { .page-toc { display: none; } }
+/* (AR) الوضعُ الداكن: `--sad-accent-soft` (#e3fafc) لوحٌ فاتحٌ يصرخ في navy/coal/ayu
+ — نفسُ معالجةِ الاقتباسات والبطاقات أعلاه. */
+.navy .content .page-toc,
+.coal .content .page-toc,
+.ayu .content .page-toc { background: rgba(16,152,173,.10); border-color: rgba(16,152,173,.28); }
+.navy .content .page-toc a,
+.coal .content .page-toc a,
+.ayu .content .page-toc a { color: #c8d3de; }
+.navy .content .page-toc > summary,
+.coal .content .page-toc > summary,
+.ayu .content .page-toc > summary { color: #66d9e8; }
+.navy .content .page-toc a:hover,
+.coal .content .page-toc a:hover,
+.ayu .content .page-toc a:hover { color: #66d9e8; }
diff --git a/theme/page-toc.js b/theme/page-toc.js
new file mode 100644
index 0000000..57ff23c
--- /dev/null
+++ b/theme/page-toc.js
@@ -0,0 +1,86 @@
+/* ============================================================================
+ فهرسُ الصفحة (في هذه الصفحة) — يبني قائمةَ عناوينِ h2/h3 للفصل المفتوح
+ ويضعها بعد عنوانِ الصفحة مباشرةً. شريطُ mdBook الجانبيّ يعرض عناوينَ الفصول
+ لا عناوينَ الأقسام، فالفصولُ الطويلة تُقرأ جدارًا بلا مسح.
+ بلا تبعيّةٍ خارجيّة ولا معالجٍ مسبق (mdbook-toc غير مستعمَل عمدًا: يُضيف
+ تبعيّةَ cargo إلى CI ويكتب الفهرسَ في HTML المبنيّ فيقيسه lychee).
+ يُحمَّل عبر additional-js في book.toml.
+ ============================================================================ */
+(function () {
+ "use strict";
+
+ var MIN_HEADINGS = 4; // (AR) أقلّ من ذلك: الفصلُ يُمسَح بلا فهرس
+ var COLLAPSE_WIDTH = 900; // (AR) تحت هذا العرض يبدأ الفهرسُ مطويًّا
+
+ // (AR) عنوانٌ صالحٌ للفهرسة: له مُعرِّفٌ يولّده mdBook، ولا يُدرَج h3 قبل أوّل h2.
+ function collect(main) {
+ var nodes = main.querySelectorAll("h2[id], h3[id]");
+ var out = [], sawH2 = false, i;
+ for (i = 0; i < nodes.length; i++) {
+ var h = nodes[i];
+ if (h.tagName === "H2") sawH2 = true;
+ else if (!sawH2) continue;
+ var text = (h.textContent || "").replace(/\s+/g, " ").trim();
+ if (!text) continue;
+ out.push({ id: h.id, text: text, level: h.tagName === "H2" ? 2 : 3 });
+ }
+ return out;
+ }
+
+ function build(items) {
+ var box = document.createElement("details");
+ box.className = "page-toc";
+ box.open = window.innerWidth >= COLLAPSE_WIDTH;
+
+ var head = document.createElement("summary");
+ head.textContent = "في هذه الصفحة";
+ box.appendChild(head);
+
+ var list = document.createElement("ul");
+ for (var i = 0; i < items.length; i++) {
+ var it = items[i];
+ var li = document.createElement("li");
+ li.className = "page-toc-l" + it.level;
+ var a = document.createElement("a");
+ // (AR) مرساةٌ خام لا مُرمَّزة: مُعرِّفاتُ mdBook عربيّةٌ حرفيّةٌ في HTML، وروابطُ
+ // العناوين التي يولّدها mdBook نفسُها خامّة (`href="#لماذا-خلفيّةٌ-ثالثة"`)
+ // — فالمطابقةُ اتّساقٌ مع الصفحة لا اجتهادُ ترميز.
+ a.setAttribute("href", "#" + it.id);
+ a.textContent = it.text;
+ li.appendChild(a);
+ list.appendChild(li);
+ }
+ box.appendChild(list);
+ return box;
+ }
+
+ function init() {
+ var main = document.querySelector(".content main");
+ if (!main || main.querySelector(".page-toc")) return;
+
+ // (AR) صفحةُ الطباعة (`print.html`) تلصق كلَّ الفصول في `main` واحد: ٣٣ عنوانَ h1
+ // و١٨٣ عنوانَ h2/h3 بمُعرِّفاتٍ قد تتكرّر — فهرسٌ واحدٌ عملاقٌ بمراسٍ ملتبسة.
+ // علامةُ الصفحة: أكثرُ من h1 واحدٍ في `main`.
+ var h1s = main.querySelectorAll("h1");
+ if (h1s.length !== 1) return;
+
+ var items = collect(main);
+ if (items.length < MIN_HEADINGS) return;
+
+ // (AR) الموضعُ: بعد كتلةِ العنوان. h1 ليس دائمًا ابنًا مباشرًا لـ`main`:
+ // في `introduction.md` هو داخل `div.hero`، فالإدراجُ عند `main.firstChild`
+ // كان يضعُ الفهرسَ *فوق* لافتةِ الهبوط. نصعدُ إلى أعلى سلفٍ تحت `main`.
+ var anchor = h1s[0];
+ while (anchor && anchor.parentNode !== main) anchor = anchor.parentNode;
+ var box = build(items);
+ if (anchor && anchor.nextSibling) main.insertBefore(box, anchor.nextSibling);
+ else if (anchor) main.appendChild(box);
+ else main.insertBefore(box, main.firstChild);
+ }
+
+ if (document.readyState === "loading") {
+ document.addEventListener("DOMContentLoaded", init);
+ } else {
+ init();
+ }
+})();