تخطَّ إلى المحتوى

الذاكرة في ميم

باختصار: الذاكرة في ميم يدوية، قريبة من نموذج Zig. لا عدّ مراجع ولا جامع قمامة (حُذف عدّ المراجع في 0.7.0). تُحجز الذاكرة من مخصص، وتعيدها أنت بـ حرر، أو دفعة واحدة بـساحة، وخاتمه تؤجّل الإعادة إلى الخروج من الكتلة. وما لا تعيده يعود إلى النظام عند خروج البرنامج.

برنامجكالمخصص الافتراضيكتلة كتلة: حرر(س)ساحةكلها دفعة: اعد(ساحه)ما لا تعيده يبقى حتى خروج البرنامج
كل حجز من مخصص: الافتراضي تعيد منه كتلة كتلة، والساحة تعيد كل ما فيها دفعة.
  1. المخصص. كل نص تبنيه وكل قائمة وقاموس يُحجز من مخصص. والمدمجات التي تبني شيئاً تأخذه وسيطاً أخيراً، فإن تركته فمن الافتراضي. ومن المخصصات المدمجة: النظام، والافتراضي، وساحة، وكاشف، ومخزن_ثابت. وبلا_افتراضي في أول الوحدة يمنع الحجز من الافتراضي فيها.
  2. حرر(س) تعيد ما حُجز لـ س فوراً، وتجعل س لاشيء. ولا تتبع ما في داخله: تحرير قائمة قوائم يترك الداخلية.
  3. خاتمه جملة تؤجّل الجملة إلى الخروج من الكتلة، عند كل مخرج: آخر السطر، أو ارجع مبكرة، أو جرّب فاشلة. وتُنفَّذ بعكس ترتيب كتابتها:
خاتمه عند كل مخرج، بعكس الترتيب
داله عالج(ن عدد) نص:
اطبع("فتح المورد ", ن)
خاتمه اطبع("إغلاق المورد ", ن)
خاتمه اطبع("تنظيف أول")
اذا ن < 0:
ارجع "سالب"
اطبع("عمل على ", ن)
ارجع "تم"
اطبع(عالج(5))
اطبع("---")
اطبع(عالج(-1))
مخرجات مسجّلة من المجمّعmeem ذاكرة_خاتمه.م · meem 0.10.0+b01b55f
فتح المورد 5عمل على 5تنظيف أولإغلاق المورد 5تم---فتح المورد -1تنظيف أولإغلاق المورد -1سالب
  1. الساحة تجمع ما يُحجز منها، واعد تعيده كله دفعة. تناسب مرحلة تبني فيها كثيراً ثم تنتهي منه كله:
ساحة لكل دورة
مجموع = 0
لكل دورة في مدى(0, 3):
ساحه = ساحة(الافتراضي)
خاتمه اعد(ساحه)
كلمات = تقسيم(دمج_نصوص("ا ب ج ", دورة, ساحه), " ", ساحه)
مجموع += طول(كلمات)
اطبع("كلمات في الدورات الثلاث: ", مجموع)
مخرجات مسجّلة من المجمّعmeem 16_ساحة.م · meem 0.10.0+b01b55f
كلمات في الدورات الثلاث: 12
  1. الكاشف مخصص يراقب ما يُحجز ويُحرَّر. يعمل افتراضياً في التشغيل المباشر (meem برنامج.م) منذ 0.10.0، و--debug-mem يضيف إليه تقريراً في آخر البرنامج بكل سطر حجز ولم يحرّر:
تسرب يكشفه --debug-mem بالسطر
لكل ع في مدى(0, 3):
ن = "سطر " + نص(ع)
اطبع(ن)
مخرجات مسجّلة من المجمّعmeem --debug-mem 16_تسرب.م · meem 0.10.0+b01b55f
سطر 0سطر 1سطر 2
[ذاكرة] معلومة: كتل لم تُحرَّر من الافتراضي: 3 (75 بايت)، تعود للنظام عند الخروج  سطر 2: 3 كتل، 75 بايت  تلميح: الحجز المتكرر في سطر واحد (حلقة في الغالب) يُعاد بـ خاتمه حرر(...) بعد إنشائه، أو بساحة للمرحلة
التشغيل المباشر meem برنامج.م الملف المبني meem build
الافتراضي بالكاشف، بلا تقرير عند النهاية بلا كاشف
الخيار المقابل --release: بلا كاشف --debug أو --debug-mem: بالكاشف
التقرير بما لم يُحرَّر مع --debug-mem مع --debug-mem

فالتطوير بالتشغيل المباشر محميّ، والملف المبني سريع، كوضعي Debug وReleaseFast في Zig. وللكاشف كلفة: على برامج القياس في مستودع المجمّع كان أبطأ من 0% إلى 32%، وما يُحرَّر في وضعه لا يُعاد إلى النظام (يُعزل ليُكشف استعماله بعد التحرير)، فبرنامج يحرّر كثيراً ويطول عمله يُشغَّل بـ --release.

ما يضمنه المجمّع في كل الأوضاع

رابط إلى قسم «ما يضمنه المجمّع في كل الأوضاع»

خارج خطر وبلا_فحص، وبالكاشف أو بدونه:

الحساب والفهرسة. تجاوز حدود 64 بت، والفهرس خارج القائمة أو النص، والقسمة على صفر، وفك لاشيء، كلها أخطاء تشغيل منظّمة برمز 3 ومعرّف وسطر، لا سلوك غير معرَّف:

فهرس خارج الحدود
ق = [10, 20, 30]
اطبع(ق[2])
اطبع(ق[3])
مخرجات مسجّلة من المجمّعmeem ذاكرة_فهرس.م · meem 0.10.0+b01b55f
30
[خطأ تشغيل E0321] سطر 3:7 - الفهرس 3 خارج الحدود (الحجم 3)  اطبع(ق[3])

رمز الخروج: 3

في فهرس الأخطاء: E0321

تجاوز حدود 64 بت
كبير = 9223372036854775807
اطبع(كبير)
اطبع(كبير + 1)
مخرجات مسجّلة من المجمّعmeem ذاكرة_تجاوز.م · meem 0.10.0+b01b55f
9223372036854775807
[خطأ تشغيل E0341] سطر 3:11 - تجاوز العدد الصحيح حدود 64 بت في العملية '+' (للالتفاف بدل الخطأ شغّل مع --wrap-overflow)  اطبع(كبير + 1)

رمز الخروج: 3

في فهرس الأخطاء: E0341

قائمة أو قاموس بالاسم نفسه بعد حرر. حرر(ق) تجعل ق لاشيء، واستعمالها بعده خطأ E0428، في التشغيل المباشر وفي الملف المبني كليهما (كان في 0.9.1 سقوطاً بإشارة SIGSEGV):

استعمال القائمة بعد تحريرها بالاسم نفسه
ق = [1, 2, 3]
حرر(ق)
اطبع(طول(ق))
مخرجات مسجّلة من المجمّعmeem ذاكرة_نفس_الاسم.م · meem 0.10.0+b01b55f
[خطأ تشغيل E0428] سطر 3:10 - الحاوية 'ق' استُعملت بعد تحريرها (قيمتها لاشيء)  اطبع(طول(ق))

رمز الخروج: 3

في فهرس الأخطاء: E0428

بُني أيضاً بـ meem build عند بناء الموقع: ملف ساكن حجمه 37.2 ك.ب، شُغّل وحده وطابق مخرجه المخرج أعلاه.

لا حجز لم تكتبه. لا يحجز البرنامج إلا ما تراه في الشيفرة: مدمجة تأخذ مخصصاً (مكتوباً أو متروكاً للافتراضي)، أو + على النصوص، أو قيمة حرفية [...] و{...}. والعمليات على «العرض» (ناتج جزء وقص_الفراغات ومسارات.الامتداد…) لا تنسخ: طول والمقارنة والفهرسة ولكل وعدد() والمفتاح في قاموس. هذه حلقة من ألف دورة بـ --debug-mem، ولا تقرير في آخرها لأن لا شيء بقي:

العمليات على العرض لا تحجز
جملة = " ميم لغة عربية "
مجموع = 0
لكل ع في مدى(0, 1000):
ك = قص_الفراغات(جملة)
مجموع += طول(ك)
اذا ك == "ميم لغة عربية":
مجموع += 1
اطبع(مجموع)
مخرجات مسجّلة من المجمّعmeem --debug-mem ذاكرة_لا_نسخ.م · meem 0.10.0+b01b55f
14000

والاستثناء الوحيد: نمو ن += ذيل (انظر «ما لا يضمنه» أدناه).

حين يمرّ الخطأ عبر اسم آخر لا يعرفه المجمّع وقت الترجمة، فيكشفه الكاشف وقت التشغيل، برسالة فيها سطر الإنشاء وسطر التحرير. وهذه الأمثلة كلها بالتشغيل المباشر الافتراضي، بلا أي خيار:

قائمة يحملها اسمان، حُرّرت بأحدهما واستُعملت بالآخر (E0429):

استعمال قائمة بعد التحرير عبر اسم آخر
ا = [7, 8, 9]
ب = ا
حرر(ا)
ج = [1, 2, 3, 4, 5, 6]
اطبع(ب[0], " ", طول(ب))
حرر(ج)
مخرجات مسجّلة من المجمّعmeem ذاكرة_بعد_التحرير.م · meem 0.10.0+b01b55f
[خطأ تشغيل E0429] سطر 5:7 - استعمال القائمة أو القاموس بعد التحرير (أُنشئت في السطر 1 وحُرّرت في السطر 3)  اطبع(ب[0], " ", طول(ب))

رمز الخروج: 3

في فهرس الأخطاء: E0429

قائمة من ساحة استُعملت بعد اعد لساحتها (E0429 أيضاً):

ساحة بعد اعد
ساحه = ساحة(الافتراضي)
ق = قائمة_من([1, 2, 3], ساحه)
اعد(ساحه)
اطبع(ق[0])
مخرجات مسجّلة من المجمّعmeem ذاكرة_ساحة_بعد_اعد.م · meem 0.10.0+b01b55f
[خطأ تشغيل E0429] سطر 4:7 - استعمال القائمة أو القاموس بعد التحرير (أُنشئت في السطر 2 وحُرّرت في السطر 3)  اطبع(ق[0])

رمز الخروج: 3

في فهرس الأخطاء: E0429

عرض على نص حُرّر أصله (E0430):

عرض معلّق
مسار = "ملفات/تقرير.md"
ن = مسار + ""
امتداد = جزء(ن, 10)
حرر(ن)
اطبع(امتداد)
مخرجات مسجّلة من المجمّعmeem ذاكرة_عرض_معلق.م · meem 0.10.0+b01b55f
[خطأ تشغيل E0430] سطر 5:1 - استعمال النص بعد التحرير (أُنشئت في السطر 2 وحُرّرت في السطر 4)  اطبع(امتداد)

رمز الخروج: 3

في فهرس الأخطاء: E0430

ونص حُرّر مرتين عبر اسمين (E0431). والتحرير المزدوج للحاوية E0350، وللخانة والكتلة E0421:

تحرير مزدوج عبر اسم آخر
ن = "مرحبا " + نص(1)
م = ن
حرر(ن)
حرر(م)
مخرجات مسجّلة من المجمّعmeem ذاكرة_تحرير_مزدوج.م · meem 0.10.0+b01b55f
[خطأ تشغيل E0431] سطر 4:1 - تحرير مزدوج: النص حُرّر من قبل (عبر اسم آخر يحمله)  حرر(م)

رمز الخروج: 3

في فهرس الأخطاء: E0431

والذاكرة المحرَّرة في وضع الكشف تُملأ بالبايت 0xDF، فقراءة لم يفحصها الكاشف ترى نفايات ظاهرة لا البيانات القديمة سليمة.

  • الملف المبني بلا كاشف. الأمثلة الأربعة السابقة في ملف بُني بـ meem build بلا --debug سلوك غير معرَّف: الاستعمال بعد التحرير عبر اسم آخر قد يطبع ناتجاً قديماً أو نفايات، والتحرير المزدوج عبر اسم آخر يُسقط البرنامج. لذلك لا ننشر ناتجها هناك. جرّب برنامجك بالتشغيل المباشر أو ابنه بـ --debug قبل أن تبنيه للإصدار.
  • ما لم يُنفَّذ لا يُكشف. الكاشف يعمل وقت التشغيل، والمجمّع لا يتتبع الملكية ولا الأسماء المستعارة. فرع لم يمرّ به الاختبار لا يُفحص.
  • حرر لا يتبع ما في الداخل. تحرير قائمة قوائم، أو هيكل فيه قوائم، أو قائمة نصوص من تقسيم، لا يحرر ما فيها. للبنى المتداخلة الساحة، أو تحرير عميق تكتبه.
  • نمو += يترك المخزن القديم. تسرب محدود: نحو لوغاريتم الطول للأساس 2 من المخازن، مجموعها نحو ضعفي الطول النهائي (الحجز والأداء في المدمجات).
  • داخل خطر: المؤشرات الخام وبلا_فحص وحوّل وذاكرة C على كاتبها، والكاشف لا يرى ذاكرة C.
  • الخيوط: لا خيوط في اللغة، والمخصصات غير ذرّية.
  • أخطاء التشغيل لا تنفّذ خاتمه. خطأ التشغيل (رمز 3) ينهي البرنامج فوراً، كـ panic في Zig: الذاكرة يستعيدها النظام، أما ملف مؤقت تحذفه خاتمه فيبقى على القرص. الخطأ المتوقع يُعاد بـ ارجع خطأ.اسم فتُنفَّذ الخاتمات.

الدرس 17: المخصصات والساحات · مرجع الذاكرة · ما هو خطر؟ · ميم مقابل C وZig