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

العدّ المرجعي (تاريخي: 0.6 وما قبله)

المصدر: docs/memory.md في مستودع المجمّع (الجزء الثاني). ما لم يُقس مكتوب أمامه غير مقيس، كما في الوثيقة.

العدّاد i64 قبل القيمة بثمانية بايتات (وللنص طوله قبله بثمانية أخرى). الهيكل والمصفوفة بلا رأس.

كل تعبير يعطي قيمة مملوكة (مرجع جديد على من يأخذه أن يخزّنه أو يتخلى عنه) أو مستعارة (مرجع يملكه غيره):

الصنف التعابير الناتج
قيمة الأعداد، الكسور، الرموز، المنطقي، لاشيء، العامل الأحادي لا قيمة مُدارة
ثابت النص الحرفي مستعار من ثابت خالد
موضع متغير، ق[ف]، س.حقل مستعار من موضعه
حرفي [...]، {...}، مصفوفة حرفية مملوك جديد (المصفوفة بالقيمة)
عامل العامل الثنائي + على نصين مملوك جديد؛ غيره بلا قيمة مُدارة
إنشاء هيكل نقطة(1, 2) بالقيمة؛ حقوله تأخذ مراجعها عند التخزين
استدعاء ف(...) دالة المستخدم: مملوك. المدمجة: بحسب تصريحها

التخزين في موضع يأخذ مرجعاً للجديد ثم يتخلى عن القديم، بهذا الترتيب (فيصح س = س). المؤقتات المملوكة التي لم تُخزَّن يُتخلى عنها عند نهاية الجملة.

النص الحرفي ثابت في البرنامج برأس كامل وعدّاد قيمته 2^62: الزيادة والنقصان عليه يجريان كغيره ولا يبلغ الصفر أبداً. لا يُعدَّل في مكانه (الإلحاق به ينسخ أولاً).

  • معاملات الدوال مستعارة: المستدعي يمسك القيمة طوال الاستدعاء، فالدالة لا تزيد ولا تنقص، إلا إن أسندت إلى المعامل نفسه.
  • القراءة من متغير محلي لا يراه غير دالته لا تأخذ مرجعاً.
  • قيمة مستعارة من موضع غير محلي (عام، عنصر حاوية، حقل)، ثم استدعاء قد يزيلها من ذلك الموضع قبل أن تُستعمل: تُمسك بمرجع حتى نهاية الجملة.

ن = ن + ذيل ون += ذيل لمتغير نصي يكتبان الذيل في آخر كتلة النص نفسها حين: العدّاد 1 (لا يمسكه غير المتغير)، والنص ليس حرفياً، ولم يُمرَّر إلى C، وفي الكتلة متسع (أو تُكبَّر). وإلا يُبنى نص جديد. الناتج واحد في الحالين.

عشرون ألف إلحاق ثم إلحاق بعد مشاركة:

2_الحاق.م
# الإلحاق في المكان: «ن += ذيل» يكتب في آخر النص نفسه إن لم يمسكه أحد غير المتغير،
# فلا يُنشأ نص جديد في كل دورة. شغّله: MEEM_RC_REPORT=1 meem 2_الحاق.م --debug-mem
ن = "" + نص(0) # نص جديد يملكه المتغير وحده (النص الحرفي لا يُعدَّل)
لكل ع في مدى(0, 20000):
ن += "ا" # عشرون ألف إلحاق في النص نفسه
اطبع(طول(ن))
# حين يمسك النصَّ اسمٌ آخر لا يُمسّ: يُنسخ مرة، ثم يعود الإلحاق في المكان
صورة = ن
ن += "!"
اطبع(طول(صورة), " ", طول(ن))
مخرجات مسجّلة من المجمّعmeem --debug-mem 2_الحاق.م · meem 0.6.0+d882040 · مسجَّل بإصدار أقدم، لا يُعاد تشغيله (صفحة تاريخية)
2000120001 20002
[ذاكرة] كل القيم المُدارة حُرّرت (عددها 3).

ثلاثة نصوص في البرنامج كله، لا عشرون ألفاً: النص الأول، ونص نص(0) المؤقت، والنسخة التي لزمت حين أمسك صورة النصَّ نفسه.

قائمة بلغ عدّادها الصفر تتخلى عن عناصرها، وقد يبلغ بعضها الصفر فيتخلى عن عناصره. هذا لا يجري بالعودية: الحاويات التي بلغت الصفر توضع في قائمة عمل وتُعاد واحدة واحدة. كلفة تحرير بنية كبيرة دفعة واحدة تتناسب مع حجمها وتقع في لحظة تركها: غير مقيس كتوقف (لا قياس لأطول توقف).

تنشأ في شيفرة آمنة بلا مؤشرات. الهيكل بالقيمة فلا يشير إلى نفسه، لكن القائمة والقاموس مرجعان:

دورة.م
هيكل عقدة:
اسم نص
جيران قائمة[عقدة]
داله اصنع_دورة() عدد:
ا قائمة[عقدة] = []
ب قائمة[عقدة] = []
اضف(ا, عقدة("ا" + نص(1), ب)) # ا يمسك ب
اضف(ب, عقدة("ب" + نص(2), ا)) # ب يمسك ا: دورة
ارجع طول(ا) + طول(ب)
اطبع(اصنع_دورة())
مخرجات مسجّلة من المجمّعmeem --debug-mem دورة.م · meem 0.6.0+d882040 · مسجَّل بإصدار أقدم، لا يُعاد تشغيله (صفحة تاريخية)
2
[ذاكرة] قيم مُدارة لم تُحرَّر: 4 من 6 (نصوص 2، قوائم 2، قواميس 0)  سطر 9: نص × 1  سطر 8: نص × 1  سطر 7: قائمة × 1  سطر 6: قائمة × 1

ما يحدث: انتهت الدالة وترك المتغيران القائمتين، وعدّاد كلٍّ منهما بقي 1 (تمسكها الأخرى). لا خطأ ولا انهيار؛ الذاكرة لا تعود حتى ينتهي البرنامج. بحسب وثيقة المجمّع: في حلقة تنشئ 200 ألف دورة صغيرة بلغت ذروة ذاكرة البرنامج 122 م.ب.

لا جامع دورات في اللغة ولا مراجع ضعيفة. الحل اليوم: اكسر الدورة قبل ترك البنية (أفرغ إحدى القائمتين)، أو مثّل العلاقة بأرقام (فهارس في قائمة واحدة).

  • نص يُمرَّر إلى C يُعطى مؤشر بايتاته نفسها (لا نسخة). يُعلَّم النص بعدها «مرّ إلى C»، فلا يُلحق به في مكانه أبداً.
  • C تحتفظ بالمؤشر بعد رجوع الدالة: ميم لا تعرف، وستحرر النص حين يتركه آخر من يمسكه في ميم. إبقاء النص حياً (في متغير عام مثلاً) مسؤولية كاتب التصريح. لا آلية «تثبيت» في اللغة.
  • نص ترجعه C (نص): يُنسخ إلى نص للغة برأسه؛ الأصل يبقى لـ C. ونص_مملوك: يُنسخ ثم يُعاد الأصل بـ free. المؤشر الفارغ يصير لاشيء.
  • مؤشر_خام: يمرّ كما هو في الاتجاهين، بلا عدّ ولا نسخ.
  • القوائم والقواميس والهياكل لا تُمرَّر إلى C.

التفصيل في استدعاء C.

  • لا خيوط في اللغة: لا صيغة ولا دالة تنشئ خيطاً، وخارجي لا يمرّر دالة من ميم إلى C (لا دوال راجعة)، فمكتبة C لا تستطيع استدعاء شيفرة ميم من خيط آخر.
  • العدّاد غير ذرّي: زيادة ونقصان عاديان على i64. آمن ما دامت شيفرة ميم تعمل في خيط واحد، وهو الحال دائماً.
  • مكتبة C تنشئ خيوطاً داخلها: خيوطها لا تمسّ عدّادات ميم ولا تستدعي شيفرتها. الخطر الوحيد أن يقرأ خيط من المكتبة نصاً أعطيته لها بعد أن حررته ميم. غير مجرَّب مع مكتبة حقيقية تنشئ خيوطاً.
  • إضافة خيوط للغة لاحقاً تلزمها عدّادات ذرّية (أو قيم لا تُشارَك بين الخيوط) وكلفتها: غير مقيس.

قياس كلفة العدّ في الأداء.