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(); + } +})();