Skip to content

لماذا يجبُ أن يكونَ المعالجُ اسمًا حرفيًّا

كلُّ صفحاتِ هذا المجالِ تُمرِّرُ المعالِجَ اسمًا حرفيًّا في موضعِ نداءِ المدمَجة. وهذه الصفحةُ تشرحُ لماذا، وأينَ ينتهي القيدُ بالضبط — لا كيفَ تكتُب.

القاعدة

معالِجُ المسارِ يجبُ أن يصلَ إلى مدمَجةِ التسجيلِ حرفيًّا في موضعِ ندائها نفسِه. والقيدُ قيدُ موضعٍ، لا قيدُ معرفةٍ بالقيمة.

وهي قاعدةٌ مُعلَنةٌ برمزَينِ في language-truth/errors/semantic.yaml: SEM049 للمعالِجِ غيرِ الحرفيّ، وSEM051 للمعالِجِ المُصرَّحِ بمعاملات.

البرهان: ثلاثةُ برامجَ رُفِضَت

① معالِجٌ في متغيّر

sad
متغير المعالج = "معالج_الجذر"
عند_طلب_جلب(الخادم، "/"، المعالج)
error: [SEM049] (AR) معالجُ المسار في 'sad_http_server_get_cb' يجب أن يكون اسمَ دالّةٍ معرَّفةٍ حرفيًّا؛ وردَ '%المعالج'
  → مرِّرِ اسمَ دالّةٍ معرَّفةٍ في هذا الملفّ مباشرةً (لا متغيّرًا ولا معاملًا). والمعالجُ غيرُ المباشرِ غيرُ مخفَّضٍ بعدُ: يلزمُه ترامبولينُ وقتِ تشغيلٍ يعرفُ اتّفاقيّةَ المُغلَقات.
1 error(s) generated.

القيمةُ ههنا معلومةٌ لأيِّ قارئ: سطرٌ واحدٌ فوقَها. ومع ذلك تُرفَض. وهذا أضيقُ صورةٍ للقاعدة، وهي التي تُبيِّنُ أنّ الشرطَ شرطُ موضعٍ لا شرطُ علم.

② معالِجٌ يمرُّ عبرَ دالّةٍ حرّة

sad
دالة سجل(الخادم، المسار، المعالج)
    عند_طلب_جلب(الخادم، المسار، المعالج)
نهاية

سجل(خ، "/"، "معالج_الجذر")

الاسمُ حرفيٌّ في موضعِ نداءِ سجل… ولا يُغني:

error: [SEM049] (AR) معالجُ المسار في 'sad_http_server_get_cb' يجب أن يكون اسمَ دالّةٍ معرَّفةٍ حرفيًّا؛ وردَ '%المعالج'

🔑 وهذا هو الشاهدُ الحاسم: الحرفيّةُ تُقاسُ عند مدمَجةِ التسجيل، لا عندَ سطرِك. فالغلافُ لا يُنجّي، ولا فرقَ بين طريقةِ صنفٍ ودالّةٍ حرّة.

③ معالِجٌ بمعاملات

sad
دالة معالج_الجذر(الطلب، الرد)
    عين_نص_الرد("مرحبًا")
نهاية

عند_طلب_جلب(الخادم، "/"، "معالج_الجذر")
error: [SEM051] (AR) معالجُ المسار 'معالج_الجذر' في 'sad_http_server_get_cb' يأخذُ 2 معاملًا، ومعالجُ المسارِ لا يأخذُ شيئًا
  → اجعلْ توقيعَ المعالجِ خاليًا من المعاملات. فالطلبُ والردُّ يُثبَّتانِ في وقتِ التشغيلِ قبلَ ندائِه ويُقرآنِ من داخلِ جسمِه، فلا يُمرَّرانِ وسيطَين.

لماذا القاعدةُ ما هي عليه

تسجيلُ المسارِ لا يُمرِّرُ عنوانَ دالّةِ ص خامًّا إلى طبقةِ C. بل يبني ثانكًا توقيعُه void() يُنادي معالِجَك بنوعِه الحقيقيّ، ويُسلِّمُ عنوانَ الثانكِ وحدَه.

وسببُ ذلك مُدوَّنٌ في الكتالوجِ نفسِه: عائدُ دالّةِ ص قد يكون SadDyn بستّةَ عشرَ بايتًا، فيخفضُه Win64 إلى مؤشّرِ sret خفيٍّ في السجلِّ الأوّل؛ فلو سُلِّمَ العنوانُ خامًّا لكتبتِ الدالّةُ عائدَها عبرَ سجلٍّ مهمَل ⇒ فسادُ ذاكرةٍ يقتلُ العمليّةَ بعدَ إرسالِ الرد — وذلك مقيسٌ لا مُتوقَّع.

ومن ههنا تتبيّنُ القاعدتانِ معًا:

القيدلأنّ الثانكَ…
اسمٌ حرفيٌّ (SEM049)يُبنى وقتَ التوليد، فيلزمُه أن يعرفَ الدالّةَ حينئذٍ. وقيمةٌ في سجلٍّ وقتَ التشغيلِ تصلُ بعدَ فواتِ الأوان
بلا معاملات (SEM051)عقدُه void()، ولا يستطيعُ اختراعَ قيمٍ لمعاملاتٍ لا مصدرَ لها

ما الذي يفتحُه رفعُ القيد

ترامبولينُ وقتِ تشغيلٍ يعرفُ اتّفاقيّةَ المُغلَقات — كما يقولُ تلميحُ SEM049 حرفيًّا. وهو مشروعٌ قائمٌ بذاتِه لا سطرٌ يُضاف: بها وحدَها يصيرُ المعالِجُ قيمةً تُحمَلُ في متغيّرٍ ومعاملٍ ولامدا.

ما زالَ هذا القيدُ يُكلِّفُ سطحَ اللغةِ ثمنًا مدفوعًا

كانت شبكات.ص تُعرِّفُ أربعةَ أغلفةٍ (عند_جلب · عند_إرسال · عند_استبدال · عند_حذف) تُمرِّرُ المعالِجَ معاملًا. واستيرادُ الوحدةِ يُخفِضُ دوالَّها كلَّها، فكانَ استورد شبكات وحدَه يُنتِجُ أربعةَ تشخيصاتٍ ويُسقِطُ كلَّ مستورِدٍ ولو لم يمسَّ HTTP. فحُذفتِ الأربعةُ — وذلك أصدقُ من غلافٍ لا يمكنُ أن يعمل.

القاعدةُ مُحاكَمة، لا مُعلَنةً فحسب

في المستودعِ بذرةٌ واحدةٌ تمسُّ SEM049: tests/behavior/…/05_شبكة/050_route_handler_not_literal.ص، وهي تُمرِّرُ المعالِجَ متغيّرًا وتُوكِّدُ الرفض. وقبلَها لم تكن في الشجرةِ كلِّها بذرةٌ تمسُّ هذا الرمز — فكان رمزًا يُبعَثُ ولا يُحاكَم.

ملحوظةٌ للقارئِ الذي يفتحُ تلك البذرة

تعليقُها يقولُ إنّ التوجيهَ بلا نمطٍ لأنّ الرسالةَ المعروضةَ لا تحملُ رمزَها. والمقيسُ اليومَ خلافُ ذلك: المخرَجاتُ الثلاثةُ أعلاه كلُّها تبدأُ بـerror: [SEM049] و[SEM051]. فالعطبُ الذي وُصِفَ هناك قد سُدَّ، والتوكيدُ على الرمزِ صارَ ممكنًا.

حدودٌ متّصلةٌ بهذه القاعدة

  • فضاءُ SadNet ٢٢ مدخلًا وكلُّها مؤجَّلة — إعلانٌ لا قدرة.
  • لا تنفيذَ لشفرةِ ص في المتصفّح: مسارُ WebAssembly كان يمرُّ بالمفسّرِ المحذوف.
  • وبقيّةُ الحدودِ في حدودِ الويبِ المُعلَنة.

مُرخَّص بموجب رخصة MIT