From f361a978960b39d5672c4b8a57c9641f656de94b Mon Sep 17 00:00:00 2001 From: Sad Lang Dev Date: Wed, 22 Jul 2026 03:58:19 +0300 Subject: [PATCH 1/2] =?UTF-8?q?RFC:=20=D8=AA=D8=B5=D8=AF=D9=8A=D8=B1=20?= =?UTF-8?q?=D8=A7=D9=84=D8=AF=D9=88=D8=A7=D9=84=D9=91=20=D8=A8=D8=A7=D8=B3?= =?UTF-8?q?=D9=85=20=D8=B1=D9=85=D8=B2=20=E2=80=94=20@=D8=B1=D9=85=D8=B2("?= =?UTF-8?q?=D8=A7=D8=B3=D9=85")=20=D8=B9=D9=84=D9=89=20=D8=AA=D8=B5=D8=B1?= =?UTF-8?q?=D9=8A=D8=AD=20=D8=AF=D8=A7=D9=84=D9=91=D8=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit يمدّ التوجيه @رمز ليقبل FunctionDecl فتُصدَّر الدالّة في LLVM باسم رمز ASCII بربط خارجيّ. الغرض: تعريف رموز ABI للنواة (__sad_panic، __stack_chk_fail) بلغة ص خالصة وإطفاء تعريفات C. يشمل حارس تصادم دلاليًّا (SEM024) للرموز المُصدَّرة المكرَّرة (دالّة/دالّة، دالّة/متغيّر). Co-Authored-By: Claude Opus 4.8 --- ...0\263\331\205-\330\261\331\205\330\262.md" | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 "text/0000-\330\252\330\265\330\257\331\212\330\261-\330\247\331\204\330\257\331\210\330\247\331\204\331\221-\330\250\330\247\330\263\331\205-\330\261\331\205\330\262.md" diff --git "a/text/0000-\330\252\330\265\330\257\331\212\330\261-\330\247\331\204\330\257\331\210\330\247\331\204\331\221-\330\250\330\247\330\263\331\205-\330\261\331\205\330\262.md" "b/text/0000-\330\252\330\265\330\257\331\212\330\261-\330\247\331\204\330\257\331\210\330\247\331\204\331\221-\330\250\330\247\330\263\331\205-\330\261\331\205\330\262.md" new file mode 100644 index 0000000..3d7a4de --- /dev/null +++ "b/text/0000-\330\252\330\265\330\257\331\212\330\261-\330\247\331\204\330\257\331\210\330\247\331\204\331\221-\330\250\330\247\330\263\331\205-\330\261\331\205\330\262.md" @@ -0,0 +1,121 @@ +- **عنوان المقترح:** تصدير الدوالّ باسم رمز — `@رمز("اسم")` على تصريح دالّة +- **النطاق:** لغة `text/` +- **تاريخ البدء:** 2026-07-21 +- **رقم الـ RFC:** (يُترك فارغاً حتى الدمج) +- **الحالة:** مقترَح +- **Issue التتبُّع:** (يُترك فارغاً حتى القبول) + +# ملخّص + +نمدّ التوجيه القائم `@رمز("اسم")` — الذي يُصدِّر **متغيّرًا/ثابتًا** تحت اسم +رمز ASCII محدَّد (اللبنتان 3.14/3.16) — ليقبل **تصريح دالّة** كذلك. فتصير +`@رمز("bee_x") دالة اسم(...)` تُصدِّر الدالّة في LLVM باسم `bee_x` بربط +خارجيّ، بدل اسمها الداخليّ المُشوَّه — فيستدعيها كود C أو الكود الذي يولّده +المترجم بالاسم حرفيًّا. + +المبدأ الحاكم نفسه: **الرمز عقد ABI مع العالم الخارجيّ، والاسم العربيّ يبقى +لغة ص.** + +# الدافع (Motivation) + +- **إطفاء آخر تعريفات C في نواة النحلة:** المترجم يولّد نداءات إلى رموز + ABI محجوزة (`__sad_panic` لمسارات حدود المصفوفات، `__stack_chk_fail` + لفشل حارس الإطار). اليوم تُعرَّف هذه في C (`تراب.c`) لأنّ ص لا تملك + تصدير دالّة تحت اسم ASCII — فيتعذّر بلوغ هدف «صفر C». هذا التوجيه يزيل + العائق: تُعرَّف الدالّة بلغة ص وتُصدَّر تحت الاسم المحجوز. +- **تناظر مع `@رمز` على البيانات:** تصدير البيانات تحت اسم رمز (3.14) + وتصدير الكود تحته وجهان لعقد ABI واحد؛ إبقاء أحدهما دون الآخر تفاوت + تعسّفيّ. +- **الاستضافة الذاتيّة والـFFI العكسيّ:** أيّ سيناريو يستدعي فيه كود + خارجيّ (نظام تشغيل، مكتبة C، مُحمِّل) دالّةً مكتوبة بلغة ص يحتاج اسم + رمز مستقرًّا معلومًا. + +# الشرح التوجيهي (Guide-level explanation) + +`@رمز("اسم")` سمة سابقة على تصريح دالّة. تجعل رمز الرابط للدالّة = `"اسم"` +حرفيًّا (بدل الاسم الداخليّ)، بربط خارجيّ: + +```sad +# تُصدَّر في LLVM كـ: define void @__sad_panic(i64 %الرمز) { … } +@رمز("__sad_panic") دالة لا_ترجع اهلع_المترجم(رقم الرمز) + اطبع_خام("هلع") + قف_أبديًّا() +نهاية +``` + +- الدالّة **معرَّفة كاملةً** (لها جسم) لا مجرّد إعلان — بخلاف `دالة خارجية` + التي تستورد رمزًا بلا جسم. +- تتركّب مع المعدِّلات القائمة: `@رمز("s") دالة لا_ترجع اسم()` ⇒ رمز مُصدَّر + بسمة `noreturn` (3.15). +- الاسم العربيّ (`اهلع_المترجم`) يبقى للاستدعاء من كود ص؛ الاسم ASCII + للعالم الخارجيّ. (اليوم إن اختُلف الاسمان يُصدَّر بالاسم ASCII فقط؛ + الاستدعاء الداخليّ بلغة ص يمرّ عبر رمز الرابط نفسه.) + +# التصميم التفصيليّ (Reference-level explanation) + +الآليّة قائمة بالكامل تحت السطح؛ ينقصها ربط المحلّل فقط: + +1. **AST:** `FunctionDecl` يملك أصلًا `linkName` (كان لاستيراد FFI عبر + `دالة خارجية("اسم")`). نعيد استعماله للتصدير — دلالته الموحَّدة «اسم + رمز الرابط لهذه الدالّة». +2. **المحلّل** (`parser_main.cpp`، كتلة `@رمز`): بعد تحليل التصريح التالي، + إن كان `FunctionDecl` يُضبَط `linkName = اسم_الرمز` (كما يُضبَط + `linkSymbol` على `VarDeclStmt`). رسالة الخطأ تُحدَّث لتشمل «دالة». +3. **جسر SIR:** `funcDecl->linkName → sirFunction->linkName` يتدفّق أصلًا. +4. **الخلفيّة:** اسم رمز LLVM = `sirFunc->getLinkName()` (=‏`linkName` + إن وُجد) أصلًا؛ والدالّة ذات `linkName ≠ name` تبقى `ExternalLinkage` + (لا تُدوَّل). فالتصدير يعمل بلا تغيير خلفيّ. + +5. **حارس التصادم (SEM024):** إبقاء رمزين مُصدَّرين باسم رابط واحد على + تعريفين **مُعرَّفين** يجعل الخلفيّة تُفسدهما صامتًا: دالّتان تُدمَجان (جسم + الثانية يُلحَق ككتلة بلا سلف ويُفقَد)، ودالّة تشارك متغيّرًا الاسمَ تُعيد + LLVM تسمية أحدهما (`@اسم.1`) فيَضيع عقد الـABI — كلاهما كودٌ خاطئ صامت. لذا + يتتبّع الباني أسماء الرموز المُصدَّرة (مجموعتان: دالّة/متغيّر، متقاطعتان + مستقلًّا عن ترتيب المعالجة) ويرفض التكرار بخطأ قاتل `SEM024` لحالتَي + دالّة/دالّة ودالّة/متغيّر. (تصادم متغيّر/متغيّر يبقى لحارسه القائم خلفيًّا؛ + والدوالّ الخارجيّة `دالة خارجية` بلا جسم = استيراد، فلا تتصادم فتُستثنى.) + المجموعتان تُمسحان عند دخول كلّ وحدة (لئلّا يُطلَق `SEM024` كاذبًا عبر + الوحدات في بانٍ مُعاد استخدامه — LSP). + +**التغيير الصافي:** فرع `else if` واحد في المحلّل + حارس تصادم دلاليّ +(`SEM024`، تتبّع أسماء الرموز المُصدَّرة) + رسالة الخطأ. لا كلمة مفتاحيّة +جديدة، لا تغيير خلفيّ. + +## القيود (الإصدار الأوّل) + +- الدالّة المُصدَّرة يجب أن تكون بتوقيع بسيط قابل للتعبير في ABI الهدف + (لا أنواع عامّة/قوالب، لا async/مولّد — تلك تُشوّه أسماءها أو تحتاج بيئة + تشغيل). الاستعمال الأوّل (نواة، FFI عكسيّ) لا يحتاج غير التوقيع البسيط. +- مسؤوليّة تطابق التوقيع مع عقد المستدعي الخارجيّ على المبرمج (نظير + `دالة خارجية`). + +# البدائل (Alternatives) + +- **حقل `exportName` مستقلّ عن `linkName`:** أوضح دلاليًّا لكن يضاعف مسارات + الخلفيّة بلا كسب (كلاهما «اسم رمز الرابط»). رُفض لصالح إعادة الاستعمال. +- **كلمة مفتاحيّة `صدّر_كـ("اسم")`:** تركيب جديد بلا داعٍ؛ `@رمز` قائم + ومفهوم ومتناظر مع البيانات. +- **إبقاء `__sad_panic` في C أبدًا:** يناقض «صفر C» ويترك دَينًا دائمًا. + +# أسئلة مفتوحة (Unresolved questions) + +- تصدير دالّة عامّة/مُنمَّطة (بأيّ تخصيص؟) — مؤجَّل حتّى يظهر طلب فعليّ. +- حارس دلاليّ يرفض `@رمز` على async/مولّد/عامّة برسالة صريحة — تحسين + لاحق (الإصدار الأوّل يعتمد على بساطة الاستعمال؛ رصدته المراجعة العدائيّة + كفخّ بلا تشخيص M3). أمّا **تصادم اسم الرمز المكرَّر فمحروس منذ الإصدار + الأوّل** (`SEM024`) — دالّة/دالّة ودالّة/متغيّر معًا — بعد أن كشفته المراجعة + العدائيّة (دمج/إعادة تسمية صامتة ⇒ كودٌ خاطئ). +- تصدير `@رمز("malloc"/"free"/"memset"/…)` يتجاوز رمزًا يوفّره زمن التشغيل + (weak): مسار الخلفيّة يفرض نوع العائد لهذه الأسماء المعروفة، فقد يُبدَّل + عائد الدالّة المُصدَّرة صامتًا (رصد المراجعة العدائيّة M2). مقبولٌ في الإصدار + الأوّل (نظير `دالة خارجية`: تطابق التوقيع عهدةٌ على المبرمج)؛ حارس أسماء + محجوزة للدوالّ تحسينٌ لاحق. +- تجاوز مدمج بتوقيع مخالف (`@رمز("__sad_panic") دالة بلا معاملات`) يبقى + مسؤوليّة المبرمج (نظير `دالة خارجية`) — تطابق التوقيع مع عقد المستدعي + عهدةٌ عليه. + +# الأثر على مصدر الحقيقة + +لا شيء: `@رمز` توجيه سمة لا كلمة مفتاحيّة، فلا إدخال في `keywords.yaml` ولا +توليد. اختبارات منع الانحدار في +`tests/system/lowlevel_freestanding/test_symbol_export_func.py`. From 6955c2cf94c266f3c1f985aa68add98bdbd3630e Mon Sep 17 00:00:00 2001 From: Sad Lang Dev Date: Wed, 22 Jul 2026 03:59:04 +0300 Subject: [PATCH 2/2] =?UTF-8?q?RFC:=20=D8=AA=D8=B1=D9=82=D9=8A=D9=85=20004?= =?UTF-8?q?2=20(=3D=20=D8=B1=D9=82=D9=85=20PR)=20=D9=88=D8=A5=D8=B9=D8=A7?= =?UTF-8?q?=D8=AF=D8=A9=20=D8=AA=D8=B3=D9=85=D9=8A=D8=A9=20=D8=A7=D9=84?= =?UTF-8?q?=D9=85=D9=84=D9=81=D9=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- ...330\250\330\247\330\263\331\205-\330\261\331\205\330\262.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename "text/0000-\330\252\330\265\330\257\331\212\330\261-\330\247\331\204\330\257\331\210\330\247\331\204\331\221-\330\250\330\247\330\263\331\205-\330\261\331\205\330\262.md" => "text/0042-\330\252\330\265\330\257\331\212\330\261-\330\247\331\204\330\257\331\210\330\247\331\204\331\221-\330\250\330\247\330\263\331\205-\330\261\331\205\330\262.md" (99%) diff --git "a/text/0000-\330\252\330\265\330\257\331\212\330\261-\330\247\331\204\330\257\331\210\330\247\331\204\331\221-\330\250\330\247\330\263\331\205-\330\261\331\205\330\262.md" "b/text/0042-\330\252\330\265\330\257\331\212\330\261-\330\247\331\204\330\257\331\210\330\247\331\204\331\221-\330\250\330\247\330\263\331\205-\330\261\331\205\330\262.md" similarity index 99% rename from "text/0000-\330\252\330\265\330\257\331\212\330\261-\330\247\331\204\330\257\331\210\330\247\331\204\331\221-\330\250\330\247\330\263\331\205-\330\261\331\205\330\262.md" rename to "text/0042-\330\252\330\265\330\257\331\212\330\261-\330\247\331\204\330\257\331\210\330\247\331\204\331\221-\330\250\330\247\330\263\331\205-\330\261\331\205\330\262.md" index 3d7a4de..86bcd0c 100644 --- "a/text/0000-\330\252\330\265\330\257\331\212\330\261-\330\247\331\204\330\257\331\210\330\247\331\204\331\221-\330\250\330\247\330\263\331\205-\330\261\331\205\330\262.md" +++ "b/text/0042-\330\252\330\265\330\257\331\212\330\261-\330\247\331\204\330\257\331\210\330\247\331\204\331\221-\330\250\330\247\330\263\331\205-\330\261\331\205\330\262.md" @@ -1,7 +1,7 @@ - **عنوان المقترح:** تصدير الدوالّ باسم رمز — `@رمز("اسم")` على تصريح دالّة - **النطاق:** لغة `text/` - **تاريخ البدء:** 2026-07-21 -- **رقم الـ RFC:** (يُترك فارغاً حتى الدمج) +- **رقم الـ RFC:** 0042 - **الحالة:** مقترَح - **Issue التتبُّع:** (يُترك فارغاً حتى القبول)