Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<div dir="rtl">

- **عنوان المقترح:** تكافؤ تعديل عنصر واجهة عامّ (المعدّل الانسيابيّ) بين المفسّر والمترجم
- **النطاق:** لغة `text/` (سلوك استنتاج النوع في المترجم)
- **تاريخ البدء:** 2026-07-02
- **رقم الـ RFC:** (يُترك فارغاً حتى الدمج — يصبح رقم الـ PR)
- **الحالة:** مقترَح (PR مفتوح)
- **Issue التتبُّع:** (يُترك فارغاً حتى القبول)

# ملخّص

يغلق هذا المقترح فجوة تكافؤ ثالثة بين محرّكَي لغة ص في نظام الرسومات: تطبيق
**معدّل انسيابيّ** (مثل `.محتوى` أو `.لون`) على **متغيّر عنصرِ واجهةٍ عامّ**
(global) من داخل دالّة. المفسّر يشغّله بنجاح (نوع وقت التشغيل)، بينما المترجم
(`sad-build`) كان يُنتج `lld-link: error: undefined symbol: .محتوى` لأنّه لا
يتتبّع أنّ المتغيّر العامّ من نوع مقبض عنصر عبر حدود الدوال. النتيجة المرئيّة:
تطبيق تفاعليّ يعدّل عنصر عرضٍ عامًّا من معالِج حدث (آلة حاسبة تحدّث شاشتها) يعمل
الآن **بالكامل في المحرّكين معًا** بمخرَجٍ متطابق بايتيًّا.

# الدافع (Motivation)

النمط الأساسيّ للتطبيقات التفاعليّة في SadUI هو: عنصر عرضٍ **عامّ** تعدّله
معالِجات الأحداث في مكانه ثم `تحديث_حالة()`. هذا النمط يعمل في المفسّر لكنّه كان
**محجوبًا في المترجم**: مصانع العناصر (`نص_عنصر`، `زر`، …) تُرجع «كائن» ⇒ مقبض
عنصر (Pointer)، لكن استنتاج النوع الساكن للمتغيّرات العامّة في المترجم
(`TemplateBuilder::inferExprType`) كان يُرجع `Integer` افتراضيًّا لأيّ نداء دالّة
غير مسجَّل في جدول دوال المستخدم — فلا يمرّ المُستقبِل عبر بوّابة المعدّل الانسيابيّ
(`call_method_dispatch.cpp`) التي تشترط أن يكون المُستقبِل من نوع Pointer، فيُعامَل
`عرض.محتوى(...)` نداءً لدالّةٍ اسمها `.محتوى` غير موجودة ⇒ رمز غير معرَّف عند الربط.

الفرق الدقيق: التسلسل المباشر `نص_عنصر("0").حجم(44)` (inline) كان يعمل في المترجم
لأنّ المُستقبِل طازجٌ معروف؛ بينما `عرض.محتوى(...)` حيث `عرض` **متغيّر عامّ مخزَّن**
يفشل. أي أنّ الفجوة كانت في تتبّع النوع عبر التخزين وحدود الدوال، لا في الرسم.

هذا يكسر وعد «اكتب مرّة، اعمل في المحرّكين» للتطبيقات التفاعليّة الحقيقيّة، لا
للعروض الساكنة فقط.

# الشرح التوجيهي (Guide-level explanation)

يُكتب عنصر العرض متغيّرًا عامًّا، وتعدّله الدوال في مكانه بمعدّل انسيابيّ:

```sad
استورد رسومات

متغير الشاشة = "0"
# عنصر عرض عامّ — مرجع نعدّله في مكانه
متغير عرض_الشاشة = نص_عنصر("0").حجم(44).لون("أبيض")

دالة اعرض()
عرض_الشاشة.محتوى(الشاشة) # كان يفشل في المترجم (رمز غير معرَّف) — يعمل الآن
تحديث_حالة()
نهاية

دالة أدخل_رقم(ر)
الشاشة = نص(ر)
اعرض()
نهاية
```

بعد هذا المقترح، يسلك `عرض_الشاشة.محتوى(الشاشة)` سلوكًا متطابقًا في `sad-run`
و`sad-build`: يعدّل خاصّيّة المحتوى في مكانها ويعيد رسم الشجرة. لا صياغة جديدة ولا
مفاهيم جديدة — فقط إغلاق تباعدٍ صامت كان يجبر مطوّري المترجم على واجهات ساكنة.

# الشرح المرجعي (Reference-level explanation)

- **مصدر الحقيقة (`language-truth/`):** لا توسيع. الإصلاح يشتقّ نوع الإرجاع من
الحقل `returns` القائم في `language-truth/builtins/ui_widgets.yaml` (يظهر في
`BuiltinMeta::returnType` = «كائن» لمصانع UIWidgets الـ42)، لا من قائمة أسماء
مثبّتة في الأداة. التزامٌ بمبدأ «الأدوات لا توسّع SoT اللغة».
- **المحلل المعجمي/النحوي:** لا تغيير.
- **الشجرة المجردة (AST):** لا عقد جديدة.
- **المفسّر:** لا تغيير (مصدر سلوك التكافؤ المرجعيّ).
- **المترجم (`sad-build`):** ثلاثة تعديلات في استنتاج النوع الساكن
(`TemplateBuilder::inferExprType`):
1. **مصانع العناصر ⇒ Pointer:** داخل حالة `CallExpr`، إن كانت الدالّة مُدمَجة
(`Sad::Builtins::findBuiltinMeta`) ونوع إرجاعها من السجلّ = «كائن» ⇒ يُرجع
`Pointer`. هذا يجعل المتغيّر العامّ المخزَّن نتيجةَ مصنعِ عنصرٍ متتبَّعًا
كمقبض عنصر عبر حدود الدوال.
2. **المعدّل الانسيابيّ ⇒ Pointer:** حالة `MethodCallExpr` جديدة: إن كان نوع
الكائن المُستقبِل `Pointer` ⇒ يُرجع `Pointer` (لأنّ المعدّل يُرجع العنصر نفسه
للتسلسل، فيبقى `نص_عنصر(..).حجم(..)` مقبضًا).
3. **مساعد مركزيّ:** `builtinReturnsToSIRKind(returnType)` رُقّي إلى دالّة عضو
في `TemplateBuilder`، فيعتمد عليه مساراً الاستنتاج (نوع إرجاع الجسم + نوع
التعبير) على **الحقل نفسه** `returnType` بدل حقلين مختلفين.
- **نظام الأخطاء:** لا رموز جديدة. على العكس، يزيل رسالة ربطٍ مضلِّلة
(`undefined symbol`) كانت تظهر لبرنامج `.ص` سليم.
- **الأدوات (LSP/المنسّق):** لا أثر.
- **التوافق الخلفي:** لا يكسر شيئًا. يوسّع مجموعة البرامج التي تُترجَم بنجاح فقط
(برامج كانت تفشل صارت تعمل). لا برنامج كان يعتمد على الفشل.

## التحقّق

- بناء `sad-build` (Release) ناجح.
- آلة حاسبة تفاعليّة كاملة (`آلة_حاسبة.ص`): منطق `7+3=10.0` وشجرة العرض متطابقان
بايتيًّا بين المحرّكين.
- انحدار: 20/20 من اختبارات تغطية الواجهة (`ui_cov_*.ص`) تكافؤ مترجم↔مفسّر تامّ.
- `x.py gen --check`: المصدر المولَّد متزامن مع مصدر الحقيقة (لا انجراف).

# السلبيات (Drawbacks)

- يوسّع مسؤوليّة استنتاج النوع الساكن في المترجم قليلًا (حالة `MethodCallExpr`
جديدة). الكلفة هامشيّة والمنطق محصور.
- المطابقة تبقى نصّيّة على «كائن» لأنّ مصدر الحقيقة نصّيّ (YAML)، لكنّها الآن
ممركزة وموثَّقة في مساعد واحد بدل نثرها.

# المبرّرات والبدائل (Rationale and alternatives)

- **لماذا هذا التصميم:** يشتقّ النوع من مصدر الحقيقة (سجلّ المدمجات) لا من قائمة
أسماء مثبّتة، فيبقى متّسقًا تلقائيًّا مع أيّ توسّع مستقبليّ لكتالوج العناصر.
- **بديل مرفوض:** دعم بانِي الجذر في `تشغيل_تطبيق` للمترجم (إعادة بناء الشجرة كلّ
إطار) نظير [نموذج البانِي في التنقّل]. أثقل، ويغيّر نموذج البرمجة، ولا يلزم لحلّ
نمط «التعديل في المكان» الشائع.
- **بديل مرفوض:** تثبيت قائمة أسماء المصانع في المترجم. يكرّر مصدر الحقيقة ويخالف
مبدأ عدم توسيع/تكرار SoT في الأدوات.
- **أثر عدم الفعل:** يبقى التطبيق التفاعليّ الحقيقيّ محجوبًا في المترجم، والوعد
الأساسيّ منقوصًا.

# أعمال سابقة (Prior art)

استنتاج النوع الساكن لمقابض الكائنات المعتمة (opaque handles) عبر جدول رموز مطبوع
ممارسةٌ قياسيّة في مترجمات اللغات ذات مصدر حقيقة للأنواع (مثل اشتقاق أنواع الإرجاع
في Rust/Dart من توقيعات الدوال بدل تخمينها). الجديد هنا خصوصيّة لغة ص: مصدر الحقيقة
عربيّ الأسماء (`returns: كائن`) والمترجم يشتقّ منه لا من قائمة يدويّة.

# أسئلة غير محسومة (Unresolved questions)

- خارج النطاق: تتبّع النوع للوسائط (parameters) التي تستقبل عناصر — هذا المقترح
يعالج المتغيّرات العامّة والمعدّلات المتسلسلة؛ تتبّع نوع الوسيط شريحة لاحقة.
- خارج النطاق: بانِي الجذر في `تشغيل_تطبيق` للمترجم (بديل نموذجيّ مؤجَّل).

# إمكانات مستقبلية (Future possibilities)

- تعميم اشتقاق `returns` من مصدر الحقيقة لكلّ أنواع الإرجاع (عدد/نص/…) لا «كائن»
فقط، بحيث يستنتج المترجم أنواع كلّ المدمجات ساكنًا من SoT.
- مخطَّط SoT يفرض أسماء الأنواع رسميًّا، فتزول المطابقة النصّيّة كلّيًّا.

</div>
Loading