لماذا SDL2 مخرَجًا مرجعيًّا
شجرةُ واجهةٍ واحدةٌ في لغة ص تُوصَفُ مرّةً وتُصيَّرُ على أكثرَ من مخرَج. فلماذا يُسمّى مخرَجُ سطحِ المكتبِ عبر SDL2 «المرجعيَّ» دونَ غيرِه؟ لا لأنّه أجمل، بل لأنّه الوحيدُ الذي يُقاسُ عليه معنى «يعمل» بلا وسيط.
مُصيِّرٌ حيٌّ ≠ مولِّدُ مصدر
هذا هو الفرقُ الذي يُفَكُّ به الالتباسُ كلُّه:
| النوع | ماذا يُخرِج | مَن يُشغّل |
|---|---|---|
| مُصيِّرٌ حيّ | بكسلًا على شاشة، وحلقةَ أحداثٍ تُرسِلُ النقرةَ إلى معالِجِك | ثنائيُّك أنت |
| مولِّدُ مصدر | نصَّ شفرةٍ لمنصّةٍ أخرى (HTML · Compose · SwiftUI) | أدواتُ تلك المنصّة |
ومولِّدُ المصدرِ لا يرسمُ ولا يُشغِّلُ ولا يُدير حلقةَ أحداث. فلو قِيسَ النضجُ بعددِ المخارجِ لبدَتِ اللغةُ تدعمُ خمسَ منصّاتٍ وهي لا تفتحُ نافذةً إلّا على واحدة. ولهذا يُسمّى المُصيِّرُ الحيُّ مرجعًا: هو الذي يُغلِقُ الحلقةَ من زر(…) إلى نقرةٍ تُنفَّذ.
المُصيِّراتُ المُعلَنةُ في مصدرِ الحقيقة
من language-truth/ui_nodes.yaml — قائمةُ platform_renderers:
| المُصيِّر | enabled |
|---|---|
desktop_sdl2 | ✅ |
freestanding (إطارُ بكسلٍ مباشرٍ بلا نظامِ تشغيل) | ✅ |
web · android · ios | ✅ في الإعلان |
macos_appkit | ❌ مؤجَّلٌ بسببٍ مكتوب |
والإعلانُ ليس برهانَ البناء
مصدرُ الحقيقةِ نفسُه غيرُ معصومٍ في هذا الحقل، وذلك مُدوَّنٌ في محورِ SadUI: enabled: true لا يعني أنّ الخلفيّةَ تُترجَمُ وتعمل. ولذلك لا تُشتَقُّ درجةُ أيِّ مجالٍ من إعلاناتِ التفعيل، بل من status/intent — وهي حقولٌ قِيسَ صدقُها.
خلفيّةُ ماكِ الأصليّة: تأجيلٌ مكتوبٌ لا سهو
macos_appkit مُعلَنٌ enabled: false، والسببُ في الملفِّ نفسِه:
يستدعي طبقةَ تفاعلٍ (
hitTest/fireEvent/focusedNode_) لا تصرّحُ بها ترويستُه فلا يترجم كما هو؛ وماك يعمل اليومَ على مسارِ SDL2 عبرَ المُرسِّمِ المشترَك.
وحقلُ السببِ هذا إلزاميٌّ متى كان enabled: false، ويحرسُه scripts/codegen/check_ui_render_completeness.py فيُحمِّرُ إن ادّعى ملفٌّ مؤجَّلٌ أنّه مبنيٌّ أو العكس — كي لا يتنكّرَ التأجيلُ في صورةِ سطرٍ معلَّقٍ في CMake يبدو سهوًا.
فماك اليومَ يعملُ على SDL2، لا على AppKit. وإتمامُ AppKit معلَمٌ قائمٌ بذاتِه: رفعُ طبقةِ التفاعلِ إلى PlatformRenderer (فتفيدُ كلَّ منصّة)، ثمّ بناءٌ وتشغيلٌ على ماكَ للتحقّق — ولا يُدَّعى إنجازُه بلا ذلك.
الخلفيّاتُ الثلاثُ للمترجِم
عقدٌ مُعلَنٌ في ui_nodes.yaml تحتَ backend_support:
| الخلفيّة | تدعمُ الواجهة |
|---|---|
llvm | ✅ — المسارُ المدعومُ للبرامجِ المُترجَمةِ ذاتِ الواجهة |
interpreter | ✅ في الإعلان — والمفسّرُ محذوفٌ من اللغة، فلا مستهلكَ له |
native (ELF مباشرٌ بلا LLVM) | ❌ |
وnative لا يسكتُ عن عجزِه: الخفضُ يفشلُ صراحةً بوسمِ kUiRequiresLlvm، فلا يُنتَجُ ثنائيٌّ يُنشئُ عناصرَ ثمّ لا يعرضُ شيئًا. وهذا هو النمطُ الحاكمُ في هذه اللغة: فشلٌ مُشخَّصٌ خيرٌ من نجاحٍ كاذب.
حدُّ هذا المخرَجِ الأكبر
لا مجموعةَ بذورٍ سلوكيّةٍ للواجهةِ في tests/behavior. فالمخرَجُ المرئيُّ غيرُ محروسٍ بانحدارٍ آليّ، ويُقاسُ بالعينِ لا ببوّابة. ولذلك درجةُ هذا المجالِ «يعملُ بحدودٍ مُعلَنة» ولا تُرفَعُ بسطرٍ يُكتَب.
والفتحُ معلومٌ لا مجهول
طباعة_شجرة تُعطي نقطةَ ارتساءٍ نصّيّةً قابلةً للمقارنةِ بلا صورة. فبذورٌ تُصيِّرُ شجرةً وتُقارِنُ مخرَجَها نصًّا كافيةٌ لرفعِ هذا الحدّ — وهي مكتوبةٌ في مصدرِ الحقيقةِ حقلًا اسمُه unblocked_by، لا أمنيّةً في وثيقة.
وطبقةُ المنصّةِ دَينٌ لا قدرة
UIPlatform مُعلَنٌ ٤٣ مدخلًا واثنانِ منهما فقط مستقرّان (ارسم_خط وارسم_مستطيل). فما تحتَ العنصرِ من نوافذَ متعدّدةٍ وحوارٍ ودورةِ حياةٍ إعلانٌ لا قدرةٌ جاهزة — وبقيّةُ الحدودِ في حدودِ سطحِ المكتبِ المُعلَنة.