diff --git "a/text/0000-\330\247\331\204\330\247\330\263\330\252\330\266\330\247\331\201\330\251-\330\247\331\204\330\260\330\247\330\252\331\212\330\251-\331\204\331\205\330\252\330\261\330\254\331\205-\330\265.md" "b/text/0000-\330\247\331\204\330\247\330\263\330\252\330\266\330\247\331\201\330\251-\330\247\331\204\330\260\330\247\330\252\331\212\330\251-\331\204\331\205\330\252\330\261\330\254\331\205-\330\265.md" new file mode 100644 index 0000000..14e280e --- /dev/null +++ "b/text/0000-\330\247\331\204\330\247\330\263\330\252\330\266\330\247\331\201\330\251-\330\247\331\204\330\260\330\247\330\252\331\212\330\251-\331\204\331\205\330\252\330\261\330\254\331\205-\330\265.md" @@ -0,0 +1,273 @@ +- **عنوان المقترح:** الاستضافة الذاتيّة لمترجم لغة ص — خارطة طريق مرحليّة لإعادة كتابة المترجم بلغة ص، وسدّ الفجوات اللغويّة الحاجزة +- **النطاق:** لغة `text/` (RFC خارطة طريق إستراتيجيّ يُولّد RFCs فرعيّة قابلة للإسناد) +- **تاريخ البدء:** 2026-07-24 +- **رقم الـ RFC:** (يُترك فارغاً حتى الدمج) +- **الحالة:** مقترَح (PR مفتوح) +- **Issue التتبُّع:** (يُترك فارغاً حتى القبول) + +# ملخّص + +يقترح هذا المقترح **خارطة طريق رسميّة للاستضافة الذاتيّة (Self-Hosting / Bootstrapping)**: أن يُعاد كتابة مترجم لغة ص — المكتوب اليوم بـ C++ (‏~٢٢٣ ألف سطر فوق LLVM) — **بلغة ص نفسها**. لا يقترح هذا المقترح تنفيذ الاستضافة الذاتيّة دفعةً واحدة (فذلك جهد سنوات)، بل **يُثبّت المسار المرحليّ** ويعزل **الفجوات اللغويّة الحاجزة** التي يجب سدّها في مصدر الحقيقة والمترجم أوّلًا، فيصبح كلٌّ منها **RFC فرعيًّا قابلاً للإسناد لوكيل**. + +الأساس اللغويّ مُثبَت عمليًّا: نواة `nahla` مكتوبة بـ ص خالصة تقريبًا (~٨٫٧ ألف سطر، ٤١ وحدة، تُقلع على QEMU) — برهان قاطع على جاهزيّة ص للبرمجة النظاميّة. **لكنّ الحاجز الأوّل ليس نضج الواجهة الأماميّة بل الخلفيّة (توليد الشيفرة) ونوعها، يليه غياب الأنواع الجبريّة الموسومة لتمثيل شجرة AST، وعدم إثبات نظام الوحدات وFFI على مقياس مترجم.** **النتيجة المرئية للمستخدم:** لغة ص تصبح لغةً مُستضيفةً لذاتها (سيادة كاملة على سلسلة أدواتها)، وتُنجَز الطريق عبر خطوات مُتحقَّقة ذهبيًّا مقابل المترجم البذرة (C++) في كلّ مرحلة. + +# الدافع (Motivation) + +الاستضافة الذاتيّة هدف إستراتيجيّ للغة ص ضمن رؤية «منظومة تقنيّة عربيّة سياديّة»: لغةٌ لا تملك مترجمًا مكتوبًا بها هي لغةٌ تابعة لسلسلة أدوات أجنبيّة (C++/LLVM). الاستضافة الذاتيّة: + +- **تُثبت نضج اللغة:** المترجم أعقد برنامج تكتبه لغة عن نفسها؛ نجاحه شهادة قدرة. +- **تُوحّد السيادة:** يكتمل المكدّس العربيّ (نواة `nahla` بـ ص + مترجم ص بـ ص). +- **تُسرّع اللغة نفسها:** كلّ فجوة تُكتشَف أثناء كتابة المترجم تُسدّ في المنبع فتفيد كلّ مستخدمي ص. + +**لكنّ الخطر الأكبر هو الانطلاق بلا تثبيت المتطلّبات**، فينكشف نقصٌ لغويّ في منتصف الطريق يُوقف المشروع. لذا الدافع المباشر لهذا المقترح: **تحويل «هل نستطيع؟» إلى قائمة فجوات محدّدة بالدليل**، كلٌّ منها وحدة عمل مستقلّة، قبل أن نلتزم بإعادة الكتابة الكبرى. + +حالة الاستخدام الواقعيّة: مبرمج ص يريد أن يكتب `مترجم_ص.ص` يقرأ ملفّ `.ص` ويولّد ثنائيًّا — اليوم يصطدم بأنّ تمثيل عقدة AST يلزمه التفافٌ عبر أصناف OOP (لغياب التعداد بحمولة)، وأنّ ربط الخلفيّة غير مُثبَت. + +# الشرح التوجيهي (Guide-level explanation) + +## البنية الحاليّة (نقطة الانطلاق) + +المترجم اليوم = **قلب مشترك** (`shared/`، ~٩٩٫٧ ألف سطر C++: lexer + parser + AST + semantic + types + modules) + **خلفيّة LLVM** (`compiler/src/`، ~١٢٣ ألف سطر C++ تبني SIR ثمّ LLVM IR). الواجهة الأماميّة مُقادة بمصدر الحقيقة (`language-truth/*.yaml`)، ما يُسهّل مواءمة أيّ مترجم جديد مع المواصفة. + +## ما تملكه ص اليوم (لبنات كتابة مترجم — مُثبَتة بالدليل) + +| اللبنة | الحالة | الدليل | +|---|---|---| +| البنى (structs) | ✅ تعمل حرًّا | `nahla/نواة/فحص_تخطيط.ص:17` (`بنية عقدة_فحص` + وصول حقول) | +| مصفوفات `مصفوفة` وخرائط `خريطة` | ✅ مضمَّنة | `language-truth/types.yaml` | +| معالجة الملفّات | ✅ كاملة مستضافةً | `stdlib/ملفات.ص` + `builtins/compiler_io_utils.yaml` | +| إجماليّ المدمجات | ✅ ١٬٠٩٠ دالّة (٤٢ ملفّ) | `builtins/*.yaml` | +| مؤشّرات + ذاكرة خام | ✅ حرًّا | `nahla/نواة/ذاكرة_فيزيائية.ص:19` (`@رمز … متغير ساكن مصفوفة[131072]`) + `:63` | +| دوالّ من الدرجة الأولى | ✅ (بدرجات) | `stdlib/خرائط.ص:105` (تمرير `دالة_شرط`) | +| مطابقة أنماط | ✅ (٢٤/٤١ ملفّ نواة) | `language-truth/patterns.yaml` | +| الوحدات `استورد`/`صدّر` | ✅ منفَّذة | `grammar/20_declarations.yaml:179` | +| FFI مع C | ✅ (عدديّ فقط) | `grammar/20_declarations.yaml:243`؛ nahla: `دالة خارجية("bee_paging_enable")` | + +## ما ينقصها (الفجوات الحاجزة) + +مثال ملموس على الفجوة الأولى — تمثيل عقدة AST لو كان لدينا **تعداد بحمولة (ADT) + نمط باني**: + +```sad +# المنشود (غير مدعوم اليوم) — بالصياغة الفعليّة لـ«طابق … عندما»: +تعداد عقدة + عدد(رقم قيمة) + جمع(عقدة يسار، عقدة يمين) + متغير(نص اسم) +نهاية + +دالة قيّم(عقدة ع) + طابق (ع) + عندما عدد(ق): # نمط باني — غير مدعوم اليوم + أرجع ق + عندما جمع(ي، ن): + أرجع قيّم(ي) + قيّم(ن) + عندما متغير(اسم): + أرجع ابحث(اسم) + نهاية +نهاية +``` + +المواصفة التفصيليّة الكاملة لهذا الحاجز في **الملحق أ** أدناه (رُقّي من RFC فرعيّ مقترَح إلى مواصفة مدمجة جاهزة للتنفيذ). + +اليوم يُحاكى هذا بتسلسل أصناف OOP + إرسال ظاهريّ — ممكن لكنّه مُسهَب وعُرضة للأخطاء. + +# الشرح المرجعي (Reference-level explanation) + +## الفجوات الحاجزة — كلٌّ منها RFC فرعيّ قابل للإسناد + +### حاجز ١ — الخلفيّة (توليد الشيفرة) من ص 🔴 الأكبر + +لا يوجد مكوّن توليد شيفرة مكتوب بـ ص. الخيارات: + +- **ربط libLLVM عبر FFI** — يتطلّب تمرير مقابض معتمة (`LLVMModuleRef`…) ومصفوفات وردود نداء. **خارج قدرة FFI الحاليّة** (عدديّة فقط)؛ مخاطرة عالية. +- **توليد LLVM-IR نصّيًّا ثمّ `llc`/الرابط خارجيًّا** — ✅ **الموصى**. يحتاج فقط بناء نصوص (تجيده ص) + تشغيل عمليّة خارجيّة، **وكلاهما متاح اليوم**. سابقة مُثبَتة على مستوى الأدوات: المترجم البذرة C++ يولّد بالفعل `.ص → .ll` نصّيًّا (`nahla/بناء/موحد.ll` عبر `sad-build --freestanding`، يحوي `declare void @bee_paging_enable(i64)`) — يبقى تحويل *المولِّد* من C++ إلى ص. +- **توليد C** — الأبسط، لكن يفقد سيادة المكدّس. + +> **التوصية الحاسمة:** البدء بخلفيّة **LLVM-IR نصّيّة**، لا بربط libLLVM. الأثر على مصدر الحقيقة: لا شيء (مجرّد برنامج ص يكتب نصًّا). الأثر على المترجم: **مدمج تشغيل العمليّة الخارجيّة موجود ومستقرّ** — `نفذ_امر` (‏C `system()`) في `builtins/ffi.yaml:371` (`cpp_id: C_SYSTEM`, `status: stable`)، ومعه `قيمة_بيئة` (getenv). فاستدعاء `llc`/الرابط خارجيًّا **قدرةٌ قائمة لا سؤال تحقّق مفتوح**. الفجوة المتبقّية **تحسينٌ لا حاجز:** التقاط مخرجات العمليّة وتدفّقها (لا مجرّد رمز الخروج)، وقراءة حجج سطر الأوامر. + +### حاجز ٢ — الأنواع الجبريّة الموسومة (tagged unions / ADT) + المطابقة الاستنفاديّة 🔴 + +- التعداد الحاليّ **بسيط** (قيم صحيحة فقط، بلا حمولة): `oop_constructs.yaml:43` (id: oop.enum؛ المثال `أحمر = 1`). +- المطابقة **بلا نمط باني**: `patterns.yaml` (‏٨ أنماط: حرفيّ/شامل/متغيّر/قائمة/أو/نطاق/بنية/ربط — لا نمط «باني تعداد بحمولة»). +- **الأثر:** بلا ADT، تمثيل AST يلزمه التفاف OOP. **هذا الحاجز رُقّي من RFC فرعيّ مقترَح إلى مواصفة تفصيليّة كاملة مدمجة — انظر [الملحق أ](#الملحق-أ--مواصفة-التعداد-بحمولة--نمط-الباني-الحاجزان-الأهمّ).** + +### حاجز ٣ — FFI بنيويّ (بنى/مؤشّرات/ردود نداء عبر حدّ C) 🟠 + +- توقيعات FFI الحاليّة **عدديّة/نصّيّة فقط**: تمرّر `رقم` (i64) و`عشري` (double — مثال رسميّ: `دالة خارجية("cos") عشري جيب_التمام(عشري)` في `20_declarations.yaml:277`) و`نص`؛ العناوين تُمرَّر كـ`رقم`. والمواصفة تصنّف FFI `compiler_optional: true` (`20_declarations.yaml:274`). +- ضروريّ **فقط لو** اخترنا مسار libLLVM. مع مسار IR النصّيّ الموصى، هذا الحاجز **مؤجَّل لا حاجز**. **RFC فرعيّ (مشروط):** «توسيع FFI للبنى بالقيمة والمؤشّرات وردود النداء». + +### حاجز ٤ — نظام الوحدات على المقياس 🟠 + +- الوحدات موجودة ومنفَّذة (`shared/modules/` + `compiler/src/frontend/sir_module.cpp`)، لكن **🚩 nahla تتجنّبها وتدمج ٤١ ملفًّا نصّيًّا** في `موحد.ص` (`nahla/أدوات/ترتيب_الوحدات.txt` + `أدوات/بناء.ps1:120`). لا يُبنى مترجمٌ جدّيّ بالدمج النصّيّ. +- **قيود تصدير معروفة في مصدر الحقيقة تخصّ هذا الحاجز مباشرةً:** `صدّر بنية` **لا يُترجَم بعد** (‏`20_declarations.yaml:232`, ISSUE-026)، وقيود دلاليّة على `من … استورد` (`:206`). تصدير البنى شرطٌ لتمثيل AST عبر وحدات. +- **مطلوب:** إثبات ربط ≥٢٠ وحدة مستضافة فعليًّا + رفع ISSUE-026. **RFC فرعيّ (تحقّق):** «تصليب ربط الوحدات وتصدير البنى على المقياس». + +### حاجز ٥ — إثبات المقياس 🟠 + +لا برنامج ص مستضاف يقارب حجم مترجم (١٠٠ ألف سطر+). مطلوب قياس تجريبيّ: زمن الترجمة، الذاكرة، ثبات الواجهة الأماميّة. **ليس RFC بل بند تحقّق في م٠ أدناه.** + +### حاجز ٦ — نضج الإغلاقات والدوالّ عالية الرتبة 🟠 + +تمرير الدوالّ مُثبَت (`stdlib/خرائط.ص:105`)، لكنّه في الغالب **تمرير معامل إلى مدمج** (`filter_map`) لا إغلاقات ببيئات ملتقَطة حقيقيّة، ونضجها الحرّ غير مُثبَت بكثافة. المترجم يحتاج إغلاقات متينة (زوّار AST، جداول رموز). **بند تحقّق في م٠.** + +### حاجز ٧ — بنية معالجة الأخطاء والتشخيص على المقياس 🟠 + +المترجم يحتاج منظومة أخطاء **مسترجَعة** (لا ذعر) لتراكم تشخيصات عربيّة على ملفّ كبير. جاهزيّة `حاول/امسك` وتوليد التشخيص المسترجَع عند مقياس ١٠٠ ألف سطر **غير مُقيَّمة**. **بند تحقّق في م٠**؛ يتقاطع مع استنفاد المطابقة (حاجز ٢). + +## المسار المرحليّ (كلّ مرحلة مُتحقَّقة ذهبيًّا مقابل المترجم البذرة C++) + +| المرحلة | المحتوى | التقدير | بوّابة القبول | +|---|---|---|---| +| **م٠ — تصليب المتطلّبات** | حجج CLI + التقاط مخرجات `نفذ_امر` (لا رمز الخروج فقط) + ربط ≥٢٠ وحدة فعليّة + **نضج الإغلاقات ببيئات ملتقَطة** (حاجز ٦) + **جاهزيّة `حاول/امسك` والتشخيص المسترجَع بلا ذعر** (حاجز ٧) + قياس زمن/ذاكرة برنامج ٢٠ ألف سطر مُولَّد | شهر | كلّ بند مُثبَت تجريبيًّا | +| **م١ — Lexer بـ ص** | يقرأ `.ص`، يُخرِج رَتلًا مطابقًا لمرجع `shared/lexer` | ١–٢ شهر | مقارنة ذهبيّة على مجموعة اختبار | +| **م٢ — Parser + AST بـ ص** | AST عبر ADT (بعد حاجز ٢) أو OOP التفافًا | ٣–٦ أشهر | AST مُتسلسَل يُطابق المرجع | +| **م٣ — تحليل دلاليّ مُصغَّر** | أنواع كافية لمجموعة فرعيّة ذاتيّة الاستضافة | ٢–٤ أشهر | يمرّر مجموعة اختبار دلاليّة | +| **م٤ — خلفيّة نصّيّة** | LLVM-IR نصّيّ ثمّ `llc`+رابط | ٦–١٢ شهرًا | ترجمة «مرحبا» ثمّ برنامج غير تافه | +| **م٥ — الإغلاق الذاتيّ** | توسيع المجموعة الفرعيّة حتى يترجم مترجم-ص نفسه | ٦–١٢ شهرًا | نقطة الثبات `stage2 == stage3` | + +## الأثر على الأنظمة المتشابكة + +- **مصدر الحقيقة (`language-truth/`):** يتطلّبه حاجز ٢ (نحو تعداد بحمولة + `patterns.yaml`) وحاجز ٣ (توسيع نحو FFI). خارطة الطريق نفسها لا تُغيّر YAML. +- **Lexer/Parser/AST:** لا تُمَسّ بخارطة الطريق؛ تُمَسّ في RFCs الفرعيّة (حاجز ٢). +- **المفسّر + المترجم (sadc):** codegen اتّحاد موسوم (حاجز ٢)؛ التحقّق من مدمج العمليّة الخارجيّة (حاجز ١). +- **نظام الأخطاء:** استنفاد المطابقة (حاجز ٢) قد يستلزم رمز خطأ جديد. +- **الأدوات:** لا أثر مباشر؛ لاحقًا المترجم-بـ-ص يصبح هدف بناء جديدًا. +- **التوافق الخلفي:** خارطة الطريق غير كاسرة. ADT إضافة غير كاسرة. توسيع FFI إضافة غير كاسرة. + +# السلبيات (Drawbacks) + +- **الجهد هائل:** ٢–٣ سنوات لفريق صغير مركّز حتى تكافؤ LLVM. قد يُزاحم أولويّات أقرب عائدًا. +- **تبعيّة LLVM تبقى** مع مسار IR النصّيّ (سيادة منقوصة — نعتمد `llc`/الرابط). +- **ازدواج صيانة مؤقّت:** مترجمان (C++ البذرة + ص) حتى نقطة الثبات. +- **خطر التوقّف عند فجوة منبعيّة:** كلّ ميزة ناقصة تُكتشَف أثناء الكتابة تُوقف المسار حتى تُسدّ (نمط nahla). + +# المبرّرات والبدائل (Rationale and alternatives) + +- **لماذا خارطة طريق لا تنفيذ مباشر؟** لأنّ الجهد سنوات؛ RFC واحد لا يُسند. تقسيمه إلى فجوات محدّدة (كلٌّ RFC فرعيّ) يجعله وحدات عمل قابلة للإسناد ويقلّل خطر التوقّف المنتصف. +- **لماذا IR نصّيّ لا libLLVM؟** libLLVM يتطلّب FFI بنيويًّا (مشروع لغويّ قائم بذاته) قبل أن نكتب سطرًا واحدًا من الخلفيّة. IR النصّيّ ينطلق بقدرات ص الحاليّة. +- **البديل «توليد C»:** أبسط وأسرع للـ PoC، لكنّه يفقد سيادة المكدّس ويُبقي تبعيّة مُجمِّع C. صالح كخطوة PoC، لا كهدف. +- **البديل «لا نفعل شيئًا»:** تبقى ص لغةً تابعةً لسلسلة أدوات C++/LLVM دون سيادة على مترجمها — يتعارض مع الرؤية السياديّة. + +# أعمال سابقة (Prior art) + +- **Rust:** بدأ بمترجم OCaml (`rustboot`) ثمّ استضاف نفسه (`rustc`) مع خلفيّة LLVM — نموذج «مترجم بذرة بلغة أخرى ثمّ إغلاق ذاتيّ». +- **Go:** بدأ بـ C ثمّ هاجر مترجمه إلى Go آليًّا (أداة `c2go`) — نموذج الهجرة التدريجيّة. +- **Zig / TypeScript:** استضافة ذاتيّة مع خلفيّة LLVM؛ TS يولّد JS نصًّا (نظير «الخلفيّة النصّيّة»). +- **الدرس:** الاستضافة الذاتيّة تُنجَز مرحليًّا مع مترجم بذرة يبقى حتى نقطة الثبات، والخلفيّة النصّيّة (IR/C/JS) مسار منخفض المخاطر يسبق الربط المباشر. **بخصوصيّة ص (العربيّة أوّلاً):** كلّ صياغة جديدة (تعداد بحمولة، نمط باني) تلتزم قواعد ص (الفعل أوّلًا، مطابقة الجنس، النوع قبل الاسم). + +# أسئلة غير محسومة (Unresolved questions) + +- **قبل الدمج:** هل نلتزم مسار IR النصّيّ نهائيًّا، أم نُبقي libLLVM هدفًا بعيدًا يتطلّب RFC توسيع FFI أوّلًا؟ +- **قبل الدمج:** هل حاجز ٢ (ADT + نمط باني) شرطٌ مسبق لـ م٢، أم نبدأ بـ AST عبر OOP ونُدخل ADT لاحقًا؟ (التوصية: سدّ حاجز ٢ أوّلًا لتفادي إعادة كتابة AST.) +- **أثناء التنفيذ:** حدود المجموعة الفرعيّة ذاتيّة الاستضافة (أيّ ميزات ص يترجمها المترجم-بـ-ص أوّلًا). +- **خارج النطاق:** إعادة كتابة المفسّر بـ ص؛ استبدال LLVM بخلفيّة أصيلة؛ توقيت هجر المترجم البذرة C++. + +# إمكانات مستقبلية (Future possibilities) + +- **خلفيّة أصيلة بـ ص** (توليد تجميع مباشر) تُلغي تبعيّة LLVM وتكمل السيادة. +- **مترجم ص يُقلع حرًّا** (يترجم نفسه داخل sad-os) — إغلاق المكدّس السياديّ كاملاً مع nahla. +- **مُحسّنات مكتوبة بـ ص** فوق IR النصّيّ. +- **RFCs فرعيّة مُتولّدة عن هذا المقترح:** ~~(١) تعداد بحمولة + نمط الباني~~ (رُقّي إلى مواصفة مدمجة — الملحق أ)، (٢) توسيع FFI البنيويّ [مشروط]، (٣) تصليب ربط الوحدات على المقياس. + +--- + +# الملحق أ — مواصفة «التعداد بحمولة + نمط الباني» (الحاجزان الأهمّ) + +> هذا الملحق يُفصّل الحاجز ٢ ويرقّيه من RFC فرعيّ مقترَح إلى **مواصفة جاهزة للتنفيذ**. يعالج ميزتين متلازمتين لا تنفصلان: **(أ) التعداد بحمولة** (الأنواع الجبريّة الموسومة / tagged unions) و**(ب) نمط الباني** في `طابق … عندما`. معًا يوفّران التمثيل الطبيعيّ لشجرة AST — أهمّ ما ينقص لكتابة مترجم ص بـ ص. كلّ قرار صياغيّ يلتزم قواعد ص (النوع قبل الاسم، الصياغة الفعليّة `عندما <نمط>:`). + +## أ-١ الميزة (أ): التعداد بحمولة + +### الصياغة (Guide-level) + +يُوسَّع `تعداد` القائم (`oop_constructs.yaml:43`) بحيث يقبل كلّ **مُعامِل (variant)** أحد ثلاثة أشكال: + +```sad +تعداد عقدة + عدد(رقم قيمة) # مُعامِل بحمولة موضعيّة (النوع قبل الاسم) + جمع(عقدة يسار، عقدة يمين) # حمولة متعدّدة (تعداد عوديّ ذاتيّ المرجع) + متغير(نص اسم) + فراغ # مُعامِل وحدويّ (بلا حمولة) + خطأ = 99 # مُعامِل بقيمة صحيحة (متوافق مع التعداد البسيط القائم) +نهاية +``` + +- **التوافق الخلفيّ ودلالة `= N`:** `= N` **يثبّت المُميِّز (الوسم/discriminant)** لذلك المُعامِل صراحةً، والمعاملات بلا `=` تأخذ الوسم الضمنيّ التالي (‏٠٬١٬٢…). فالتعداد البسيط الحاليّ (`أحمر = 1`) هو الحالة الخاصّة حيث كلّ المعاملات وحدويّة وأوسامها مضبوطة يدويًّا — دلالةٌ موسَّعة لا مُبدَّلة، فلا يكسر برنامجًا قائمًا. +- **البناء (construction):** `عدد(5)`، `جمع(ل، ر)`، `فراغ` (المُعامِل الوحدويّ بلا أقواس)، `عقدة.خطأ`. +- **ذاتيّة المرجع:** يجوز أن يحمل المُعامِل نوعَ تعدادِه نفسه (`جمع(عقدة، عقدة)`) — شرطٌ لتمثيل الأشجار؛ يُخزَّن مؤشّرًا (انظر أ-٣ التخطيط). + +### الشرح المرجعيّ (Reference-level) + +- **مصدر الحقيقة (`language-truth/`):** توسيع `oop_constructs.yaml` (id: `oop.enum`) بحقل `variants` يصف الأشكال الثلاثة؛ إضافة مدخل نوع «اتّحاد موسوم» في `types.yaml` (category جديدة أو `tagged_enum`). تحديث نحو التعداد في `grammar/` ليقبل قائمة معاملات لكلّ مُعامِل. +- **Lexer:** لا رموز جديدة (يُعاد استعمال `تعداد`/الأقواس/الفاصلة/المعرّفات). +- **Parser:** توسيع قاعدة تعريف التعداد لتحليل `اسم_المُعامِل ( نوع اسم [، …] )`؛ إعادة استعمال محلّل قائمة المعاملات القائم للدوالّ. +- **AST:** عقدة `EnumVariantDecl` تكتسب حقول `fields: [(type, name)]`؛ التعبير `عدد(5)` يُمثَّل كاستدعاء باني مُعامِل (عقدة `EnumConstruct` مميّزة عن `Call`). +- **نظام الأنواع (`shared/types/`):** نوع `TaggedEnumType` = اسم + قائمة معاملات، لكلّ مُعامِل وسمٌ (tag) عدديّ — ضمنيّ تسلسليّ أو مُثبَّت صراحةً بـ`= N` — + توقيع حمولته. `isAssignableTo`: مُعامِل ⊑ تعدادِه. + +## أ-٢ الميزة (ب): نمط الباني في «طابق» + +### الصياغة (Guide-level) + +نمط جديد سادس ضمن `patterns.yaml` بالصياغة الفعليّة `عندما <نمط>:` (النقطتان اختياريّتان؛ لا `=>`): + +```sad +دالة قيّم(عقدة ع) + طابق (ع) + عندما عدد(ق): # يربط ق بحمولة المُعامِل «عدد» + أرجع ق + عندما جمع(ي، ن): # يربط الحمولتين + أرجع قيّم(ي) + قيّم(ن) + عندما فراغ: # مُعامِل وحدويّ — بلا ربط + أرجع 0 + نهاية +نهاية +``` + +- **الاستنفاد (exhaustiveness):** إن لم تُغطَّ كلّ المعاملات ولا يوجد `عندما _` أو `افتراضي`، **خطأ ترجمة** (رمز جديد). هذا ما يجعل زوّار AST آمنين. +- **التداخل مع الأنماط القائمة:** يقبل نمط الباني أنماطًا متداخلة في حمولته لاحقًا (`عندما جمع(عدد(0)، ن):`) — خارج نطاق النسخة الأولى (يُذكر في أسئلة غير محسومة). + +### الشرح المرجعيّ (Reference-level) + +- **مصدر الحقيقة:** مدخل جديد في `patterns.yaml` (id: `pattern.constructor`, status: experimental أوّلًا)؛ **رمز خطأ جديد واحد** في `language-truth/errors/semantic.yaml` لعدم الاستنفاد (بعُرف التسمية القائم `SEM_`: مثلاً `SEM_NON_EXHAUSTIVE_MATCH`)، و**إعادة استعمال** `SEM_WRONG_ARG_COUNT` القائم (`semantic.yaml:76`) لفحص عدد حمولة المُعامِل. +- **Parser:** في `parsePattern` (المصدر المذكور في ترويسة `patterns.yaml`: `shared/parser/src/statements/parser_advanced.cpp`) — تمييز `معرّف ( … )` كنمط باني عن نمط المتغيّر البسيط. +- **AST:** عقدة `ConstructorPattern { variantName, subPatterns[] }`. +- **المحلّل الدلاليّ (`shared/semantic/`):** فحص الاستنفاد (كلّ معاملات النوع مغطّاة)، وفحص عدد وسائط المُعامِل، وربط أنواع المتغيّرات المُلتقَطة. +- **المفسّر:** المطابقة = مقارنة الوسم ثمّ ربط الحمولة من التمثيل الزمن-تشغيليّ. +- **المترجم (sadc / SIR → LLVM):** انظر أ-٣. + +## أ-٣ التخطيط الزمن-تشغيليّ وتوليد الشيفرة (الأصعب) + +- **التخطيط (layout):** اتّحاد موسوم = `{ i32 وسم ; حمولة }` حيث الحمولة تخزين بحجم أكبر مُعامِل (union) أو **بنية لكلّ مُعامِل مع مؤشّر** للمعاملات ذاتيّة المرجع (`جمع` يخزّن `عقدة*` لتفادي حجم لانهائيّ). القرار: **المعاملات ذاتيّة المرجع تُخزَّن مؤشّرًا (مُكوَّمة)، والقياسيّة بالقيمة.** +- **البناء (codegen):** تخصيص + كتابة الوسم + كتابة الحمولة. يتقاطع مع سياسة الذاكرة (`--gc`/`--prod`) لتخصيص المعاملات المُكوَّمة. +- **المطابقة (codegen):** `switch` على حقل الوسم ثمّ استخراج الحمولة (`extractvalue`/تحميل من المؤشّر) وربطها بمتغيّرات الفرع. +- **الوضع الحرّ:** يجب أن يعمل بلا مُخصِّص كومة عند اللزوم — للمعاملات ذاتيّة المرجع في الوضع الحرّ يلزم مُخصِّص (nahla تملك مُخصِّصها)، أو تقييد العمق. **بند تحقّق.** + +## أ-٤ الأثر على الأنظمة المتشابكة (تلخيص) + +| النظام | التغيير | +|---|---| +| `language-truth` | توسيع `oop_constructs.yaml` (variants) + `types.yaml` (نوع موسوم) + `patterns.yaml` (نمط باني) + `errors/` (استنفاد، عدد وسائط) + `grammar/` | +| Lexer | لا تغيير | +| Parser | تعريف تعداد بمعاملات + نمط باني في `parsePattern` | +| AST | `EnumVariantDecl.fields` + `EnumConstruct` + `ConstructorPattern` | +| Semantic | فحص الاستنفاد + عدد الوسائط + ربط أنواع الحمولة | +| المفسّر | تمثيل وسم+حمولة، بناء ومطابقة | +| المترجم (SIR/LLVM) | تخطيط الاتّحاد الموسوم، `switch` الوسم، مؤشّرات المعاملات ذاتيّة المرجع | +| نظام الأخطاء | رمز جديد واحد (استنفاد: `SEM_NON_EXHAUSTIVE_MATCH`) + إعادة استعمال `SEM_WRONG_ARG_COUNT` القائم | +| التوافق الخلفيّ | **غير كاسر** (التعداد البسيط حالة خاصّة) | + +## أ-٥ خطّة تنفيذ مرحليّة للحاجزين + +1. **أ-م١ (SoT + Parser + AST):** توسيع `oop_constructs.yaml`/`patterns.yaml`، تحليل التعداد بحمولة ونمط الباني، بناء العقد. بوّابة: طباعة AST صحيحة لمثال `عقدة`. +2. **أ-م٢ (Semantic):** فحص الاستنفاد وعدد الوسائط + ربط الأنواع. بوّابة: رفض مطابقة غير مستنفِدة برمز الخطأ الجديد. +3. **أ-م٣ (المفسّر):** بناء ومطابقة زمن-تشغيليّة. بوّابة: `قيّم(جمع(عدد(2)، عدد(3)))` = ٥ في `sad-run`. +4. **أ-م٤ (المترجم):** تخطيط + codegen للبناء والمطابقة، ومؤشّرات المعاملات ذاتيّة المرجع. بوّابة: المثال نفسه في `sad-build` يعطي ٥، ونسخة حرّة تُقلع. +5. **أ-م٥ (استنفاد الأنماط المتداخلة):** [اختياريّ لاحق] `عندما جمع(عدد(0)، ن):`. + +**تقدير:** أ-م١..أ-م٣ (‏٤–٨ أسابيع) · أ-م٤ (‏٤–٨ أسابيع، الأثقل) — إجمالاً ‏٢–٤ أشهر لفريق صغير، وهو **الشرط المسبق لـ م٢** في خارطة الطريق أعلاه. + +## أ-٦ أسئلة غير محسومة (خاصّة بالملحق) + +- الأنماط المتداخلة في حمولة المُعامِل — النسخة الأولى تقبل متغيّرات/شامل فقط داخل الباني. +- تخطيط الحمولة: union بحجم الأكبر مقابل مؤشّر دائمًا — القرار المبدئيّ: مؤشّر للذاتيّ المرجع، قيمة للباقي. +- الوضع الحرّ: سياسة تخصيص المعاملات المُكوَّمة (مُخصِّص nahla مقابل تقييد العمق). +- التسمية: `فراغ` للمُعامِل الوحدويّ مقابل استعمال اسم المُعامِل مباشرةً بلا أقواس — حُسم لصالح «بلا أقواس».