From df222f2170d470261e17db93a5f07423a8822d98 Mon Sep 17 00:00:00 2001 From: Sad Lang Dev Date: Sat, 11 Jul 2026 10:25:26 +0300 Subject: [PATCH 1/4] =?UTF-8?q?RFC:=20=D9=86=D9=82=D9=84=20=C2=AB=D8=AE?= =?UTF-8?q?=D8=A7=D8=B1=D8=AC=D9=8A=C2=BB=20=D8=A5=D9=84=D9=89=20=D9=85?= =?UTF-8?q?=D9=88=D8=B6=D8=B9=20=D8=A7=D9=84=D8=B5=D9=81=D8=A9=20=D8=A7?= =?UTF-8?q?=D9=84=D9=84=D8=A7=D8=AD=D9=82=D8=A9=20=E2=80=94=20=D8=AF=D8=A7?= =?UTF-8?q?=D9=84=D8=A9=20=D8=AE=D8=A7=D8=B1=D8=AC=D9=8A=20=D8=A8=D8=AF?= =?UTF-8?q?=D9=84=20=D8=AE=D8=A7=D8=B1=D8=AC=D9=8A=20=D8=AF=D8=A7=D9=84?= =?UTF-8?q?=D8=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- ...31\204\330\247\330\255\331\202\330\251.md" | 232 ++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 "text/0000-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" diff --git "a/text/0000-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" "b/text/0000-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" new file mode 100644 index 0000000..cfc3208 --- /dev/null +++ "b/text/0000-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" @@ -0,0 +1,232 @@ +- **عنوان المقترح:** نقل «خارجي» إلى موضع الصفة اللاحقة — «دالة خارجي» بدل «خارجي دالة» +- **النطاق:** لغة `text/` (المحلّل النحويّ + مصدر الحقيقة + الأدوات المستهلِكة) +- **تاريخ البدء:** 2026-07-11 +- **رقم الـ RFC:** (يُترك فارغاً حتى الدمج) +- **الحالة:** مسودّة +- **Issue التتبُّع:** (يُترك فارغاً حتى القبول) + +# ملخّص + +تصريح الربط الخارجيّ (FFI) هو البنية الوحيدة المتبقّية في لغة ص التي تضع +المعدِّل **قبل** «دالة»: `خارجي دالة اسم(...)`. هذا يخالف المبدأ المعلَن في +مصدر الحقيقة «**الصفة بعد الموصوف**» (`20_declarations.yaml:29,53` وعموم +`30_oop.yaml`)، ويخالف السابقة المباشرة التي أزالت `غير_متزامن دالة` لصالح +`دالة غير_متزامن` بحاجز هجرة صريح نصُّه «في العربية الصفة تأتي بعد الاسم» +(`shared/parser/src/core/parser_main.cpp` بعد السطر ~568). المقترح: نقل +«خارجي» إلى موضع الصفة اللاحقة في صيغة التصريح المفرد: + +```sad +دالة خارجي printf(نص) +دالة خارجي("cos") عشري جيب_التمام(عشري) +``` + +مع إبقاء **صيغة الكتلة** `خارجي "C" ... نهاية` كما هي (فهي بنية حاوية لا صفة +لدالة مفردة — انظر §القسم 3)، وحاجز هجرة توجيهيّ للنمط القديم على نمط حاجز +`غير_متزامن دالة` القائم. + +# الدافع (Motivation) + +1. **اتّساق نحويّ عربيّ**: كلّ معدِّلات لغة ص لاحقة اليوم — «دالة ساكن»، + «متغير عام»، «دالة غير_متزامن»، «متغير ثابت». `خارجي دالة` هو الاستثناء + الوحيد الباقي من ترتيب الصفة الإنجليزيّ (`extern function`). +2. **سابقة ملزمة منطقيًّا**: اللغة أزالت فعليًّا `غير_متزامن دالة` بحاجز خطأ + توجيهيّ. إبقاء `خارجي دالة` يجعل رسالة ذلك الحاجز («في العربية الصفة تأتي + بعد الاسم») متناقضة مع بنية حيّة أخرى في اللغة نفسها. +3. **قابليّة التعلّم**: قاعدة واحدة بلا استثناءات («المعدِّل يلي دالة/متغير») + أسهل تعليمًا وأسهل على أدوات الإكمال (LSP/المقتطفات) من قاعدة + استثناء. +4. **نافذة زمنيّة**: FFI ما يزال محدود الانتشار في برامج `.ص` (صيغة الكتلة + `experimental` في SoT)، فتكلفة الهجرة اليوم أدنى ممّا ستكون لاحقًا. + +# الشرح التوجيهي (Guide-level explanation) + +بعد المقترح، تُكتب تصاريح الربط الخارجيّ المفردة هكذا: + +```sad +# الشكل الأساسيّ — الصفة بعد الموصوف +دالة خارجي printf(نص) + +# نوع الإرجاع الاختياريّ — يبقى قبل اسم الدالة (كما في دالة عاديّة) +دالة خارجي رقم clear_screen() + +# اسم الربط الاختياريّ — يبقى ملتصقًا بـ«خارجي» بين قوسين +دالة خارجي("cos") عشري جيب_التمام(عشري) +``` + +وتبقى كتلة الربط كما هي (بنية حاوية تسبق دوالّ متعدّدة): + +```sad +خارجي "C" + دالة رقم getchar() + دالة putchar(رقم) +نهاية +``` + +ومن يكتب النمط القديم يتلقّى رسالة توجيهيّة (لا انهيارًا غامضًا): + +``` +خطأ نحوي: 'خارجي دالة' أُزيلت. استخدم 'دالة خارجي' بدلاً منها. +💡 في العربية الصفة تأتي بعد الاسم: دالة خارجي printf(نص) +💡 مثال: + دالة خارجي("cos") عشري جيب_التمام(عشري) +``` + +## 1) الصيغة المقترحة للمفرد ومواضع اسم الربط والنوع + +الصيغة الكاملة المقترحة (EBNF): + +``` +ExternDeclaration = 'دالة' 'خارجي' [ '(' StringLiteral ')' ] [ Type ] + Identifier '(' [ Parameters ] ')' ; +``` + +- **موضع اسم الربط**: يبقى بين قوسين **ملتصقًا بـ«خارجي» مباشرةً** — + `دالة خارجي("رمز")`. المسوّغ: اسم الربط **معمولُ الصفة** لا معمول الدالة؛ + هو يجيب عن سؤال «خارجيٌّ بأيّ رمز؟»، فبقاؤه لصيق الصفة يحفظ الدلالة + ويُبقي التحليل النحويّ محدَّدًا (بعد «خارجي»: قوس ⇒ اسم ربط؛ غير ذلك ⇒ + نوع/اسم). البديل المرفوض `دالة("رمز") خارجي` يفصل المعمول عن عامله ويلتبس + باستدعاء دالة. +- **موضع نوع الإرجاع**: يبقى **قبل اسم الدالة** — `دالة خارجي رقم اسم()` — + اتّساقًا حرفيًّا مع الدالة العاديّة `دالة رقم اسم()` (gr.decl.function). + ترتيب «خارجي ثمّ النوع» محسوم بأنّ «خارجي» صفة للدالة كلّها بينما النوع + جزء من توقيعها؛ ولأنّ المحلّل الحيّ أصلًا يفصل الموضعين (اسم الربط يُلتقط + في `parseDeclaration` والنوع في `parseExternFunctionDecl`) فالتغيير + التنفيذيّ محصور في نقطة دخول واحدة. +- **الترتيب مع معدِّلات أخرى**: «خارجي» تنافي دلاليًّا `غير_متزامن` والمولّدات + (التصريح بلا جسم)، فلا مسألة ترتيب مركّب اليوم. إن استُحدث مستقبلًا معدِّل + متوافق، يسري عرف اللغة: المعدِّلات تتوالى بعد «دالة» («دالة ساكن عام» قياسًا + على «متغير ساكن عام» الحيّ في SoT). + +## 2) حسم التأنيث: «دالة خارجي» لا «دالة خارجية» + +الخياران المدروسان: + +| | «دالة خارجي» (مذكّر ثابت) | «دالة خارجية» (توافق نحويّ) | +|---|---|---| +| الفصاحة العربيّة | أدنى (تنافر تأنيث ظاهر) | أعلى | +| اتّساق مع العرف الحيّ | كامل — «دالة ساكن»، «متغير عام»، «دالة غير_متزامن» | يكسر العرف ويفتح إعادة تسمية رجعيّة | +| الأثر الرجعيّ | صفر | «ساكنة/عامة/مجردة/ثابتة» على كلّ الموصوفات المؤنّثة + ازدواج مع «متغير» المذكّر («متغير عام» تبقى، «دالة عامة» تُستحدث) ⇒ **قاعدة اتّفاق نحويّ كاملة في المعجم** | +| كلفة الأدوات | كلمة واحدة كما هي (KW-RES-037) | كلمة جديدة أو مرادف لكلّ معدِّل مؤنَّث | + +**التوصية: الخيار الأوّل — «دالة خارجي» بالمعدِّل الثابت غير المؤنَّث.** +المسوّغ: المعدِّلات في لغة ص **كلمات مفتاحيّة اصطلاحيّة** لا نعوت حرّة؛ +اختارت اللغة منذ البدء صيغة المذكّر الثابت («ساكن»، «عام»، «مجرد») أيًّا كان +جنس الموصوف، وهذا قرار معجميّ متّخذ لا يعيد هذا الـRFC فتحه. إدخال «خارجية» +وحدها يخلق ازدواجًا (لماذا «دالة خارجية» و«دالة ساكن»؟) ويستدرج إمّا شذوذًا +دائمًا وإمّا هجرة رجعيّة شاملة لكلّ المعدِّلات لا يبرّرها حجم المكسب. **إن** +رغب المجتمع مستقبلًا في الاتّفاق النحويّ الكامل (مؤنَّث مع المؤنَّث) فذلك +RFC مستقلّ يطال «ساكن/عام/مجرد/غير_متزامن» جميعًا دفعة واحدة، وقرارنا هنا +لا يستبقه ولا يعرقله. + +## 3) مصير صيغة الكتلة `خارجي "C" ... نهاية` + +الكتلة **لا يمكن قلبها** لصفة لاحقة: «خارجي» فيها لا تصف دالةً مفردة بل تفتح +**نطاق ربطٍ** يضمّ دوالّ متعدّدة تسبقها. القلب الحرفيّ (`"C" خارجي`؟) عبث، +وتعليق الصفة على كلّ دالة داخليّة يلغي جدوى الكتلة أصلًا. + +**التوصية: إبقاء الكتلة كما هي، مع إعادة توصيفها لا كصفة بل كبنية حاوية.** +المسوّغ الاتّساقيّ: لغة ص تعرف أصلًا كلماتٍ تفتتح بنى حاوية باسمها — +«فضاء اسم ... نهاية»، «صنف اسم ... نهاية». «خارجي "C"» من هذا الجنس: **خبرٌ +عن النطاق** لا نعتٌ لدالة، والدوالّ داخلها تُكتب `دالة اسم(...)` بلا تكرار +«خارجي» (هذا هو السلوك الحيّ فعلًا — `parser_main.cpp:517-557`). وبذلك يصير +التقسيم الدلاليّ نظيفًا: + +- **صفة لاحقة** للتصريح المفرد: `دالة خارجي [("رمز")] [نوع] اسم(...)`. +- **بنية حاوية** للنطاق: `خارجي "نصّ_الربط" { دالة ... } نهاية`. + +بديل دُرس ورُفض: استحداث رأسٍ صريح مثل `كتلة خارجي "C"` — يضيف كلمة/تركيبًا +جديدًا بلا مكسب دلاليّ، ويكسر كلّ كود الكتل القائم مجّانًا. + +تفصيلة حسم إضافيّة: بعد المقترح يظلّ التمييز النحويّ عند «خارجي» الافتتاحيّة +قاطعًا — نصّ حرفيّ عارٍ بعدها ⇒ كتلة؛ أيّ شيء آخر بعد «خارجي» في صدر تصريح ⇒ +حاجز الهجرة (§4). ويُحسم هنا سؤال فرعيّ: **هل يجوز اسم ربط لدالة داخل كتلة؟** +التوصية: نعم لاحقًا كامتداد طبيعيّ (`دالة("رمز") ...` داخل الكتلة تلتبس +بالاستدعاء، أمّا `دالة خارجي("رمز")` داخل الكتلة فتكرار للصفة) — يُرحَّل +كسؤال غير محسوم ولا يعطّل هذا الـRFC. + +## 4) مسار الهجرة + +على نمط حاجز `غير_متزامن دالة` القائم حرفيًّا (`parser_main.cpp:568-591`): + +- **المرحلة 0 (إصدار n — هذا الـRFC)**: المحلّل يقبل الصيغة الجديدة + `دالة خارجي ...` (توسيع `parseFunctionDecl` ليلتقط «خارجي» بعد «دالة» + ويفوّض إلى `parseExternFunctionDecl`)، **ويبقي القديمة تعمل مع تحذير + إهلاك** موجَّه (نفس نصّ الحاجز أدناه بصيغة تحذير). كتلة `خارجي "نصّ"` لا + تمسّها المرحلة إطلاقًا. +- **المرحلة 1 (إصدار n+1)**: القديمة تصير **خطأً نحويًّا بحاجز توجيهيّ** + يستهلك الرمزين ويكمل التعافي (كما يفعل حاجز `غير_متزامن` اليوم): + رسالة ثنائيّة اللغة عبر `errorBilingual` نصّها الجوهريّ: + «'خارجي دالة' أُزيلت. استخدم 'دالة خارجي' — في العربية الصفة تأتي بعد + الاسم» + مثال تصحيحيّ يعيد بناء سطر المستخدم نفسه إن أمكن. +- **المرحلة 2 (إصدار n+2 أو أبعد)**: يُزال الحاجز نفسه (تنظيف)، أسوةً + بجدولة إزالة حواجز مماثلة. ملاحظة تنفيذيّة: إزالة الحاجز تُبقي «خارجي» + في صدر التصريح ملتقطةً بمسار الكتلة فقط، فيلزم إبقاء رسالة خطأ افتراضيّة + واضحة («توقّع نصّ ربط بعد 'خارجي'») كي لا يرتدّ النمط القديم إلى خطأ غامض. + +أداة مساعدة (اختياريّة، ضمن المرحلة 0): قاعدة تصحيح تلقائيّ في LSP/نِبراس +(QuickFix يقلب `خارجي دالة` إلى `دالة خارجي`) — التحويل نصّيّ حتميّ +خالٍ من الالتباس، فهو مرشّح مثاليّ لإصلاح آليّ شامل للمستودعات. + +## 5) الأثر على مصدر الحقيقة والمستهلكين + +- **`gr.decl.extern` (`language-truth/grammar/20_declarations.yaml:243`)**: + قلب ترتيب الرمزين الأوّلين في EBNF وalternatives إلى + `'دالة' 'خارجي' [ '(' StringLiteral ')' ] [ Type ] Identifier ...` + وتحديث description_ar والأمثلة. (ملاحظة: سدّ فجوتَي اسم الربط ونوع الإرجاع + في هذه القاعدة **يجري مستقلًّا الآن** كتوثيقٍ للواقع الحيّ؛ هذا الـRFC + يبني فوقه فلا تعارض.) +- **`gr.adv.ffi_extern_block` و`gr.adv.ffi_linkage` (`60_advanced.yaml:439,463`)**: + لا تغيير نحويًّا (القرار §3 يبقي الكتلة)؛ يلزم فقط تحديث description_ar + ليعكس التوصيف الجديد (بنية حاوية مقابل صفة لاحقة) والإحالة المتبادلة. +- **المحلّل**: نقطتا تعديل — التقاط «خارجي» في `parseFunctionDecl` (الصيغة + الجديدة)، وتحويل فرع `KEYWORD_EXTERN` في `parseDeclaration` إلى: كتلة + (نصّ عارٍ) أو حاجز هجرة (أيّ شيء آخر). `parseExternFunctionDecl` نفسها + بلا تغيير تقريبًا (التوقيع الداخليّ ثابت). +- **AST/المفسّر/المترجم**: **صفر تغيير** — العقدة `FunctionDecl` بحقلَي + `isExtern`/`linkName` كما هي؛ التغيير نحويّ سطحيّ بحت. +- **الاختبارات**: كلّ اختبارات FFI الموسومة بميزانيّة gr.decl.extern + (basic 4/edge 3/negative 2/interaction 1) تُحدَّث للصيغة الجديدة + اختبارات + سلبيّة جديدة للحاجز (النمط القديم ⇒ الرسالة التوجيهيّة) قياسًا على اختبارات + حاجز `غير_متزامن`. اختبارات الكتلة (gr.adv.ffi_extern_block) بلا مساس. +- **الأدوات المستهلكة**: tmGrammar (تلوين `دالة خارجي`)، المقتطفات + (gen_snippets — مقتطف extern)، LSP (الإكمال + الرموز الدلاليّة)، REPL + (كشف الكتل متعدّدة الأسطر لا يتأثّر — «نهاية» للكتلة فقط)، الوثائق المولَّدة + (`docs/parser_rule/_generated` تتجدّد آليًّا من SoT)، sadlang-docs، + وأمثلة نواة النحلة/sad-os المستعملة لـ`خارجي دالة` (هجرة نصّيّة حتميّة). +- **التوافق الخلفيّ**: كاسر عمدًا للصيغة المفردة القديمة، بمسار هجرة متدرّج + (§4) وتحويل آليّ ممكن. صيغة الكتلة متوافقة تمامًا. + +# السلبيات (Drawbacks) + +- كسر توافق خلفيّ حقيقيّ (وإن كان FFI قليل الانتشار بعد). +- ازدواج مؤقّت: «خارجي» صفة لاحقة في المفرد وكلمة افتتاحيّة في الكتلة — + يُخفَّف بالتوصيف الدلاليّ الواضح (§3) وبأنّ الكتلة لا تحوي «دالة خارجي» + داخلها أصلًا. +- تكلفة تحديث سلسلة الأدوات كاملة (وإن كان معظمها مولَّدًا من SoT آليًّا). + +# المبرّرات والبدائل (Rationale and alternatives) + +- **عدم الفعل**: يُبقي تناقضًا معلنًا مع مبدأ SoT ومع رسالة حاجز حيّة في + المحلّل — كلفة مصداقيّة تتفاقم مع انتشار FFI. +- **قبول الصيغتين للأبد**: يضاعف سطح الاختبار والتوثيق ويميّع القاعدة + النحويّة؛ رُفض كما رُفض لـ`غير_متزامن`. +- **`دالة خارجية` (مؤنَّثة)**: نوقش ورُفض في §2. +- **قلب الكتلة أو استبدالها**: نوقش ورُفض في §3. + +# أعمال سابقة (Prior art) + +- **لغة ص نفسها**: إزالة `غير_متزامن دالة` — السابقة الحاكمة شكلًا ومسارًا + (حاجز توجيهيّ ثنائيّ اللغة ثمّ إزالة). +- **Rust**: `extern "C" fn` و`extern "C" { ... }` — تعايش صيغة مفردة وكتلة + بنفس الكلمة، وهو ما نستبقيه مع نقل موضع الصفة عربيًّا. +- **Zig**: المعدِّلات (`export`/`extern`) لصيقة التصريح بموضع ثابت — قيمة + القاعدة الواحدة بلا استثناء. +- الخصوصيّة العربيّة تقلب اتّجاه الاقتباس: ما هو «بادئة» في اللغات اللاتينيّة + حقّه عربيًّا التأخير عن الموصوف. + +# أسئلة غير محسومة (Unresolved questions) + +- هل يُسمح باسم ربط لدالة **داخل** كتلة `خارجي "C"` (اقتراح مبدئيّ: + `دالة خارجي("رمز") ...` داخل الكتلة)، أم يبقى اسم الربط حكرًا على المفرد؟ +- طول نافذة الإهلاك بالضبط (إصدار واحد أم اثنان قبل الحاجز الصلب) — رهن + إحصاء استعمال FFI الفعليّ في المستودعات المعروفة وقت القبول. +- هل يُشحن التصحيح الآليّ (QuickFix) مع المرحلة 0 نفسها أم يلحقها. From be01ad91a32902bf391c4c814c15106ffe14f3d0 Mon Sep 17 00:00:00 2001 From: Sad Lang Dev Date: Sat, 11 Jul 2026 10:26:21 +0300 Subject: [PATCH 2/4] =?UTF-8?q?=D8=AA=D8=B1=D9=82=D9=8A=D9=85=20RFC=20?= =?UTF-8?q?=E2=80=8F0034=20=D9=88=D9=81=D9=82=20=D8=B1=D9=82=D9=85=20?= =?UTF-8?q?=D8=A7=D9=84=D9=80PR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- ...\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename "text/0000-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" => "text/0034-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" (99%) diff --git "a/text/0000-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" "b/text/0034-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" similarity index 99% rename from "text/0000-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" rename to "text/0034-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" index cfc3208..b2b7895 100644 --- "a/text/0000-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" +++ "b/text/0034-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" @@ -1,7 +1,7 @@ - **عنوان المقترح:** نقل «خارجي» إلى موضع الصفة اللاحقة — «دالة خارجي» بدل «خارجي دالة» - **النطاق:** لغة `text/` (المحلّل النحويّ + مصدر الحقيقة + الأدوات المستهلِكة) - **تاريخ البدء:** 2026-07-11 -- **رقم الـ RFC:** (يُترك فارغاً حتى الدمج) +- **رقم الـ RFC:** 0034 - **الحالة:** مسودّة - **Issue التتبُّع:** (يُترك فارغاً حتى القبول) From a30b1214163692be31810532994586246d26c88c Mon Sep 17 00:00:00 2001 From: Sad Lang Dev Date: Sat, 11 Jul 2026 10:37:57 +0300 Subject: [PATCH 3/4] =?UTF-8?q?=D9=82=D8=B1=D8=A7=D8=B1=20=D8=A7=D9=84?= =?UTF-8?q?=D9=85=D8=A7=D9=84=D9=83:=20=D8=A7=D9=84=D8=B5=D9=81=D8=A9=20?= =?UTF-8?q?=D8=A7=D9=84=D9=84=D8=A7=D8=AD=D9=82=D8=A9=20=D8=A8=D9=85=D8=B7?= =?UTF-8?q?=D8=A7=D8=A8=D9=82=D8=A9=20=D8=A7=D9=84=D8=AC=D9=86=D8=B3=20?= =?UTF-8?q?=E2=80=94=20=C2=AB=D8=AF=D8=A7=D9=84=D8=A9=20=D8=AE=D8=A7=D8=B1?= =?UTF-8?q?=D8=AC=D9=8A=D8=A9=C2=BB=20=D9=84=D8=A7=20=C2=AB=D8=AF=D8=A7?= =?UTF-8?q?=D9=84=D8=A9=20=D8=AE=D8=A7=D8=B1=D8=AC=D9=8A=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - EBNF بنصّ القرار: 'دالة' 'خارجية' [('رمز')] [نوع] اسم(...) - قاعدة معياريّة عامّة: لفظ الصفة يتبع جنس الموصوف قبلها - §2 قُلبت: المطابقة مقدَّمة على الاتّساق مع عرف «دالة ساكن» — مواءمة المعدِّلات القائمة RFC مستقلّ لاحق - تسجيل «خارجية» في كتالوج المفردات ضمن الأثر على SoT Co-Authored-By: Claude Fable 5 --- ...31\204\330\247\330\255\331\202\330\251.md" | 172 ++++++++++-------- 1 file changed, 92 insertions(+), 80 deletions(-) diff --git "a/text/0034-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" "b/text/0034-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" index b2b7895..4e71c5d 100644 --- "a/text/0034-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" +++ "b/text/0034-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" @@ -1,4 +1,4 @@ -- **عنوان المقترح:** نقل «خارجي» إلى موضع الصفة اللاحقة — «دالة خارجي» بدل «خارجي دالة» +- **عنوان المقترح:** نقل صفة الربط الخارجيّ إلى موضع الصفة اللاحقة بمطابقة الجنس — «دالة خارجية» بدل «خارجي دالة» - **النطاق:** لغة `text/` (المحلّل النحويّ + مصدر الحقيقة + الأدوات المستهلِكة) - **تاريخ البدء:** 2026-07-11 - **رقم الـ RFC:** 0034 @@ -12,28 +12,33 @@ مصدر الحقيقة «**الصفة بعد الموصوف**» (`20_declarations.yaml:29,53` وعموم `30_oop.yaml`)، ويخالف السابقة المباشرة التي أزالت `غير_متزامن دالة` لصالح `دالة غير_متزامن` بحاجز هجرة صريح نصُّه «في العربية الصفة تأتي بعد الاسم» -(`shared/parser/src/core/parser_main.cpp` بعد السطر ~568). المقترح: نقل -«خارجي» إلى موضع الصفة اللاحقة في صيغة التصريح المفرد: +(`shared/parser/src/core/parser_main.cpp` بعد السطر ~568). المقترح — **بقرار +مالك اللغة**: نقل صفة الربط الخارجيّ إلى موضع الصفة اللاحقة **مع مطابقة +الموصوف في الجنس** («دالة» مؤنّثة ⇒ «خارجية»): ```sad -دالة خارجي printf(نص) -دالة خارجي("cos") عشري جيب_التمام(عشري) +دالة خارجية printf(نص) +دالة خارجية("cos") عشري جيب_التمام(عشري) ``` -مع إبقاء **صيغة الكتلة** `خارجي "C" ... نهاية` كما هي (فهي بنية حاوية لا صفة -لدالة مفردة — انظر §القسم 3)، وحاجز هجرة توجيهيّ للنمط القديم على نمط حاجز -`غير_متزامن دالة` القائم. +وتُرسى بهذا **قاعدة عامّة**: لفظ الصفة يتبع جنس الموصوف الذي قبلها — +«خارجية» بعد موصوف مؤنّث (دالة)، و«خارجي» بعد موصوف مذكّر (إن استُحدث +موصوفٌ مذكّر يقبل هذه الصفة مستقبلًا). مع إبقاء **صيغة الكتلة** +`خارجي "C" ... نهاية` كما هي (فهي بنية حاوية لا صفة لدالة مفردة — انظر +§القسم 3)، وحاجز هجرة توجيهيّ للنمط القديم على نمط حاجز `غير_متزامن دالة` +القائم. # الدافع (Motivation) -1. **اتّساق نحويّ عربيّ**: كلّ معدِّلات لغة ص لاحقة اليوم — «دالة ساكن»، - «متغير عام»، «دالة غير_متزامن»، «متغير ثابت». `خارجي دالة` هو الاستثناء - الوحيد الباقي من ترتيب الصفة الإنجليزيّ (`extern function`). -2. **سابقة ملزمة منطقيًّا**: اللغة أزالت فعليًّا `غير_متزامن دالة` بحاجز خطأ - توجيهيّ. إبقاء `خارجي دالة` يجعل رسالة ذلك الحاجز («في العربية الصفة تأتي - بعد الاسم») متناقضة مع بنية حيّة أخرى في اللغة نفسها. -3. **قابليّة التعلّم**: قاعدة واحدة بلا استثناءات («المعدِّل يلي دالة/متغير») - أسهل تعليمًا وأسهل على أدوات الإكمال (LSP/المقتطفات) من قاعدة + استثناء. +1. **اتّساق نحويّ عربيّ**: كلّ معدِّلات لغة ص لاحقة اليوم. `خارجي دالة` هو + الاستثناء الوحيد الباقي من ترتيب الصفة الإنجليزيّ (`extern function`). +2. **الفصاحة لا الموضع وحده**: نقل الموضع مع إبقاء التذكير («دالة خارجي») + يستبدل خطأً نحويًّا بآخر — تنافر تأنيث ظاهر لكلّ قارئ عربيّ. لغةٌ شعارها + السيادة اللغويّة لا تكتفي بنصف القاعدة: **الصفة بعد الموصوف، وتطابقه + جنسًا**. +3. **سابقة ملزمة منطقيًّا**: اللغة أزالت فعليًّا `غير_متزامن دالة` بحاجز خطأ + توجيهيّ. إبقاء `خارجي دالة` يجعل رسالة ذلك الحاجز متناقضة مع بنية حيّة + أخرى في اللغة نفسها. 4. **نافذة زمنيّة**: FFI ما يزال محدود الانتشار في برامج `.ص` (صيغة الكتلة `experimental` في SoT)، فتكلفة الهجرة اليوم أدنى ممّا ستكون لاحقًا. @@ -42,14 +47,14 @@ بعد المقترح، تُكتب تصاريح الربط الخارجيّ المفردة هكذا: ```sad -# الشكل الأساسيّ — الصفة بعد الموصوف -دالة خارجي printf(نص) +# الشكل الأساسيّ — الصفة بعد الموصوف بمطابقة الجنس +دالة خارجية printf(نص) # نوع الإرجاع الاختياريّ — يبقى قبل اسم الدالة (كما في دالة عاديّة) -دالة خارجي رقم clear_screen() +دالة خارجية رقم clear_screen() -# اسم الربط الاختياريّ — يبقى ملتصقًا بـ«خارجي» بين قوسين -دالة خارجي("cos") عشري جيب_التمام(عشري) +# اسم الربط الاختياريّ — يبقى ملتصقًا بالصفة بين قوسين +دالة خارجية("cos") عشري جيب_التمام(عشري) ``` وتبقى كتلة الربط كما هي (بنية حاوية تسبق دوالّ متعدّدة): @@ -64,58 +69,57 @@ ومن يكتب النمط القديم يتلقّى رسالة توجيهيّة (لا انهيارًا غامضًا): ``` -خطأ نحوي: 'خارجي دالة' أُزيلت. استخدم 'دالة خارجي' بدلاً منها. -💡 في العربية الصفة تأتي بعد الاسم: دالة خارجي printf(نص) +خطأ نحوي: 'خارجي دالة' أُزيلت. استخدم 'دالة خارجية' بدلاً منها. +💡 في العربية الصفة تأتي بعد الاسم وتطابقه في الجنس: دالة خارجية printf(نص) 💡 مثال: - دالة خارجي("cos") عشري جيب_التمام(عشري) + دالة خارجية("cos") عشري جيب_التمام(عشري) ``` ## 1) الصيغة المقترحة للمفرد ومواضع اسم الربط والنوع -الصيغة الكاملة المقترحة (EBNF): +الصيغة الكاملة المقترحة (EBNF) — بنصّ قرار المالك: ``` -ExternDeclaration = 'دالة' 'خارجي' [ '(' StringLiteral ')' ] [ Type ] +ExternDeclaration = 'دالة' 'خارجية' [ '(' StringLiteral ')' ] [ Type ] Identifier '(' [ Parameters ] ')' ; ``` -- **موضع اسم الربط**: يبقى بين قوسين **ملتصقًا بـ«خارجي» مباشرةً** — - `دالة خارجي("رمز")`. المسوّغ: اسم الربط **معمولُ الصفة** لا معمول الدالة؛ - هو يجيب عن سؤال «خارجيٌّ بأيّ رمز؟»، فبقاؤه لصيق الصفة يحفظ الدلالة - ويُبقي التحليل النحويّ محدَّدًا (بعد «خارجي»: قوس ⇒ اسم ربط؛ غير ذلك ⇒ - نوع/اسم). البديل المرفوض `دالة("رمز") خارجي` يفصل المعمول عن عامله ويلتبس +- **لفظ الصفة**: «خارجية» هنا لأنّ الموصوف «دالة» مؤنّث. القاعدة المعياريّة: + **الصفة تطابق جنس الكلمة التي قبلها** — فلو استُحدث مستقبلًا موصوف مذكّر + يقبل صفة الربط (مثلًا متغيّر خارجيّ) لكان لفظها معه «خارجي». +- **موضع اسم الربط**: يبقى بين قوسين **ملتصقًا بالصفة مباشرةً** — + `دالة خارجية("رمز")`. المسوّغ: اسم الربط **معمولُ الصفة** لا معمول الدالة؛ + هو يجيب عن سؤال «خارجيّةٌ بأيّ رمز؟»، فبقاؤه لصيق الصفة يحفظ الدلالة + ويُبقي التحليل النحويّ محدَّدًا (بعد «خارجية»: قوس ⇒ اسم ربط؛ غير ذلك ⇒ + نوع/اسم). البديل المرفوض `دالة("رمز") خارجية` يفصل المعمول عن عامله ويلتبس باستدعاء دالة. -- **موضع نوع الإرجاع**: يبقى **قبل اسم الدالة** — `دالة خارجي رقم اسم()` — +- **موضع نوع الإرجاع**: يبقى **قبل اسم الدالة** — `دالة خارجية رقم اسم()` — اتّساقًا حرفيًّا مع الدالة العاديّة `دالة رقم اسم()` (gr.decl.function). - ترتيب «خارجي ثمّ النوع» محسوم بأنّ «خارجي» صفة للدالة كلّها بينما النوع - جزء من توقيعها؛ ولأنّ المحلّل الحيّ أصلًا يفصل الموضعين (اسم الربط يُلتقط - في `parseDeclaration` والنوع في `parseExternFunctionDecl`) فالتغيير - التنفيذيّ محصور في نقطة دخول واحدة. -- **الترتيب مع معدِّلات أخرى**: «خارجي» تنافي دلاليًّا `غير_متزامن` والمولّدات - (التصريح بلا جسم)، فلا مسألة ترتيب مركّب اليوم. إن استُحدث مستقبلًا معدِّل - متوافق، يسري عرف اللغة: المعدِّلات تتوالى بعد «دالة» («دالة ساكن عام» قياسًا - على «متغير ساكن عام» الحيّ في SoT). - -## 2) حسم التأنيث: «دالة خارجي» لا «دالة خارجية» - -الخياران المدروسان: - -| | «دالة خارجي» (مذكّر ثابت) | «دالة خارجية» (توافق نحويّ) | -|---|---|---| -| الفصاحة العربيّة | أدنى (تنافر تأنيث ظاهر) | أعلى | -| اتّساق مع العرف الحيّ | كامل — «دالة ساكن»، «متغير عام»، «دالة غير_متزامن» | يكسر العرف ويفتح إعادة تسمية رجعيّة | -| الأثر الرجعيّ | صفر | «ساكنة/عامة/مجردة/ثابتة» على كلّ الموصوفات المؤنّثة + ازدواج مع «متغير» المذكّر («متغير عام» تبقى، «دالة عامة» تُستحدث) ⇒ **قاعدة اتّفاق نحويّ كاملة في المعجم** | -| كلفة الأدوات | كلمة واحدة كما هي (KW-RES-037) | كلمة جديدة أو مرادف لكلّ معدِّل مؤنَّث | - -**التوصية: الخيار الأوّل — «دالة خارجي» بالمعدِّل الثابت غير المؤنَّث.** -المسوّغ: المعدِّلات في لغة ص **كلمات مفتاحيّة اصطلاحيّة** لا نعوت حرّة؛ -اختارت اللغة منذ البدء صيغة المذكّر الثابت («ساكن»، «عام»، «مجرد») أيًّا كان -جنس الموصوف، وهذا قرار معجميّ متّخذ لا يعيد هذا الـRFC فتحه. إدخال «خارجية» -وحدها يخلق ازدواجًا (لماذا «دالة خارجية» و«دالة ساكن»؟) ويستدرج إمّا شذوذًا -دائمًا وإمّا هجرة رجعيّة شاملة لكلّ المعدِّلات لا يبرّرها حجم المكسب. **إن** -رغب المجتمع مستقبلًا في الاتّفاق النحويّ الكامل (مؤنَّث مع المؤنَّث) فذلك -RFC مستقلّ يطال «ساكن/عام/مجرد/غير_متزامن» جميعًا دفعة واحدة، وقرارنا هنا -لا يستبقه ولا يعرقله. + ترتيب «خارجية ثمّ النوع» محسوم بأنّ الصفة للدالة كلّها بينما النوع جزء + من توقيعها؛ ولأنّ المحلّل الحيّ أصلًا يفصل الموضعين (اسم الربط يُلتقط في + `parseDeclaration` والنوع في `parseExternFunctionDecl`) فالتغيير التنفيذيّ + محصور في نقطة دخول واحدة. +- **الترتيب مع معدِّلات أخرى**: «خارجية» تنافي دلاليًّا `غير_متزامن` + والمولّدات (التصريح بلا جسم)، فلا مسألة ترتيب مركّب اليوم. إن استُحدث + مستقبلًا معدِّل متوافق، يسري عرف اللغة: المعدِّلات تتوالى بعد «دالة». + +## 2) قاعدة مطابقة الجنس — قرار المالك وأثره الرجعيّ + +**القرار (مالك اللغة، 2026-07-11): الصفة تطابق الموصوف جنسًا** — «دالة +خارجية» لا «دالة خارجي». هذا يعكس التوصية الأوّليّة للمسودّة (التي رجّحت +المذكّر الثابت اتّساقًا مع «دالة ساكن» القائمة) ويحسم الاتّجاه المعياريّ: +الفصاحة العربيّة الكاملة مقدَّمة على الاتّساق مع عرفٍ قائم معيب. + +الأثر المباشر على المعجم والأدوات: + +- «خارجية» تدخل المعجم (كتالوج المفردات في SoT) لفظًا معياريًّا لصفة الربط + بعد موصوف مؤنّث. «خارجي» تبقى في المعجم لموضعين: افتتاح الكتلة + (`خارجي "C"`)، والصفة بعد موصوف مذكّر إن استُحدث. +- **تبعة معياريّة مفتوحة**: العرف الحاليّ «دالة ساكن»، «دالة عامة/عام»، + «دالة مجرد» يصير بعد هذا القرار **شذوذًا معلَنًا** عن قاعدة المطابقة. + مواءمة بقيّة المعدِّلات المؤنَّثة («ساكنة»، «مجردة»، ...) **RFC مستقلّ + لاحق** يطالها دفعة واحدة بمسار هجرة خاصّ — هذا الـRFC يرسي القاعدة ويطبّقها + على صفة الربط حصرًا، ولا يعدّل المعدِّلات القائمة. ## 3) مصير صيغة الكتلة `خارجي "C" ... نهاية` @@ -127,10 +131,10 @@ RFC مستقلّ يطال «ساكن/عام/مجرد/غير_متزامن» جم المسوّغ الاتّساقيّ: لغة ص تعرف أصلًا كلماتٍ تفتتح بنى حاوية باسمها — «فضاء اسم ... نهاية»، «صنف اسم ... نهاية». «خارجي "C"» من هذا الجنس: **خبرٌ عن النطاق** لا نعتٌ لدالة، والدوالّ داخلها تُكتب `دالة اسم(...)` بلا تكرار -«خارجي» (هذا هو السلوك الحيّ فعلًا — `parser_main.cpp:517-557`). وبذلك يصير +الصفة (هذا هو السلوك الحيّ فعلًا — `parser_main.cpp:517-557`). وبذلك يصير التقسيم الدلاليّ نظيفًا: -- **صفة لاحقة** للتصريح المفرد: `دالة خارجي [("رمز")] [نوع] اسم(...)`. +- **صفة لاحقة** للتصريح المفرد: `دالة خارجية [("رمز")] [نوع] اسم(...)`. - **بنية حاوية** للنطاق: `خارجي "نصّ_الربط" { دالة ... } نهاية`. بديل دُرس ورُفض: استحداث رأسٍ صريح مثل `كتلة خارجي "C"` — يضيف كلمة/تركيبًا @@ -140,7 +144,7 @@ RFC مستقلّ يطال «ساكن/عام/مجرد/غير_متزامن» جم قاطعًا — نصّ حرفيّ عارٍ بعدها ⇒ كتلة؛ أيّ شيء آخر بعد «خارجي» في صدر تصريح ⇒ حاجز الهجرة (§4). ويُحسم هنا سؤال فرعيّ: **هل يجوز اسم ربط لدالة داخل كتلة؟** التوصية: نعم لاحقًا كامتداد طبيعيّ (`دالة("رمز") ...` داخل الكتلة تلتبس -بالاستدعاء، أمّا `دالة خارجي("رمز")` داخل الكتلة فتكرار للصفة) — يُرحَّل +بالاستدعاء، أمّا `دالة خارجية("رمز")` داخل الكتلة فتكرار للصفة) — يُرحَّل كسؤال غير محسوم ولا يعطّل هذا الـRFC. ## 4) مسار الهجرة @@ -148,36 +152,38 @@ RFC مستقلّ يطال «ساكن/عام/مجرد/غير_متزامن» جم على نمط حاجز `غير_متزامن دالة` القائم حرفيًّا (`parser_main.cpp:568-591`): - **المرحلة 0 (إصدار n — هذا الـRFC)**: المحلّل يقبل الصيغة الجديدة - `دالة خارجي ...` (توسيع `parseFunctionDecl` ليلتقط «خارجي» بعد «دالة» + `دالة خارجية ...` (توسيع `parseFunctionDecl` ليلتقط الصفة بعد «دالة» ويفوّض إلى `parseExternFunctionDecl`)، **ويبقي القديمة تعمل مع تحذير إهلاك** موجَّه (نفس نصّ الحاجز أدناه بصيغة تحذير). كتلة `خارجي "نصّ"` لا تمسّها المرحلة إطلاقًا. - **المرحلة 1 (إصدار n+1)**: القديمة تصير **خطأً نحويًّا بحاجز توجيهيّ** يستهلك الرمزين ويكمل التعافي (كما يفعل حاجز `غير_متزامن` اليوم): رسالة ثنائيّة اللغة عبر `errorBilingual` نصّها الجوهريّ: - «'خارجي دالة' أُزيلت. استخدم 'دالة خارجي' — في العربية الصفة تأتي بعد - الاسم» + مثال تصحيحيّ يعيد بناء سطر المستخدم نفسه إن أمكن. + «'خارجي دالة' أُزيلت. استخدم 'دالة خارجية' — في العربية الصفة تأتي بعد + الاسم وتطابقه في الجنس» + مثال تصحيحيّ يعيد بناء سطر المستخدم نفسه إن أمكن. - **المرحلة 2 (إصدار n+2 أو أبعد)**: يُزال الحاجز نفسه (تنظيف)، أسوةً بجدولة إزالة حواجز مماثلة. ملاحظة تنفيذيّة: إزالة الحاجز تُبقي «خارجي» في صدر التصريح ملتقطةً بمسار الكتلة فقط، فيلزم إبقاء رسالة خطأ افتراضيّة واضحة («توقّع نصّ ربط بعد 'خارجي'») كي لا يرتدّ النمط القديم إلى خطأ غامض. أداة مساعدة (اختياريّة، ضمن المرحلة 0): قاعدة تصحيح تلقائيّ في LSP/نِبراس -(QuickFix يقلب `خارجي دالة` إلى `دالة خارجي`) — التحويل نصّيّ حتميّ +(QuickFix يقلب `خارجي دالة` إلى `دالة خارجية`) — التحويل نصّيّ حتميّ خالٍ من الالتباس، فهو مرشّح مثاليّ لإصلاح آليّ شامل للمستودعات. ## 5) الأثر على مصدر الحقيقة والمستهلكين - **`gr.decl.extern` (`language-truth/grammar/20_declarations.yaml:243`)**: - قلب ترتيب الرمزين الأوّلين في EBNF وalternatives إلى - `'دالة' 'خارجي' [ '(' StringLiteral ')' ] [ Type ] Identifier ...` + استبدال EBNF وalternatives بصيغة قرار المالك أعلاه + (`'دالة' 'خارجية' [ '(' StringLiteral ')' ] [ Type ] Identifier ...`) وتحديث description_ar والأمثلة. (ملاحظة: سدّ فجوتَي اسم الربط ونوع الإرجاع في هذه القاعدة **يجري مستقلًّا الآن** كتوثيقٍ للواقع الحيّ؛ هذا الـRFC يبني فوقه فلا تعارض.) +- **كتالوج المفردات (SoT)**: تسجيل «خارجية» لفظًا معياريًّا جديدًا (مقترنة + بـKEYWORD قائمة أو جديدة حسب معمار المعجم) — مع ملاحظة قاعدة المطابقة. - **`gr.adv.ffi_extern_block` و`gr.adv.ffi_linkage` (`60_advanced.yaml:439,463`)**: لا تغيير نحويًّا (القرار §3 يبقي الكتلة)؛ يلزم فقط تحديث description_ar ليعكس التوصيف الجديد (بنية حاوية مقابل صفة لاحقة) والإحالة المتبادلة. -- **المحلّل**: نقطتا تعديل — التقاط «خارجي» في `parseFunctionDecl` (الصيغة +- **المحلّل**: نقطتا تعديل — التقاط الصفة في `parseFunctionDecl` (الصيغة الجديدة)، وتحويل فرع `KEYWORD_EXTERN` في `parseDeclaration` إلى: كتلة (نصّ عارٍ) أو حاجز هجرة (أيّ شيء آخر). `parseExternFunctionDecl` نفسها بلا تغيير تقريبًا (التوقيع الداخليّ ثابت). @@ -187,20 +193,21 @@ RFC مستقلّ يطال «ساكن/عام/مجرد/غير_متزامن» جم (basic 4/edge 3/negative 2/interaction 1) تُحدَّث للصيغة الجديدة + اختبارات سلبيّة جديدة للحاجز (النمط القديم ⇒ الرسالة التوجيهيّة) قياسًا على اختبارات حاجز `غير_متزامن`. اختبارات الكتلة (gr.adv.ffi_extern_block) بلا مساس. -- **الأدوات المستهلكة**: tmGrammar (تلوين `دالة خارجي`)، المقتطفات +- **الأدوات المستهلكة**: tmGrammar (تلوين `دالة خارجية`)، المقتطفات (gen_snippets — مقتطف extern)، LSP (الإكمال + الرموز الدلاليّة)، REPL (كشف الكتل متعدّدة الأسطر لا يتأثّر — «نهاية» للكتلة فقط)، الوثائق المولَّدة (`docs/parser_rule/_generated` تتجدّد آليًّا من SoT)، sadlang-docs، - وأمثلة نواة النحلة/sad-os المستعملة لـ`خارجي دالة` (هجرة نصّيّة حتميّة). + والأمثلة والمشاريع المستهلِكة المكتوبة بـ`خارجي دالة` (هجرة نصّيّة حتميّة). - **التوافق الخلفيّ**: كاسر عمدًا للصيغة المفردة القديمة، بمسار هجرة متدرّج (§4) وتحويل آليّ ممكن. صيغة الكتلة متوافقة تمامًا. # السلبيات (Drawbacks) - كسر توافق خلفيّ حقيقيّ (وإن كان FFI قليل الانتشار بعد). -- ازدواج مؤقّت: «خارجي» صفة لاحقة في المفرد وكلمة افتتاحيّة في الكتلة — - يُخفَّف بالتوصيف الدلاليّ الواضح (§3) وبأنّ الكتلة لا تحوي «دالة خارجي» - داخلها أصلًا. +- ازدواج لفظيّ مؤقّت في المعجم: «خارجية» صفة المفرد و«خارجي» افتتاحيّة + الكتلة — يُخفَّف بالتوصيف الدلاليّ الواضح (§3) وبقاعدة المطابقة المعلنة. +- القرار يجعل المعدِّلات القائمة غير المطابِقة («دالة ساكن») شذوذًا معلَنًا + حتى يلحقها RFC المواءمة (§2) — فجوة اتّساق مقصودة ومؤقّتة. - تكلفة تحديث سلسلة الأدوات كاملة (وإن كان معظمها مولَّدًا من SoT آليًّا). # المبرّرات والبدائل (Rationale and alternatives) @@ -209,7 +216,9 @@ RFC مستقلّ يطال «ساكن/عام/مجرد/غير_متزامن» جم المحلّل — كلفة مصداقيّة تتفاقم مع انتشار FFI. - **قبول الصيغتين للأبد**: يضاعف سطح الاختبار والتوثيق ويميّع القاعدة النحويّة؛ رُفض كما رُفض لـ`غير_متزامن`. -- **`دالة خارجية` (مؤنَّثة)**: نوقش ورُفض في §2. +- **`دالة خارجي` (مذكّر ثابت)**: كان توصية المسودّة الأولى اتّساقًا مع + «دالة ساكن»؛ **رفضه مالك اللغة** لأنّه يستبدل مخالفةً نحويّة (الموضع) + بأخرى (المطابقة) — القاعدة العربيّة تؤخذ كاملة. - **قلب الكتلة أو استبدالها**: نوقش ورُفض في §3. # أعمال سابقة (Prior art) @@ -220,13 +229,16 @@ RFC مستقلّ يطال «ساكن/عام/مجرد/غير_متزامن» جم بنفس الكلمة، وهو ما نستبقيه مع نقل موضع الصفة عربيًّا. - **Zig**: المعدِّلات (`export`/`extern`) لصيقة التصريح بموضع ثابت — قيمة القاعدة الواحدة بلا استثناء. -- الخصوصيّة العربيّة تقلب اتّجاه الاقتباس: ما هو «بادئة» في اللغات اللاتينيّة - حقّه عربيًّا التأخير عن الموصوف. +- الخصوصيّة العربيّة تقلب اتّجاه الاقتباس مرّتين: ما هو «بادئة» لاتينيًّا + حقّه عربيًّا التأخير عن الموصوف، وما هو لفظ ثابت لاتينيًّا حقّه عربيًّا + المطابقة في الجنس. # أسئلة غير محسومة (Unresolved questions) - هل يُسمح باسم ربط لدالة **داخل** كتلة `خارجي "C"` (اقتراح مبدئيّ: - `دالة خارجي("رمز") ...` داخل الكتلة)، أم يبقى اسم الربط حكرًا على المفرد؟ + `دالة خارجية("رمز") ...` داخل الكتلة)، أم يبقى اسم الربط حكرًا على المفرد؟ +- نطاق وجدولة **RFC مواءمة المعدِّلات القائمة** مع قاعدة المطابقة + («ساكن»⇒«ساكنة» بعد دالة، ...) — يُفتح مستقلًّا (§2). - طول نافذة الإهلاك بالضبط (إصدار واحد أم اثنان قبل الحاجز الصلب) — رهن إحصاء استعمال FFI الفعليّ في المستودعات المعروفة وقت القبول. - هل يُشحن التصحيح الآليّ (QuickFix) مع المرحلة 0 نفسها أم يلحقها. From 09518a0a635487c51dead0575d327bbe40471763 Mon Sep 17 00:00:00 2001 From: Sad Lang Dev Date: Sat, 11 Jul 2026 10:54:22 +0300 Subject: [PATCH 4/4] =?UTF-8?q?=D9=82=D8=B1=D8=A7=D8=B1=20=D8=A7=D9=84?= =?UTF-8?q?=D9=85=D8=A7=D9=84=D9=83:=20=D9=82=D8=B7=D9=8A=D8=B9=D8=A9=20?= =?UTF-8?q?=D9=81=D9=88=D8=B1=D9=8A=D9=91=D8=A9=20=D8=A8=D9=84=D8=A7=20?= =?UTF-8?q?=D9=86=D8=A7=D9=81=D8=B0=D8=A9=20=D8=AF=D8=B9=D9=85=20=D9=85?= =?UTF-8?q?=D8=B2=D8=AF=D9=88=D8=AC=20=E2=80=94=20=D8=A7=D9=84=D8=B5=D9=8A?= =?UTF-8?q?=D8=BA=D8=A9=20=D8=A7=D9=84=D8=AC=D8=AF=D9=8A=D8=AF=D8=A9=20?= =?UTF-8?q?=D8=AD=D8=B5=D8=B1=D9=8B=D8=A7=20+=20=D8=AD=D8=A7=D8=AC=D8=B2?= =?UTF-8?q?=20=D8=AA=D9=88=D8=AC=D9=8A=D9=87=D9=8A=D9=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- ...31\204\330\247\330\255\331\202\330\251.md" | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git "a/text/0034-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" "b/text/0034-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" index 4e71c5d..4e16ecd 100644 --- "a/text/0034-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" +++ "b/text/0034-\331\206\331\202\331\204-\330\256\330\247\330\261\330\254\331\212-\330\245\331\204\331\211-\331\205\331\210\330\266\330\271-\330\247\331\204\330\265\331\201\330\251-\330\247\331\204\331\204\330\247\330\255\331\202\330\251.md" @@ -147,28 +147,28 @@ ExternDeclaration = 'دالة' 'خارجية' [ '(' StringLiteral ')' ] [ Type ] بالاستدعاء، أمّا `دالة خارجية("رمز")` داخل الكتلة فتكرار للصفة) — يُرحَّل كسؤال غير محسوم ولا يعطّل هذا الـRFC. -## 4) مسار الهجرة - -على نمط حاجز `غير_متزامن دالة` القائم حرفيًّا (`parser_main.cpp:568-591`): - -- **المرحلة 0 (إصدار n — هذا الـRFC)**: المحلّل يقبل الصيغة الجديدة - `دالة خارجية ...` (توسيع `parseFunctionDecl` ليلتقط الصفة بعد «دالة» - ويفوّض إلى `parseExternFunctionDecl`)، **ويبقي القديمة تعمل مع تحذير - إهلاك** موجَّه (نفس نصّ الحاجز أدناه بصيغة تحذير). كتلة `خارجي "نصّ"` لا - تمسّها المرحلة إطلاقًا. -- **المرحلة 1 (إصدار n+1)**: القديمة تصير **خطأً نحويًّا بحاجز توجيهيّ** - يستهلك الرمزين ويكمل التعافي (كما يفعل حاجز `غير_متزامن` اليوم): - رسالة ثنائيّة اللغة عبر `errorBilingual` نصّها الجوهريّ: - «'خارجي دالة' أُزيلت. استخدم 'دالة خارجية' — في العربية الصفة تأتي بعد - الاسم وتطابقه في الجنس» + مثال تصحيحيّ يعيد بناء سطر المستخدم نفسه إن أمكن. -- **المرحلة 2 (إصدار n+2 أو أبعد)**: يُزال الحاجز نفسه (تنظيف)، أسوةً - بجدولة إزالة حواجز مماثلة. ملاحظة تنفيذيّة: إزالة الحاجز تُبقي «خارجي» - في صدر التصريح ملتقطةً بمسار الكتلة فقط، فيلزم إبقاء رسالة خطأ افتراضيّة - واضحة («توقّع نصّ ربط بعد 'خارجي'») كي لا يرتدّ النمط القديم إلى خطأ غامض. - -أداة مساعدة (اختياريّة، ضمن المرحلة 0): قاعدة تصحيح تلقائيّ في LSP/نِبراس -(QuickFix يقلب `خارجي دالة` إلى `دالة خارجية`) — التحويل نصّيّ حتميّ -خالٍ من الالتباس، فهو مرشّح مثاليّ لإصلاح آليّ شامل للمستودعات. +## 4) مسار الهجرة — قطيعة فوريّة بقرار المالك + +**قرار المالك (2026-07-11): لا توافق خلفيّ ولا نافذة دعم مزدوج** — تُعتمد +الصيغة الجديدة وحدها فورًا. (المسودّة الأولى اقترحت ثلاث مراحل متدرّجة على +نمط إهلاك `غير_متزامن`؛ أُسقطت لصالح القطيعة لأنّ FFI محدود الانتشار +والمستودعات المستهلِكة معدودة وتحت سيطرة المشروع.) + +- **إصدار واحد (هذا الـRFC)**: المحلّل يقبل `دالة خارجية ...` حصرًا، والصيغ + القديمة (`خارجي دالة ...` و`خارجي("رمز") دالة ...`) تصير **خطأً نحويًّا + بحاجز توجيهيّ** يستهلك الرموز ويكمل التعافي (كما يفعل حاجز `غير_متزامن` + اليوم — `parser_main.cpp:568-591`): رسالة ثنائيّة اللغة عبر `errorBilingual` + جوهرها: «'خارجي دالة' أُزيلت. استخدم 'دالة خارجية' — في العربية الصفة تأتي + بعد الاسم وتطابقه في الجنس» + مثال تصحيحيّ. +- كتلة `خارجي "نصّ"` لا يمسّها التغيير إطلاقًا (نصّ عارٍ بعد «خارجي» ⇒ كتلة؛ + أيّ شيء آخر ⇒ الحاجز). +- إزالة الحاجز نفسه لاحقًا (تنظيف) تُجدوَل كحواجز مماثلة، مع إبقاء رسالة + افتراضيّة واضحة («توقّع نصّ ربط بعد 'خارجي'») كي لا يرتدّ النمط القديم + إلى خطأ غامض. + +أداة مساعدة (اختياريّة): قاعدة تصحيح تلقائيّ في LSP/نِبراس (QuickFix يقلب +`خارجي دالة` إلى `دالة خارجية`) — التحويل نصّيّ حتميّ خالٍ من الالتباس، +فهو مرشّح مثاليّ لإصلاح آليّ شامل للمستودعات المستهلِكة. ## 5) الأثر على مصدر الحقيقة والمستهلكين @@ -198,8 +198,9 @@ ExternDeclaration = 'دالة' 'خارجية' [ '(' StringLiteral ')' ] [ Type ] (كشف الكتل متعدّدة الأسطر لا يتأثّر — «نهاية» للكتلة فقط)، الوثائق المولَّدة (`docs/parser_rule/_generated` تتجدّد آليًّا من SoT)، sadlang-docs، والأمثلة والمشاريع المستهلِكة المكتوبة بـ`خارجي دالة` (هجرة نصّيّة حتميّة). -- **التوافق الخلفيّ**: كاسر عمدًا للصيغة المفردة القديمة، بمسار هجرة متدرّج - (§4) وتحويل آليّ ممكن. صيغة الكتلة متوافقة تمامًا. +- **التوافق الخلفيّ**: كاسر عمدًا وفوريًّا للصيغة المفردة القديمة — قطيعة + بلا نافذة دعم مزدوج بقرار المالك (§4)، مع حاجز توجيهيّ وتحويل آليّ ممكن. + صيغة الكتلة متوافقة تمامًا. # السلبيات (Drawbacks) @@ -239,6 +240,6 @@ ExternDeclaration = 'دالة' 'خارجية' [ '(' StringLiteral ')' ] [ Type ] `دالة خارجية("رمز") ...` داخل الكتلة)، أم يبقى اسم الربط حكرًا على المفرد؟ - نطاق وجدولة **RFC مواءمة المعدِّلات القائمة** مع قاعدة المطابقة («ساكن»⇒«ساكنة» بعد دالة، ...) — يُفتح مستقلًّا (§2). -- طول نافذة الإهلاك بالضبط (إصدار واحد أم اثنان قبل الحاجز الصلب) — رهن - إحصاء استعمال FFI الفعليّ في المستودعات المعروفة وقت القبول. -- هل يُشحن التصحيح الآليّ (QuickFix) مع المرحلة 0 نفسها أم يلحقها. +- موعد إزالة الحاجز التوجيهيّ نفسه (التنظيف النهائيّ) — حُسم عدم وجود نافذة + دعم مزدوج (§4)، وبقي فقط جدول تقاعد رسالة الحاجز. +- هل يُشحن التصحيح الآليّ (QuickFix) مع دفعة التنفيذ نفسها أم يلحقها.