Skip to content
Merged
Show file tree
Hide file tree
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
Expand Up @@ -87,6 +87,12 @@
كسر قاطع) لأنّه يُبقي النمط الأعجميّ حيًّا ويضاعف مصدر الحقيقة.
- **الإبقاء على الحال**: مرفوض — يرسّخ تناقضًا نحويًّا في قلب اللغة.

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

- **كسر قاطع لكلّ مستهلك**: أيّ برنامج ص يستعمل الأسماء القديمة يتوقّف عن الترجمة
حتى يُرحَّل (تفصيله في قسم التوافق أدناه).
- **عبء ترحيل تابع**: مستودعات ص الخارجيّة (sad-os مثلًا) يلزمها ترحيل متزامن.

# التأثير على التوافق (Compatibility / Migration)

**كسر قاطع**: كلّ برنامج ص يستعمل الأسماء القديمة يتوقّف عن الترجمة حتى يُرحَّل.
Expand All @@ -97,7 +103,20 @@
- **دَين معلَن**: `sad-os` وأيّ مستودع ص آخر يستعمل هذه المدمجات يلزمه ترحيل تابع
(يُتتبَّع بـIssue منفصل عند القبول).

# الأسئلة المفتوحة (Unresolved questions)
# أعمال سابقة (Prior art)

- **ترتيب فعل-فاعل في العربيّة الفصحى**: الجملة الفعليّة تبدأ بالفعل («اقرأ المنفذ»)،
وهو الأصل النحويّ الذي تبني عليه هذه القاعدة.
- **تسمية دوالّ POSIX/النظم (`read`/`write`/`ioctl`)**: الفعل أوّلًا سابقة راسخة في
واجهات العتاد، تُعرَّب هنا بالحفاظ على البنية الفعليّة لا قلبها.
- **مبدأ «مصدر حقيقة وحيد» في قلب اللغة الموحَّد (RFC #10)**: يمنع ازدواج التسمية.

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

- هل تُعمَّم قاعدة «فعل-أوّلًا» لاحقًا على مدمجات أخرى مقلوبة إن وُجدت (تدقيق شامل
للكتالوج)؟ يُقترح تدقيقٌ تابع بعد إقرار هذا المبدأ.

# أعمال مستقبلية (Future work)

- تدقيق شامل لكتالوج المدمجات يكشف أيّ اسم مقلوب متبقٍّ ويوحّده على «فعل-أوّلًا».
- توثيق القاعدة في دليل المطوّر كي تُطبَّق على أيّ مدمج عتاد جديد تلقائيًّا.
127 changes: 127 additions & 0 deletions text/0000-رموز-سبب-الهلع-المسمّاة.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
- **عنوان المقترح:** رموز سبب الهلع المسمّاة (ABI نداء `__sad_panic` في الوضع الحرّ) + تمييز فشل التأكيد
- **النطاق:** لغة `text/`
- **تاريخ البدء:** 2026-07-22
- **رقم الـ RFC:** 49 (رقم PR هذا المقترح)
- **الحالة:** مقترَح (PR مفتوح: sadlang/rfcs#49) — نُفِّذ في المترجم sadlang/s-programming-language#248 (مدموج) واستهلكته نواة النحلة (المرحلة ب، مدموجة)
- **Issue التتبُّع:** (يُترك فارغاً حتى القبول)

# ملخّص

في الوضع الحرّ، كلّ مواقع نداء `__sad_panic` الخمسة في المولِّد تمرّر الوسيطَ
الثابتَ السحريّ `1`. فيُصنّف البرنامج الحرّ (نواة النحلة) **كلّ** أنواع الفشل رمزًا
واحدًا (خطأ_انتهاك_مترجم). يقترح هذا المقترح: (١) استبدال `1` بثوابت مسمّاة في
`sir_constants.h` (عقد ABI)، و(٢) منح فشل عامل التأكيد `مؤكَّد` (نظير RUN056)
رمزًا مميَّزًا (`kSadPanicNullAssert = 2`) كي تُصنّفه النواة بدقّة لا كـ«تجاوز حدّ»،
و(٣) كبت سطر RUN056 العربيّ السابق للّافتة في الوضع الحرّ (اللافتة التشخيص الوحيد).

# الدافع (Motivation)

نواة النحلة تُخرِّط وسيط `__sad_panic` إلى لافتة `[هلع-ص نظام:<نظام> رمز:<رقم>]`.
لأنّ المولِّد يمرّر `1` دائمًا، تظهر كلّ الانتهاكات رمز:4 (خطأ_انتهاك_مترجم) —
بما فيها فشل عامل التأكيد على قيمة عدم، وهو **ليس** تجاوز حدّ ولا وسم تعداد خاطئ
بل تأكيد مستخدم انكسر. رصدت مراجعة سابقة هذا التصنيف الخاطئ. كما أنّ المولِّد يطبع
سطر RUN056 العربيّ قبل اللافتة في الوضع الحرّ (يخالف مبدأ «اللافتة التشخيص
الوحيد» الذي أرساه مقترح كبت التشخيص الإنجليزيّ).

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

للقارئ الذي يكتب برنامجًا حرًّا (نواة/محمَّل إقلاع) يعرّف `__sad_panic` بنفسه: بدل
أن تصل كلّ حالات الفشل القاتلة برمز واحد لا يميّز بينها، صار المولِّد يمرّر **رمز
سبب** يقول لماذا هلع البرنامج. اليوم قيمتان: `1` = فحص بنيويّ زرعه المولِّد
(تجاوز حدّ مصفوفة، وسم تعداد خاطئ، تأكيد وسيط) و`2` = فشل عامل التأكيد اللاحق
`مؤكَّد` (نظير RUN056: طُبِّق على قيمة عدم). يستقبل المستهلك القيمة معاملًا واحدًا
`(i64)` ويُخرِّطها إلى لافتته/كتالوجه كما يشاء — نواة النحلة مثلًا تُخرِّط `2` إلى
رمز خطأ مخصَّص (`خطأ_تأكيد_عدم`) فتظهر لافتة مميَّزة بدل خلطها مع تجاوز الحدّ. من
لا يعنيه التمييز يعامل أيّ قيمة ≠ الحالات المعروفة كفشل بنيويّ عامّ (سلوك آمن
افتراضيًّا: يوقِف دائمًا). لا يتغيّر توقيع ABI ولا نحو اللغة.

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

- عقد رموز السبب في `compiler/include/frontend/sir_constants.h`:
- `kSadPanicCheckViolation = 1` — فحص بنيويّ يزرعه المولِّد فشل (حدّ مصفوفة،
وسم تعداد خاطئ، إجهاض `abort`، مدمج أمنيّ). **يبقى 1** للتوافق التاريخيّ.
- `kSadPanicNullAssert = 2` — فشل عامل التأكيد اللاحق `مؤكَّد` على قيمة عدم.
حصريّ له؛ مدمجا `تأكد`/`ذعر` يبقيان 1.
- **مستقرّ:** لا تُعاد ترقمة القيم (المستهلكون يعتمدونها) — يحرسه
`static_assert(kSadPanicCheckViolation != kSadPanicNullAssert)`.
- رسالة RUN056 العربيّة رُفعت إلى ثابت مسمّى `kNullAssertRun056Msg` (لا سلسلة
حرفيّة منطقيّة في الكود).
- المواقع الخمسة (`array_ops`, `enum_ops`, `builtin_funcs_ops` assert, `security_builtins_ops`,
`arith_main` null-assert) صارت تستعمل الثوابت المسمّاة بدل `1`. أربعة تحمل
`kSadPanicCheckViolation`؛ `arith_main` وحده `kSadPanicNullAssert`.
- **توحيد بناء النداء:** دالّة `LLVMCodeGen::emitFreestandingPanicCall(reasonCode)`
(في `llvm_codegen.h`) تبني `call void @__sad_panic(i64 reason)` مرّة واحدة؛
وُحِّدت عليها المواقع الخمسة كي لا يُمرَّر رمز سبب خاطئ يدويًّا. لا تُصدر
`unreachable` (المنادي يضيفه، وقد يُشارَك مع المسار المستضاف).
- `arith_main` (الوضع الحرّ): كبت `printf("خطأ [RUN056]…")` — اللافتة العربيّة
السياديّة (النواة تُصنّفها «تأكيد على عدم» عبر رمز 2) هي التشخيص الوحيد. المستضاف
يُبقي RUN056 العربيّ + exit للمطوّر.
- `builtin_funcs_ops` (`emitBuiltinAssert` الكامن): نُقل سطر «Assertion failed»
الإنجليزيّ إلى فرع المستضاف حصرًا (إصلاح دفاعيّ؛ الواجهة تُخفِض `تأكد` إلى
`BUILTIN_SECURITY_ASSERT`/مسار الأمن `sec.fail` فهذا المسار غير مُنتَج اليوم).

# البدائل (Alternatives)

1. **رمز مميَّز لكلّ موقع** (حدّ/تعداد/إجهاض/أمن منفصلة): أدقّ لكنّه يوسّع كتالوج
المستهلك بلا حاجة الآن؛ المقترح يفصل الصنف الأهمّ (تأكيد) ويُبقي البنيويّة
موحَّدة (1)، قابلة للتوسيع لاحقًا (القيم 3+ متاحة).
2. **الإبقاء على `1` وتصنيف النواة داخليًّا:** مستحيل — النواة لا تملك سياقًا تميّز
به مصدر الهلع؛ الوسيط هو المعلومة الوحيدة.
3. **توسيع ABI بتمرير تفاصيل (فهرس/طول/رسالة):** يكسر تواقيع النواة القائمة
(`(i64)`)؛ خارج النطاق.

# السلبيات والمخاطر والتخفيف (Drawbacks)

- **مستهلك يفترض `1` دائمًا:** نواة النحلة حُدِّثت بالتوازي (المرحلة ب) لتُخرِّط 2 →
رمز كتالوج مخصَّص؛ سلوكها القديم (تجاهل الوسيط) يبقى صحيحًا لرمز 1. المستهلكون
الآخرون (إن وُجدوا) يرون 1 كما كان لكلّ ما عدا التأكيد.
- **الاحتياطيّ الضعيف `[SAD PANIC %lld]`:** يعرض الآن 1 أو 2 — تحسّن تشخيصيّ لا كسر.
- **عبء عقد ثنائيّ:** القيمتان تصيران عقدًا مستقرًّا يلزم المستهلك والمولِّد الاتّفاق
عليه؛ خفّفناه بثابت مسمّى واحد في `sir_constants.h` وحارس `static_assert` للتفرّد.

# الاختبارات

(‏`tests/system/lowlevel_freestanding/test_bounds_diag_sovereign.py`)
- `test_freestanding_bounds_fail_no_english_diagnostic`: الحدّ يمرّر `@__sad_panic(i64 1)`.
- `test_freestanding_null_assert_distinct_code_no_arabic_line`: التأكيد يمرّر
`@__sad_panic(i64 2)` وبلا `na.fmt`/`RUN056`.
- `test_hosted_null_assert_keeps_arabic_diagnostic`: مستضاف ⇒ `na.fmt` + `exit`.
- `test_panic_reason_codes_are_distinct`: 1 (حدّ) ≠ 2 (تأكيد)، لا خلط.
- `test_freestanding_user_assert_check_violation_no_english`: مسار `تأكد`
(sec.fail) حرًّا ⇒ `@__sad_panic(i64 1)` بلا `exit` (يحرس بقاء مواقع الانتهاك
غير-الحدّ على رمز 1).
- `test_hosted_user_assert_uses_abort`: مستضاف ⇒ `abort` بلا `__sad_panic`.
- المجموع: 65 اختبار وضع حرّ خضراء، `gen --check` أخضر.

# الأثر على مصدر الحقيقة

الثوابت تُضاف إلى `sir_constants.h` (مصدر ثوابت المولِّد). لا تغيير في نحو اللغة
ولا كتالوج المفردات ولا LSP — عقد ABI خلفيّ للوضع الحرّ. المستهلك (النواة) يوثّق
الخريطة عنده (رموز.ص).

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

- **`errno`/رموز خروج POSIX:** سابقة راسخة لتصنيف الفشل برمز عدديّ صغير مستقرّ عبر
حدّ ABI، يُخرِّطه المستهلك إلى رسالة بلغته — النمط نفسه هنا.
- **`__stack_chk_fail`/`abort` في libc:** دوالّ هلع بلا معامل تفرّق الأسباب؛ يتجاوزها
هذا المقترح بمعامل سبب واحد يبقي التوقيع البسيط `(i64)`.
- **مقترح كبت التشخيص الإنجليزيّ للوضع الحرّ (s-programming-language#243):** أرسى مبدأ
«اللافتة السياديّة هي التشخيص الوحيد» الذي يمدّده هذا المقترح لمسار التأكيد.
- **هجرة `__sad_panic`/`__stack_chk_fail`/`__stack_chk_guard` إلى ص (أخ.3/أخ.4، #238/#239):**
الأساس الذي يجعل النواة تملك تعريف مسار الهلع فتستطيع تخريط رمز السبب.

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

- هل يُفصَل مدمجا `تأكد`/`ذعر` (يشتركان اليوم في `1`) برمزَي سبب مميّزين لاحقًا؟
يتطلّب توسيع العقد (قيم 3+) ومقترحًا لاحقًا.
- المسار الكامن `emitBuiltinAssert` (لا مُنتِج له في الواجهة اليوم): هل يُغطّى
باختبار على مستوى SIR مباشرةً بدل الاعتماد على مسار أماميّ غائب؟
- هل تُوحَّد خريطة رمز السبب بين المستهلكين (نواة النحلة + أيّ مستهلك مستقبليّ)
في جدول مشترك، أم يبقى كلّ مستهلك حرًّا في تخريطه؟

# أعمال مستقبلية (Future work)

- توسيع الكتالوج بقيم سبب بنيويّة أدقّ (حدّ مصفوفة/وسم تعداد/إجهاض منفصلة) عند
الحاجة — القيم 3+ متاحة دون كسر المستهلكين الحاليّين.
- تمرير سياق إضافيّ اختياريّ (فهرس/طول) عبر توقيع موسَّع منفصل لا يكسر `(i64)`.
- اختبار تغطية مباشر لمسار `emitBuiltinAssert` الكامن (انظر الأسئلة غير المحسومة).
Loading