دليل المكتبات التنفيذية
دليل مكتبة التنفيذ المعيارية (Srl)
دليل مكتبة `مغلفة` (closure)
دليل مكتبة `بـناء` (Build)
دليل مكتبة `ضـغط` (Zip)
دليل مدير الحزم
دليل الوحدة `الـقلب` (Core)
دليل الوحدة `نـبم` (Spp)
معالجة شجرة البنية المجردة

دليل مكتبة التنفيذ المعيارية (Srl)


مكتبة التنفيذ المعيارية تتكون من وحدة واحدة اسمها `مـتم` (Srl) وتحتوي هذه الوحدة على الوحدات والأصناف التالية:

الصنف: مـصفوفة (Array)

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

دالة هات_مصفوفة (): مـصفوفة[صـحيح] {
  عرف ن: مـصفوفة[صـحيح]؛
  ن.أضف(0)؛
  ارجع ن؛ // لا يتم هنا إعادة حجز الذاكرة أو نسخها
}

دالة اطبع_مصفوفة (ن: مـصفوفة[صـحيح]) {
  عرف ع: صـحيح؛
  لكل ع = 0، ع < ن.هات_الطول()، ++ع طـرفية.اطبع("%d\ج"، ن(ع))؛
}
func main {
  def a: Array[Int] = getArray();
  a.add(1); // Here the allocated memory block is expanded.
  def a2: Array[Int] = a; // No new memory block is allocated here.
  a.add(2); // Now a new copy of the buffer is created so a2 is not affected.
  printArray(a); // No new memory block is created or copied here.
  // Now the memory blocks of a and a2 are freed.
}

func getArray(): Array[Int] {
  def a: Array[Int];
  a.add(0);
  return a; // No new memory block is allcoated here and memory copy happens.
}

func printArray (a: Array[Int]) {
  def i: Int;
  for i = 0, i < a.getLength(), ++i Console.print("%d\n", a(i));
}
يحتوي الصنف `مـصفوفة` على الدالات التالية:
  • التهيئة
      عملية هذا~هيئ(سند[مـصفوفة[صـنف_المحتوى]])؛
      عملية هذا_هيئ(عدد_العناصر: صـحيح، العناصر: ...صـنف_المحتوى)؛
    
      handler this~init(ref[Array[ContentType]]);
      handler this~init(count: Int, args: ...ContentType);
    
    الصيغة الأولى تهيئ المصفوفة من مصفوفة أخرى. ستستخدم المصفوفة الجديدة نفس المحتوى الذي في المصفوفة المعطاة ولن يتم نسخ المحتوى حتى تغير إحدى المصفوفتي المحتوى، وعندها ينسخ المحتوى قبل التغيير لضمان عدم تأثر المصفوفة الأخرى.
    الصيغة الثانية تهيئ المصفوفة من العناصر المعطاة كما في المثال التالي:
    عرف م1: مـصوفة[صحيح]({ 5، 2، 1 })؛ // ستحتوي المصفوفة على 3 عناصر: 5، 2، 1.
    عرف م2: مـصفوفة[صحيح](3، 5، 2، 1)؛ // ستحتوي المصفوفة على 3 عناصر: 5، 2، 1.
    
    def a1: Array[Int]({ 5, 2, 1 }); // Array will contain 3 elements: 5, 2, and 1.
    def a2: Array[Int](3, 5, 2, 1); // Array will contain 3 elements: 5, 2, and 1.
    
  • هات_الطول (getLength)
    عملية هذا.هات_الطول (): صـحيح_متكيف؛
    
    handler this.getLength (): ArchInt;
    
    ترجع عدد العناصر في المصفوفة.
  • هات_حجم_الصوان (getBufSize)
    عملية هذا.هات_حجم_الصوان (): صـحيح_متكيف؛
    
    handler this.getBufSize (): ArchInt;
    
    ترجع عدد العناصر التي تتسع لها الذاكرة المحجوزة حاليًا. عند تجاوز هذا الحجم يقوم الكائن تلقائيا بتوسيع حجز الذاكرة.
  • عيّن (assign)
    عملية هذا.عين (م: سند[مـصفوفة[صـنف_المحتوى]])؛
    
    handler this.assign (a: ref[Array[ContentType]]);
    
    تعيين محتوى جديد للمصفوفة من مصفوفة أخرى. هذه الدالة لا تنسخ المحتوى من المصفوفة الأخرى وإنما تتشارك معها بنفس الصوان لحين حاجة إحدى المصفوفتين لتغيير المحتوى، حينها تنسخ تلك المصفوفة الصوان وتنتهي المشاركة.
  • أضف (add)
    عملية هذا.أضف (م: صـنف_المحتوى)؛
    عملية هذا.أضف (عدد_العناصر: صـحيح، العناصر: ...صـنف_المحتوى)؛
    عملية هذا.أضف (م: مـصفوفة[صـنف_المحتوى])؛
    
    handler this.add (e: ContentType);
    handler this.add (argCount: Int, args: ...ContentType);
    handler this.add (e: Array[ContentType]);
    
    الصيغة الأولى تضيف عنصرا إلى المصفوفة بعد توسيع حجز الذاكرة إن وجب. إذا كان المحتوى مشارك مع مصفوفة أخرى تقوم الدالة بنسخ المحتوى إلى صوان جديد.
    الصيغة الثانية تضيف عدة عناصر مرة واحدة بدل أن تضيف عنصرا واحدًا.
    الصيغة الثالثة تضيف مصفوفة إلى المصفوفة الحالية، أي تضيف كل عناصر المصفوفة المعطاة إلى المصفوفة الحالية. المصفوفة المعطاة لن تتأثر بهذا الاستدعاء.
    م.أضف({ 5، 2، 1 })؛ // تضيف 3 عناصر: 5، 2، 1.
    م.أضف(3، 5، 2، 1)؛ // تضيف 3 عناصر: 5، 2، 1.
    
    a.add({ 5, 2, 1 }); // Adds 3 elements: 5, 2, 1.
    a.add(3, 5, 2, 1); // Adds 3 elements: 5, 2, 1.
    
  • احشر (insert)
    عملية هذا.احشر (موقع: صـحيح_متكيف، عنصر: صـنف_المحتوى)؛
    
    handler this.insert (index: ArchInt, element: ContentType);
    
    إضافة عنصر جديد إلى المصفوفة في الموقع المحدد بعد توسيع حجز الذاكرة إن وجب. إذا كان المحتوى مشارك مع مصفوفة أخرى تقوم الدالة بنسخ المحتوى إلى صوان جديد.
  • أزل (remove)
    عملية هذا.أزل (موقع: صـحيح_متكيف)؛
    
    handler this.remove (index: ArchInt);
    
    إزالة العنصر الذي في الموقع المحدد. إذا كان المحتوى مشارك مع مصفوفة أخرى تقوم الدالة بنسخ المحتوى إلى صوان جديد.
  • اجتزئ (slice)
    عملية هذا.اجتزئ (بداية: صـحيح_متكيف، عدد: صـحيح_متكيف)؛
    
    handler this.slice (start: ArchInt, count: ArchInt);
    
    نسخ جزء من المصفوفة وإرجاعه كمصفوفة جديدة. يبدأ النسخ من العنصر `بداية` ويستمر حتى نسخ `عدد` من العناصر، أو حتى وصول نهاية المصفوفة (إن وصلنا نهاية المصفوفة قبل استيفاء العدد المطلوب).
  • فرّغ (clear)
    عملية هذا.فرّغ ()؛
    
    handler this.clear ();
    
    إزالة جميع العناصر من المصفوفة. إذا كان المحتوى غير مشارَك مع مصفوفة أخرى سيُحرر الصوان.

الصنف: نـص (String)

الصنف `نـص` يسهل التعامل مع سلاسل المحارف فهو يتولى مسؤولية حجز وتحرير الذاكرة الخاصة بسلسلة المحارف مع مراعاة الأداء وتجنب عمليات النسخ وحجز الذاكرة غير الضرورية. يوفر الصنف دالات لتسهيل العمليات المختلفة على سلاسل الحارف. المثال التالي يوضح التعامل مع سلاسل المحارف:
دالة رئيسي {
  عرف نص: نـص = هات_نص()؛
  نص += " والحمد لله"؛ // هنا يتم تمديد حجم الذاكرة المحجوزة
  عرف نص2: نـص = نص؛ // هنا لا يتم إنشاء نسخة جديدة من النص
  نص += "."؛ // الآن يتم إنشاء نسخة جديدة كي لا يتأثر نص2
  اطبع_نص(نص)؛ // لا يتم هنا إعادة حجز الذاكرة أو نسخها
  // الآن يتم تحرير ذاكرة نص ونص2
}

دالة هات_نص (): نـص {
  عرف ن: نـص = "بسم الله"؛
  ارجع ن؛ // لا يتم هنا إعادة حجز الذاكرة أو نسخها
}

دالة اطبع_نص (ن: نـص) {
  طـرفية.اطبع(ن)؛ // يتم هنا التحويل تلقائيا من صنف نـص إلى مؤشر على محارف.
}
func main {
  def str: String = getString();
  str += " world"; // Memory block is expanded here.
  def str2: String = str; // No new memory is allocated here.
  str += "."; // Copy of the string buffer is created so str2 is not affected.
  printStr(str); // No new memory allocation or copy happens here.
  // Now memory blocks of str and str2 are freed.
}

func getString (): String {
  def s: String = "Hello";
  return s; // No new memory allocation or copy happens here.
}

func printStr (s: String) {
  Console.print(s); // s is automatically casted into ptr[array[Char]].
}
يحتوي الصنف `نـص` على المتغيرات والدالات التالية:
  • صوان (buf)
    عرف صوان: مؤشر[مصفوفة[مـحرف]]؛
    
    def buf: ptr[array[Char]];
    
    مؤشر على محتوى هذا النص.
  • مؤثر الأقواس
    عملية هذا(م: صـحيح_متكيف): مـحرف
    
    handler this(i: ArchInt): Char
    
    يمكن استخدام هذا المؤثر لإرجاع المحرف في الموقع المحدد.
  • مؤثرات المقارنة
    عملية هذا == مؤشر[مصفوفة[مـحرف]]: ثـنائي
    عملية هذا < مؤشر[مصفوفة[مـحرف]]: ثـنائي
    عملية هذا > مؤشر[مصفوفة[مـحرف]]: ثـنائي
    عملية هذا <= مؤشر[مصفوفة[مـحرف]]: ثـنائي
    عملية هذا >= مؤشر[مصفوفة[مـحرف]]: ثـنائي
    
    handler this == ptr[array[Char]]: Bool
    handler this > ptr[array[Char]]: Bool
    handler this < ptr[array[Char]]: Bool
    handler this >= ptr[array[Char]]: Bool
    handler this <= ptr[array[Char]]: Bool
    
    تقارن هذا النص مع النص المعطى.
  • هات_الطول (getLength)
    1: عملية هذا.هات_الطول (): صـحيح_متكيف؛
    2: دالة هات_الطول (م: مؤشر[مصفوفة[مـحرف]]): صـحيح_متكيف؛
    
    1: handler this.getLength (): ArchInt;
    2: func getLength (p: ptr[array[Char]]): ArchInt;
    
    1. ترجع طول هذا النص.
    2. ترجع طول سلسلة المحارف المعطاة.
  • احجز (alloc)
    عملية هذا.احجز (صـحيح_متكيف)؛
    
    handler this.alloc (ArchInt);
    
    تقوم بحجز مسبق للذاكرة. تمكن هذه الدالة المستخدم من حجز الذاكرة مسبقًا قبل تعبئتها بالمحتوى باستخدام التعامل المباشر مع صوان هذا النص. تنفع هذه الطريقة عند التعامل مع مكتبات تتعامل مع مؤشرات المحارف، مع الاستفادة من خاصيات إدارة الذاكرة التي يوفرها هذا الصنف.
  • غير_الحجز (realloc)
    عملية هذا.غير_الحجز (صـحيح_متكيف)؛
    
    handler this.realloc (ArchInt);
    
    تغير حجم الذاكرة المحجوزة لهذا النص. تمكن هذه الدالة المستخدم من تغيير حجم الذاكرة المحجوزة قبل تغيير المحتوى باستخدام التعامل المباشر مع صوان هذا النص.
  • عين (assign)
    1. عملية هذا.عين (نص: سند[نـص])؛
    2. عملية هذا.عين (صوان: مؤشر[مصفوفة[مـحرف]])؛
    3. عملية هذا.عين (صوان: مؤشر[مصفوفة[مـحرف]]، عدد: صـحيح_متكيف)؛
    4. دالة عين (المقصد: مؤشر[مصفوفة[مـحرف]]، نسق: مؤشر[مصفوفة[مـحرف]]، ...أيما): صـحيح؛
    
    1: handler this.assign (str: ref[String]);
    2: handler this.assign (buf: ptr[array[Char]]);
    3: handler this.assign (buf: ptr[array[Char]], count: ArchInt);
    4: func assign (target: ptr[array[Char]], fmt: ptr[array[Char]], ...any): Int;
    
    1. تعيين محتوى جديد للنص من نص آخر. هذه الدالة لا تنسخ محتوى النص الآخر وإنما تتشارك معه بنفس الصوان لحين حاجة أحد النصين لتغيير المحتوى، حينها ينسخ ذاك النص الصوان وتنتهي المشاركة.
    2. تعيين محتوى جديد للنص من صوان في الذاكرة. تنسخ هذه الدالة المحتوى من ذلك الصوان إلى صوان جديد يديره هذا النص.
    3. مشابهة للدالة 2 لكنها تنسخ فقط العدد المحدد من المحارف من الصوان المعطى.
    4. تعيين قيمة جديدة من نسق (format) وعدد غير محدد من المعطيات إلى المقصد. يجب على المستخدم ضمان أن تكفي ذاكرة المقصد لاستيعاب الناتج كاملاً.
    يمكن للمستخدم أيضًا استخدام المؤثر = للاستعاضة عن الدالتين 1 و 2.
  • ألحق (append)
    1. عملية هذا.ألحق (صوان: مؤشر[مصفوفة[مـحرف]])؛
    2. عملية هذا.ألحق (صوان: مؤشر[مصفوفة[مـحرف]]، عدد: صـحيح_متكيف)؛
    3. عملية هذا.ألحق (م: مـحرف)؛
    4. عملية هذا.ألحق (ص: صـحيح[64])؛
    5. عملية هذا.ألحق (ع: عـائم[64])؛
    
    1. handler this.append (buf: ptr[array[Char]]);
    2. handler this.append (buf: ptr[array[Char]], count: ArchInt);
    3. handler this.append (c: Char);
    4. handler this.append (i: Int[64]);
    5. handler this.append (f: Float[64]);
    
    1. ألحق الصوان المعطى بنهاية محتوى هذا النص.
    2. ألحق العدد المحدد من المحارف من الصوان المعطى.
    3. ألحق محرفا بنهاية هذا النص.
    4. ألحق العدد المعطى بنهاية هذا النص. هذه الدالة تلحق تمثيلاً نصيا للعدد المعطى.
    5. مشابهة للدالة 4 لكنها تلحق عددا عائما بدل عدد صحيح.
    يمكن أيضا الاستعاضة عن هذه الدالات (باستثناء الدالة 2) بالمؤثر +=.
  • سلسل (concat)
    1. عملية هذا.سلسل (صوان: مؤشر[مصفوفة[مـحرف]])؛
    2. عملية هذا.سلسل (صوان: مؤشر[مصفوفة[مـحرف]]، عدد: صـحيح_متكيف)؛
    3. عملية هذا.سلسل (م: مـحرف)؛
    4. عملية هذا.سلسل (ص: صـحيح[64])؛
    5. عملية هذا.سلسل (ع: عـائم[64])؛
    6. دالة سلسل (المقصد: مؤشر[مصفوفة[مـحرف]]، المصدر: مؤشر[مصفوفة[مـحرف]]): مؤشر؛
    7. دالة سلسل (المقصد: مؤشر[مصفوفة[مـحرف]]، المصدر: مؤشر[مصفوفة[مـحرف]]، عدد: صـحيح_متكيف): مؤشر؛
    
    1. handler this.concat (buf: ptr[array[Char]]);
    2. handler this.concat (buf: ptr[array[Char]], count: ArchInt);
    3. handler this.concat (c: Char);
    4. handler this.concat (i: Int[64]);
    5. handler this.concat (f: Float[64]);
    6. func concat (target: ptr[array[Char]], source: ptr[array[Char]]): ptr;
    7. func concat (target: ptr[array[Char]], source: ptr[array[Char]], count: ArchInt): ptr;
    
    1-5. هذه الدالات مشابهة لدالات `ألحق` لكنها ترجع النتيجة في نص جديد بدل تعديل النص الحالي. يمكن أيضًا الاستعاضة عن هذه الدالات 1 و3 و4 و5 بالمؤثر +.
    6. تلحق سلسلة محارف المصدر بنهاية سلسلة محارف المقصد. يجب على المستخدم ضمان أن تكون ذاكرة المقصد المحجوزة كافية لاستيعاب العناصر الجديدة.
    7. مشابهة للدالة 6 لكنها تنسخ فقط العدد المحدد من عناصر المصدر.
  • جد (find)
    1: عملية هذا.جد (صوان: مؤشر[مصفوفة[محرف]]): صـحيح_متكيف؛
    2: عملية هذا.جد (م: مـحرف): صـحيح_متكيف؛
    3: دالة جد (سلسلة: مؤشر[مصفوفة[مـحرف]]، مقطع: مؤشر[مصفوفة[مـحرف]]): مؤشر[مصفوفة[مـحرف]]؛
    4: دالة جد (سلسلة: مؤشر[مصفوفة[مـحرف]]، م: مـحرف): مؤشر[مصفوفة[مـحرف]]؛
    
    1. handler this.find (buf: ptr[array[Char]]): ArchInt;
    2. handler this.find (c: Char): ArchInt;
    3. func find (haystack: ptr[array[Char]], needle: ptr[array[Char]]): ptr[array[Char]];
    4. func find (haystack: ptr[array[Char]], c: Char): ptr[array[Char]];
    
    1. بحث عن سلسلة محارف داخل هذا النص. ترجع موقع بداية سلسلة المحارف المكتشفة، أو -1 إذا فشل العثورة عليها.
    2. بحث عن محرف داخل هذ النص. ترجع موقع المحرف المكتشف، أو -1 إذا فشل العثور عليه.
    3. بحث عن مقطع داخل سلسلة المحارف المعطاة. ترجع مؤشر على بداية سلسلة المحارف المكتشفة، أو 0 إذا فشل العثور عليها.
    4. بحث عن محرف داخل سلسلة المحارف المعطاة. ترجع مؤشر على المحرف المكتشف، أو 0 إذا فشل العثور عليه.
  • جد_آخر (findLast)
    1: عملية هذا.جد_آخر (صوان: مؤشر[مصفوفة[محرف]]): صـحيح_متكيف؛
    2: عملية هذا.جد_آخر (م: مـحرف): صـحيح_متكيف؛
    3: دالة جد_آخر (سلسلة: مؤشر[مصفوفة[مـحرف]]، مقطع: مؤشر[مصفوفة[مـحرف]]): مؤشر[مصفوفة[مـحرف]]؛
    4: دالة جد_آخر (سلسلة: مؤشر[مصفوفة[مـحرف]]، م: مـحرف): مؤشر[مصفوفة[مـحرف]]؛
    
    1: handler this.findLast (buf: ptr[array[Char]]): ArchInt;
    2: handler this.findLast (c: Char): ArchInt;
    3: func findLast (haystack: ptr[array[Char]], needle: ptr[array[Char]]): ptr[array[Char]];
    4: func findLast (haystack: ptr[array[Char]], c: Char): ptr[array[Char]];
    
    هذه الدالات مشابهة لدالات `جد` لكنهن تبدأن البحث من نهاية النص بدل البحث من البداية.
  • قارن (compare)
    1. عملية هذا.قارن (صوان: مؤشر[مصفوفة[مـحرف]]): صـحيح؛
    2. عملية هذا.قارن (صوان: مؤشر[مصفوفة[مـحرف]]، عدد: صـحيح_متكيف): صـحيح؛
    3. دالة قارن (نص1: مؤشر[مصفوفة[مـحرف]]، نص2: مؤشر[مصفوفة[مـحرف]]): صـحيح؛
    4. دالة قارن (نص1: مؤشر[مصفوفة[مـحرف]]، مص2: مؤشر[مصفوفة[مـحرف]]، عدد: صـحيح_متكيف): صـحيح؛
    
    1. handler this.compare (buf: ptr[array[Char]]): Int;
    2. handler this.compare (buf: ptr[array[Char]], count: ArchInt): Int;
    3. func compare (str1: ptr[array[Char]], str2: ptr[array[Char]]): Int;
    4. func compare (str1: ptr[array[Char]], str2: ptr[array[Char]], count: ArchInt): Int;
    
    1. تقارن النص الحالي بالنص المعطى وترجع 1 إذا كان النص الحالي أكبر أو -1 إذا كان أصغر أو 0 إذا كانا متطابقين.
    2. مشابهة للدالة 1 لكنها تقارن فقط العدد المحدد من عناصر الصوان المعطى.
    3. مشابهة للدالة 1 لكنها تقارن مصفوفتي المحارف المعطاتين.
    4. مشابهة للدالة 3 لكنها تقارن عددا محددا فقط من محارف المصفوفة الثانية.
  • استبدل (replace)
    1. عملية هذا.استبدل (التطابق: مؤشر[مصفوفة[محرف]]، البديل: مؤشر[مصفوفة[محرف]])؛
    2. دالة استبدل (محارف: مؤشر[مصفوفة[مـحرف]]، من: مـحرف، إلى: مـحرف): مؤشر[مصفوفة[مـحرف]]؛
    
    1. handler this.replace (match: ptr[array[Char]], replacement: ptr[array[Char]]);
    2. func replace (chars: ptr[array[Char]], from: Char, to: Char): ptr[array[Char]];
    
    1. تبدل جزءا من النص بآخر وترجع الناتج في نص جديد.
    2. تستبدل محرفًا مكان آخر في سلسلة المحارف المعطاة. هذه الدالة تغيّر المصفوفة المعطاة.
  • شذب (trim)
    عملية هذا.شذب (): نـص؛
    
    handler this.trim (): String;
    
    تزيل الفراغات (المحارف غير المرئية سواء محرف المسافة أو غيرها) من طرفي النص وترجع الناتج في نص جديد.
  • شذب_البداية (trimStart)
    عملية هذا.شذب_البداية (): نـص؛
    
    handler this.trimStart (): String;
    
    مشابهة لدالة `شذب` لكنها تشذب البداية فقط.
  • شذب_النهاية (trimEnd)
    عملية هذا.شذب_النهاية (): نـص؛
    
    handler this.trimEnd (): String;
    
    مشابهة لدالة `شذب` لكنها تشذب النهاية فقط.
  • كبر (toUpperCase)
    عملية هذا.كبر (): نـص؛
    
    handler this.toUpperCase (): String;
    
    تستبدل الأحرف اللاتينية الصغيرة بمثيلاتها الكبيرة وترجع الناتج في نص جديد.
  • صغر (toLowerCase)
    عملية هذا.صغر (): نـص؛
    
    handler this.toLowerCase (): String;
    
    تستبدل الأحرف اللاتينية الكبيرة بمثيلاتها الصغيرة وترجع الناتج في نص جديد.
  • اجتزئ (slice)
    عملية هذا.اجتزئ (بداية: صـحيح_متكيف، عدد: صـحيح_متكيف): نـص؛
    
    handler this.slice (start: ArchInt, count: ArchInt): String;
    
    ترجع جزءا من النص الحالي كنص جديد.
  • قطع (split)
    عملية هذا.قطع (فاصل: مؤشر[مصفوفة[مـحرف]]): مـصفوفة[نـص]؛
    
    handler this.split (separator: ptr[array[Char]]): Array[String];
    
    ترجع أجزاء النص الحالي التي يفصلها الفاصل المعطى. إذا لم يوجد هذا النص فإنها ترجع عنصرا واحدا يحتوي النص كاملا.
  • ادمج (merge)
    دالة ادمج (أجزاء: مـصفوفة[نـص]، فاصل: مؤشر[مصفوفة[مـحرف]]): نـص؛
    
    func merge (parts: Array[String], separator: ptr[array[Char]]): String;
    
    ترجع نصًا جديدا يحتوى الأجزاء المعطاة مفصولة بالفاصل المعطى.
  • انسخ (copy)
    1. دالة انسخ (المقصد: مؤشر[مصفوفة[مـحرف]]، المصدر: مؤشر[مصفوفة[مـحرف]]): مؤشر؛
    2. دالة انسخ (المقصد: مؤشر[مصفوفة[مـحرف]]، المصدر: مؤشر[مصفوفة[مـحرف]]، عدد: صـحيح_متكيف): مؤشر؛
    
    1. func copy (target: ptr[array[Char]], source: ptr[array[Char]]): ptr;
    2. func copy (target: ptr[array[Char]], source: ptr[array[Char]], count: ArchInt): ptr;
    
    1. تنسخ سلسلة المحارف من المصدر إلى المقصد. يجب على المستخدم ضمان أن تكون الذاكرة المحجوزة للمقصد كافية لاستيعاب كامل مصفوفة المصدر.
    2. مشابهة للدالة 1 لكنها تنسخ فقط العدد المحدد من عناصر المصدر.
  • امسح (scan)
    دالة امسح (المصدر: مؤشر[مصفوفة[مـحرف]]، نسق: مؤشر[مصفوفة[مـحرف]]، ...أيما): صـحيح؛
    
    func scan (source: ptr[array[Char]], fmt: ptr[array[Char]], ...any): Int;
    
    امسح سلسلة المحارف المعطاة بحثًا عن العناصر المحددة في النسق وإرجاع هذه العناصر في المعطيات الملحقة بعد النسق. هذه الدالة مطابقة لدالة النظام sscanf.
  • أهو_مسافة (isSpace)
    دالة أهو_مسافة (م: مـحرف): ثـنائي؛
    
    func isSpace (c: Char): Bool;
    
    تخبرك فيما إذا كان المحرف المعطى مسافة أو إزاحة (tab) أو سطر جديد أو محرف الرجوع لبداية السطر.
  • أمتطابق (isEqual)
    دالة أمتطابق (نص1: مؤشر[مصفوفة[مـحرف]]، نص2: مؤشر[مصفوفة[مـحرف]]): ثـنائي؛
    
    func isEqual (str1: ptr[array[Char]], str2: ptr[array[Char]]): Bool;
    
    تخبرك فيما لو كانت سلسلتا المحارف المعطاتان متطابقتين.
  • أزل (remove)
    دالة أزل (محارف: مؤشر[مصفوفة[مـحرف]]، م: مـحرف): مؤشر[مصفوفة[مـحرف]]؛
    
    func remove (chars: ptr[array[Char]], c: Char): ptr[array[Char]];
    
    تزيل كل مطابقة للمحرف المعطى من سلسلة المحارف المعطاة. إزالة المحرف تؤدي إلى تزحيف المحارف التي بعده لتحل محله.
  • املأ (format)
    دالة املأ (صيغة: مؤشر[مصفوفة[مـحرف]]، قيم: ...أيما): نـص؛
    
    func format (fmt: ptr[array[Char]], values: ...any): String;
    
    تنشئ نصًا جديدًا من الصيغة المعطاة بعد ملئها بالقيم المطاة. تعمل هذه الدالة بشكل مشابه لدالة sprintf، وذلك باستبدال الرموز البادئة ب% في الصيغة بقيمة من قائمة المعطيات تطابق الصنف المحدد. الرمز % يتبعه محرف يدل على صنف القيمة المعطاة، وهي كالتالي:
    • %s سلسلة محارف نصية.
    • %c محرف مفرد.
    • %i عدد صحيح بحجم 32 بت.
    • %l عدد صحيح بحجم 64 بت.
    • %f عدد عائم بحجم 32 بت.
    • %d عدد عائم بحجم 64 بت.
    • %% تطبع علامة % نفسها.
  • اقرأ_صحيح (parseInt)
    دالة اقرأ_صحيح (نص: مؤشر[مصفوفة[مـحرف]]): صـحيح[64]؛
    
    func parseInt (str: ptr[array[Char]]): Int[64];
    
    تقرأ عددًا صحيحًا من سلسلة المحارف المعطاة وترجعه.
  • اقرأ_عائم (parseFloat)
    دالة اقرأ_عائم (نص: مؤشر[مصفوفة[مـحرف]]): عـائم[64]؛
    
    func parseFloat (str: ptr[array[Char]]): Float[64];
    
    تقرأ عددًا عائمًا من سلسلة المحارف المعطاة وترجعه.
  • اقرأ_محرف_هكس (parseHexDigit)
    دالة اقرأ_محرف_هكس (م: مـحرف): صـحيح؛
    
    func parseHexDigit (c: Char): Int;
    
    تحول محرفا يمثل رقمًا ست عشريًا إلى قيمته الرقمية.

الصنف: تـطبيق (Map)

قالب تـطبيق (Map) يتيح تحديد صنفي المفتاح والقيمة ويتولى مسؤولية إدارة الذاكرة مع مراعاة الأداء وتجنب عمليات النسخ وحجز الذاكرة غير الضرورية. المثال التالي يوضح التعامل مع هذا التطبيق:
دالة رئيسي {
  عرف ت1: تـطبيق[صـحيح، صـحيح] = هات_تطبيق()؛
  ت1.حدد(7، 50)؛ // هنا يتم تمديد حجم الذاكرة المحجوزة.
  عرف ت2: تـطبيق[صـحيح، صـحيح] = ت1؛ // هنا لا يتم إنشاء نسخة جديدة من الصوان.
  ت2.حدد(12، 7)؛ // الآن يتم إنشاء نسخة جديدة كي لا يتأثر ت1.
  اطبع_تطبيق(ت2)؛ // لا يتم هنا إعادة حجز الذاكرة أو نسخها.
  اطبع_صحيح(ت2(7))؛ // سيطبع 50.
  اطبع_صحيح(ت2(12))؛ // سيطبع 7.
  // الآن يتم تحرير ذاكرة ت1 و ت2.
}

دالة هات_تطبيق (): تطبيق[صـحيح، صـحيح] {
  عرف ت: تـطبيق[صـحيح، صـحيح]؛
  ت.أضف(0، 10)؛
  ارجع ت؛ // لا يتم هنا إعادة حجز الذاكرة أو نسخها.
}

دالة اطبع_تطبيق (ت: تـطبيق[صـحيح، صـحيح]) {
  عرف ع: صـحيح؛
  لكل ع = 0، ع < ت.هات_الطول()، ++ع {
    طـرفية.اطبع("%d = %d\ج"، ت.المفتاح_عند(ع)، ت.القيمة_عند(ع))؛
  }
}
func main {
  def m1: Map[Int, Int] = getMap();
  m1.set(7, 50); // Memory buffer is expanded here.
  def m2: Map[Int, Int] = m1; // Buffer is not cloned here.
  m2.set(12, 7); // Buffer is cloned here so that m1 is not affected.
  printMap(m2); // No buffer cloning happens here.
  printInt(m2(7)); // Prints 50.
  printInt(m2(12)); // Prints 7.
  // Now buffers of m1 and m2 are freed.
}

func getMap (): Map[Int, Int] {
  def m: Map[Int, Int];
  m.add(0, 10);
  return m; // No buffer cloning happens here.
}

func printMap (m: Map[Int, Int]) {
  def i: Int;
  for i = 0, i < m.getLength(), ++i {
    Console.print("%d = %d\n", m.keyAt(i), m.valAt(i));
  }
}
يحتوي الصنف `تـطبيق` على العناصر التالية:
  • التهيئة
      عملية هذا~هيئ(استخدم_فهرسا: ثـنائي)؛
      عملية هذا~هيئ(سند[تـطبيق[صـنف_المفتاح، صـنف_المحتوى]])؛
      عملية هذا~هيئ(سند[تـطبيق[صـنف_المفتاح، صـنف_المحتوى]]، استخدم_فهرسا: ثـنائي)؛
    
      handler this~init (useIndex: Bool);
      handler this~init (ref[Map[KeyType, ValueType]]);
      handler this~init (ref[Map[KeyType, ValueType]], useIndex: Bool);
    
    الصيغة الأولى تهيئ تطبيقًا فارغًا مع الاختيار بين استخدام فهرس من عدمه. استخدام الفهرس يسرع البحث عن العناصر في التطبيق، على حساب استهلاك الذاكرة وتبطيء إضافة العناصر.
    الصيغة الثانية تهيئ التطبيق من تطبيق آخر. سيستخدم التطبيق الجديد نفس المحتوى الذي في التطبيق المعطى ولن يتم نسخ المحتوى حتى يغير أحد التطبيقين المحتوى، وعندها ينسخ المحتوى قبل التغيير لضمان عدم تأثر التطبيق الآخر. في هذه الصيغة لن يتم استخدام فهرس حتى لو كان للتطبيق المعطى فهرس.
    الصيغة الثالثة مشابهة للثانية مع تمكين المستخدم من استخدام فهرس. إن طلب المستخدم استخدام فهرس فسيتم ذلك حتى لو خلا التطبيق المعطى من الفهرس.
  • مفاتيح (keys)
      عرف مفاتيح: مـصفوفة[صـنف_المفتاح]؛
    
      def keys: Array[KeyType];
    
    مصفوفة المفاتيح التي في هذا التطبيق.
  • قيم (values)
      عرف قيم: مـصفوفة[صـنف_المحتوى]؛
    
      def values: Array[ValueType];
    
    مصفوفة المحتويات التي في هذا التطبيق.
  • هات_الطول (getLength)
      عملية هذا.هات_الطول (): صـحيح_متكيف؛
    
      handler this.getLength (): ArchInt;
    
    ترجع عدد العناصر في التطبيق.
  • المفتاح_عند (keyAt)
      عملية هذا.المفتاح_عند (صـحيح_متكيف): سند[صـنف_المفتاح]؛
    
      handler this.keyAt (ArchInt): ref[KeyType];
    
    ترجع سندًا للمفتاح الذي عند الموقع المطلوب.
  • القيمة_عند (valAt)
      عملية هذا.القيمة_عند (صـحيح_متكيف): سند[صـنف_المحتوى]؛
    
      handler this.valAt (ArchInt): ref[ValueType];
    
    ترجع سندًا للقيمة التي عند الموقع المطلوب.
  • حدد (set)
      عملية هذا.حدد (
          مفتاح: صـنف_المفتاح، قيمة: صـنف_القيمة
      ): سند[تـطبيق[صـنف_المفتاح، صـنف_المحتوى]]؛
    
      handler this.set (
        key: KeyType, value: ValueType
      ): ref[Map[KeyType, ValueType]];
    
    تحدد قيمة للمفتاح المعطى. إن كان لهذا المفتاح قيمة فإنها ستبدل بالقيمة الجديدة. هذه الدالة ترجع سندا للتطبيق نفسه، ما يمكن المستخدم من سلسلة عدة عمليات تحديد في جملة واحدة.
  • حدد_عند (setAt)
      عملية هذا.حدد_عند (
          تسلسل: صـحيح_متكيف، قيمة: صـنف_القيمة
      ): سند[تـطبيق[صـنف_المفتاح، صـنف_المحتوى]]؛
    
      handler this.setAt (
        index: ArchInt, value: ValueType
      ): ref[Map[KeyType, ValueType]];
    
    تحدد قيمة جيدة عند التسلسل المعطى، أي تغيير القيمة باستخدام تسلسلها بدلاً من مفتاحها. هذه الدالة ترجع سندا للتطبيق نفسه، ما يمكن المستخدم من سلسلة عدة عمليات تحديد في جملة واحدة.
  • احشر (insert)
      عملية هذا.احشر (تسلسل: صـحيح_متكيف، مفتاح: صـنف_المفتاح، قيمة: صـنف_القيمة)؛
    
      handler this.insert (index: ArchInt, key: KeyType, value: ValueType);
    
    تضيف مفتاحًا جديدًا وقيمته عند التسلسل المحدد.
  • أزل (remove)
      عملية هذا.أزل (مفتاح: صـنف_المفتاح): ثـنائي؛
    
      handler this.remove (key: KeyType): Bool;
    
    تزيل المفتاح المحدد وقيمته. ترجع 1 إذا أُزيل المفتاح، و 0 إذا لم يوجد المفتاح ابتداءًا.
  • أزل_عند (removeAt)
      عملية هذا.أزل_عند (تسلسل: صـحيح_متكيف)؛
    
      handler this.removeAt (index: ArchInt);
    
    تزيل المفتاح عند التسلسل المحدد وقيمتَه.
  • فرغ (clear)
      عملية هذا.فرغ ()؛
    
      handler this.clear ();
    
    تفرغ كل المحتوى وتبدأ بتطبيق فارغ.
  • جد_الموقع (findPos؛)
      عملية هذا.جد_الموقع (مفتاح: صـنف_المفتاح): صـحيح_متكيف؛
    
      handler this.findPos (key: KeyType): ArchInt;
    
    ترجع تسلسل المفتاح المعطى، أو -1 إن لم يوجد هذا المفتاح.

الصنف: سـندنا (SrdRef)

قالب سند مشترك يتولى تلقائيا تحرير الكائن عندما تنتهي الحاجة له. يحتفظ هذا السند بعداد لعدد السندات المشتركة التي تشير لنفس الكائن. كلما يُتلف أحد السندات يُنقص العداد وعندما يصل العداد لصفر يُتلف الكائن وتحرر ذاكرته.
دالة رئيسي {
  عرف س: سـندنا[صـنفي] = سـندنا[صـنفي].أنشئ()؛
  عرف ص: سـندنا[صـنفي] = س؛ // الآن كلا السندين يشيران لنفس الكائن وعداده الآن 2.
  س.حرر()؛ // العداد صار 1 لكن الكائن لم يُحرر بعد.
  ص.حرر()؛ // الآن أتلف الكائن وحررت ذاكرته.
}
func main {
  def x: SrdRef[MyType] = SrdRef[MyType].construct();
  def y: SrdRef[MyType] = x; // Both refs point to same object. Counter is now 2.
  x.release(); // Counter is now 1 and the object is not freed yet.
  y.release(); // Now the object is destructed and its memory is released.
}
يحتوي الصنف `سـندنا` على المتغيرات والدالات التالية:
  • كائن (obj)
    الكائن الذي يشير إليه هذا السند. في بعض الحالات قد تحتاج للوصول إلى الكائن نفسه مثلما هو الحال عندما تحتاج مؤشرًا أو سندا اعتياديا للكائن أو في حالة الوصول إلى دالة للكائن باسم مطابق لإحدى دالات الصنف `سـندنا`.
  • عداد_السندات (refCounter)
    القيد الذي يحتفظ بعداد السندات التي تؤشر لنفس الكائن ويحتفظ أيضا بالبيانات المطلوبة لإتلاف وتحرير الكائن.
  • احجز (alloc)
      عملية هذا.احجز (): سند[صـنف_الكائن]؛
      دالة احجز (): سـندنا[صـنف_الكائن]؛
    
      handler this.alloc (): ref[ObjType];
      func alloc (): SrdRef[ObjType];
    
    تقوم هذه الدالة بحجز ذاكرة للكائن، لكنها لا تهيئ الكائن وتترك للمستخدم مسؤولية التهيئة باستخدام `~هيئ`.
  • أنشئ (construct)
      عملية هذا.أنشئ ()؛
      دالة أنشئ (): سـندنا[صـنف_الكائن]؛
    
      handler this.construct ();
      func construct (): SrdRef[ObjType];
    
    تقوم هذه الدالة بحجز ذاكرة للكائن وتهيئته أيضًا. تهيئة الكائن تتم دون أي معطيات لذا لاستخدام هذه الدالة يحتاج الكائن لتمكين التهيئة دون معطيات. إذا احتجت تهيئة الكائن بمعطيات فستحتاج لاستخدام دالة `احجز` بدلًا من هذه الدالة ثم التهيئة يدويا باستخدام `~هيئ`.
  • تملك (own)
      عملية هذا.تملك (كائن: سند[صـنف_الكائن])؛
      دالة تملك (كائن: سند[صـنف_الكائن]): سـندنا[صـنف_الكائن]؛
    
      handler this.own (obj: ref[ObType]);
      func own (obj: ref[ObjType]): SrdRef[ObjType];
    
    هذه الدالة تعين كائن هذا السند بكائن متوفر سلفًا. بعد استدعاء هذه الدالة يتولى هذا السند مسؤولية تحرير الكائن تلقائيًا. يجب تجنب هذه الدالة إذا لم يكن الكائن المعطى محجوزًا ديناميكيًا أو إذا تولت شفرة أخرى مسؤولية تحرير الكائن لأن ذلك سيؤدي إلى segmentation fault.
  • حرر (release)
      عملية هذا.حرر()؛
    
      handler this.release();
    
    تصفر هذا السند وإذا كان هذا آخر سند يشير إلى الكائن فتُحرر الكائن قبل تصفير السند.
  • عين (assign)
      عملية هذا.عين (س: سند[سـندنا[صـنف_الكائن]])؛
      عملية هذا.عين (س: سند[سـندهم[صـنف_الكائن]])؛
      عملية هذا.عين (ع: سند[عـداد_السندات]، ك: سند[صـنف_الكائن])؛
    
      handler this.assign (r: ref[SrdRef[ObjType]]);
      handler this.assign (r: ref[WkRef[ObjType]]);
      handler this.assign (c: ref[RefCounter], o: ref[ObjType]);
    
    تعين قيمة جديدة للسند، أي تغير السند ليؤشر إلى الكائن المعطى. الدالتان الأولى والثانية تأخذان قيمة السند من صنف `سـندنا` وصنف `سـندهم` على التوالي وبنفس صنف الكائن، أما الدالة الثالثة فتستخدم لجعل السند يشير إلى كائن بنفس صنف هذا السند لكنه ينتمي لسند من صنف آخر. تستخدم هذه الدالة في حالة التمثيل وما شابه مع ضمان أن تحرير الكائن عند إتلاف السند سيؤدي إلى تحرير الكائن الأصلي وبصنفه الأصلي الذي أنشئ عليه. المثال التالي يوضح الفرق:
      عرف س: سـندنا[صـنفي]؛
      س.أنشئ()؛
      عرف ص: سـندنا[صـنف_فرعي]؛
      ص.عين(س.عداد_السندات، س.فرعي)؛
    
      س.حرر()؛ // لن يحرر شيئًا الآن لأن ص ما زال يحجز الكائن.
      ص.حرر()؛ // هنا سيُحرر كائن س نفسه وليس س.فرعي.
    
      def x: SrdRef[MyType];
      x.construct();
      def y: SrdRef[SubType];
      y.assign(x.refCounter, x.subObj);
      
      x.release(); // Nothing will be released as y still holds the object.
      y.release(); // Here x itself will be released, not x.subObj.
    
  • أهو_عدم (isNull)
      عملية هذا.أهو_عدم(): ثـنائي؛
    
      handler this.isNull(): Bool;
    
    تتحقق فيما لو كان السند يشير لعدم، أي فيما لو كان مؤشره صفرًا.

الصنف: سـندهم (WkRef)

قالب سند يشير لكائن لكنه لا يُساهم في تملك الكائن، أي أنه ليس له حصة في عداد السندات الخاص بالكائن. بمعنى آخر، إذا كان هذا السند يشير لكان وأتلفت جميع سندات `سـندنا` المشيرة للكائن فإن الكائن سيُحرر رغم وجود `سـندهم` يشير إليه. يفيد هذا النوع من السندات في تجنب حلقات السندات المغلقة التي تؤدي إلى تسرب في الذاكرة. فإن كان عندك كائن يمتلك كائنًا آخر عبر `سـندنا` وكان الكائن الداخلي يحتاج سندًا للكائن الخارجي فاستخدام `سـندنا` في الكائن الداخلي سيؤدي إلى حلقة مغلقة بينما استخدام `سـندهم` في الكائن الداخلي لي يؤدي للحلقة المغلقة لأن تحرير الكائن الخارجي في هذه الحالة ممكن رغم وجود كائن داخلي يشير إليه.
الفرق بين استخدام `سـندهم` واستخدام `سند` أن الأول يحمل معلومات عداد السندات وإن كان لا يستعملها، بينما السند التقليدي لا يحمل تلك المعلومات، لذلك بالإمكان الحصول على `سـندنا` من `سـندهم` بينما لا يمكن الحصول على `سـندنا` من `سند` لأن الأخير لا يحمل معلومات العداد التي يحتاجها `سـندنا`.
طريقة استخدام `سـندهم` مطابقة لـ`سـندنا`. يملك صنف `سـندهم` العناصر التالية:
  • كائن (obj)
    الكائن الذي يشير إليه هذا السند. في بعض الحالات قد تحتاج للوصول إلى الكائن نفسه مثلما هو الحال عندما تحتاج مؤشرًا أو سندا اعتياديا للكائن أو في حالة الوصول إلى دالة للكائن باسم مطابق لإحدى دالات الصنف `سـندهم`.
  • عداد_السندات (refCounter)
    القيد الذي يحتفظ بعداد السندات التي تؤشر لنفس الكائن ويحتفظ أيضا بالبيانات المطلوبة لإتلاف وتحرير الكائن.
  • حرر (release)
      عملية هذا.حرر()؛
    
      handler this.release();
    
    تصفر هذا السند دون تغيير شيء في عداد السندات.
  • عين (assign)
      عملية هذا.عين (س: سند[سـندنا[صـنف_الكائن]])؛
      عملية هذا.عين (س: سند[سـندهم[صـنف_الكائن]])؛
      عملية هذا.عين (ع: سند[عـداد_السندات]، ك: سند[صـنف_الكائن])؛
    
      handler this.assign (r: ref[SrdRef[ObjType]]);
      handler this.assign (r: ref[WkRef[ObjType]]);
      handler this.assign (c: ref[RefCounter], o: ref[ObjType]);
    
    تعين قيمة جديدة للسند، أي تغير السند ليؤشر إلى الكائن المعطى. الدالتان الأولى والثانية تأخذان قيمة السند من صنف `سـندنا` وصنف `سـندهم` على التوالي وبنفس صنف الكائن، أما الدالة الثالثة فتستخدم لجعل السند يشير إلى كائن بنفس صنف هذا السند لكنه ينتمي لسند من صنف آخر. تستخدم هذه الدالة في حالة التمثيل وما شابه مع ضمان أن تحرير الكائن عند إتلاف السند سيؤدي إلى تحرير الكائن الأصلي وبصنفه الأصلي الذي أنشئ عليه. المثال التالي يوضح الفرق:
      عرف س: سـندنا[صـنفي]؛
      س.أنشئ()؛
      عرف ع: سـندهم[صـنف_فرعي]؛
      ع.عين(س.عداد_السندات، س.فرعي)؛
      عرف ص: سـندنا[صـنف_فرعي]؛
      ص = ع؛
    
      س.حرر()؛ // لن يحرر شيئًا الآن لأن ص ما زال يحجز الكائن.
      ص.حرر()؛ // هنا سيُحرر كائن س نفسه وليس س.فرعي.
    
      def x: SrdRef[MyType];
      x.construct();
      def y: WkRef[SubType];
      y.assign(x.refCounter, x.subObj);
      def z: SrdRef[SubType];
      z = y;
      
      x.release(); // Nothing is released here.
      z.release(); // x will be released here, not x.subObj.
    
  • أهو_عدم (isNull)
      عملية هذا.أهو_عدم(): ثـنائي؛
    
      handler this.isNull(): Bool;
    
    تتحقق فيما لو كان السند يشير لعدم، أي فيما لو كان مؤشره صفرًا.

الصنف: سـندي (UnqRef)

أبسط أنواع السندات الذكية. هذا السند غير مشترك ولا يستخدم عدادًا للسندات. عند إتلاف هذا السند فإنه سيحرر الكائن الذي يملكه مباشرة. مثال:
  عرف س: سـندي[صـنفي]؛
  س.أنشئ()؛

  عرف ص: سـندي[صـنفي]؛
  ص = س؛ // خطأ.

  س.حرر()؛ // يُحرر الكائن هنا تلقائيا.
  def x: UnqRef[MyType];
  x.construct();
  
  def y: UnqRef[MyType];
  y = x; // Error.
  
  x.release(); // Object will be released here.
يحتوي هذا الصنف على العناصر التالية:
  • كائن (obj)
    الكائن الذي يشير إليه هذا السند. في بعض الحالات قد تحتاج للوصول إلى الكائن نفسه مثلما هو الحال عندما تحتاج مؤشرًا أو سندا اعتياديا للكائن أو في حالة الوصول إلى دالة للكائن باسم مطابق لإحدى دالات الصنف `سـندهم`.
  • أنشئ (construct)
    عملية هذا.أنشئ()؛
    
    handler this.construct();
    
    تقوم هذه الدالة بحجز ذاكرة للكائن وتهيئته أيضًا. تهيئة الكائن تتم دون أي معطيات لذا لاستخدام هذه الدالة يحتاج الكائن لتمكين التهيئة دون معطيات.
  • حرر (release)
    عملية هذا.حرر()؛
    
    handler this.release();
    
    تصفر هذا السند وتحرر الكائن.
  • أهو_عدم (isNull)
      عملية هذا.أهو_عدم(): ثـنائي؛
    
      handler this.isNull(): Bool;
    
    تتحقق فيما لو كان السند يشير لعدم، أي فيما لو كان مؤشره صفرًا.

الصنف: خـطأ (Error)

جذر لأصناف حمل بيانات الأخطاء التنفيذية. يحتوي على وظيفتين مجردتين:
  • هات_الرمز (getCode)
    ترجع رمزًا يميز الخطأ عن غيره بدقة.
      عملية هذا.هات_الرمز(): نـص كمؤشر؛
    
      handler this.getCode(): String as_ptr;
    
  • هات_الرسالة (getMessage)
    ترجع وصفا نصيا للخطأ يمكن عرضه للمستخدم.
      عملية هذا.هات_الرسالة(): نـص كمؤشر؛
    
      handler this.getMessage(): String as_ptr;
    

الصنف: خـطأ_عام (GenericError)

صنف خطأ عام مُشتق من الصنف `خـطأ` (`Error`) يمكّن المستخدم من تحديد رمزه ورسالته يدويا لكل كائن منه. يحتوي على متغيرين:
  • الرمز (code): نـص (String)
  • الرسالة (message): نـص (String)

الصنف: لـا_مضمون (Possible)

قالب أصناف لحمل بيانات بصنف غير محدد (يحدده المستخدم) مع إمكانية حمل إشعار خطأ بدل البيانات في حالة فشل العملية. يحتاج المستخدم الذي يستلم متغيرا من هذا الصنف لفحص حالة الخطأ قبل التعامل مع البيانات التي يحملها هذا الصنف. يحتوي على العناصر التالية:
  • القيمة (value)
    البيانات التي يحملها الكائن. الصنف `صـنف_البيانات` (`DataType`) يشير إلى معطى القالب.
      @حقنة عرف القيمة: صـنف_البيانات؛
    
      @injection def value: DataType;
    
  • الخطأ (error)
    سند إلى الخطأ في حال وجوده. إن كان حُددت قيمة هذا الخطأ فالعملية فاشلة والبيانات في `القيمة` غير صالحة للاستخدام.
      عرف الخطأ: سـندنا[خـطأ]؛
    
      def error: SrdRef[Error];
    
  • عمليات التمثيل
    يحتوي هذا الصنف عمليات التمثيل التالية:
      عملية هذا~مثل[سند[صـنف_البيانات]] أرجع هذا.القيمة؛
      عملية هذا~مثل[ثـنائي] أرجع هذا.الخطأ.أهو_عدم()؛
    
      handler this~cast[ref[DataType]] return this.value;
      handler this~cast[Bool] return this.error.isNull();
    
    عملية التمثيل كـ`ثـنائي` (`Bool`) ترجع 1 إن كانت العملية ناجحة، أي إن كانت البيانات صالحة للاستخدام.
  • نجاح (success)
    دالة لتسهيل إنشاء كائن يحمل قيمة صالحة.
      دالة نجاح (ق: صـنف_البيانات): لـا_مضمون[صـنف_البيانات]؛
    
      func success (v: DataType): Possible[DataType];
    
  • فشل (failure)
    دالة لتسهيل إنشاء كائن خطأ.
      دالة فشل (خ: سـندنا[خـطأ]): لـا_مضمون[صـنف_البيانات]؛
    
      func failure (err: SrdRef[Error]): Possible[DataType];
    

الصنف: بـعدم (Nullable)

قالب أصناف لحمل بيانات بصنف غير محدد (يحددث المستخدم) مع إضافة القيمة `عدم` (`null`) كأحد القيم المتاحة.
  • القيمة (value)
    البيانات التي يحملها الكائن. الصنف `صـنف_البيانات` (`DataType`) يشير إلى معطى القالب.
      @حقنة عرف القيمة: صـنف_البيانات؛
    
      @injection def value: DataType;
    
  • أهو_عدم (isNull)
    قيمة ثنائية تحدد إن كانت القيمة `عدم` (`null`) أم لا.
      عرف أهو_عدم: ثـنائي؛
    
      def isNull: Bool;
    
  • عمليات التمثيل
    يحتوي هذا الصنف عملية تمثيل تحول تلقائيا إلى صنف البيانات الأصلي.
      عملية هذا~مثل[سند[صـنف_البيانات]] أرجع هذا.القيمة؛
    
      handler this~cast[ref[DataType]] return this.value;
    

الوحدة: ذاكـرة (Memory)

تحتوي وحدة `ذاكـرة` على الدالات التالية:
  • احجز (alloc)
    @تصدير[malloc] دالة احجز (حجم: صـحيح_متكيف): مؤشر؛
    
    @expname[malloc] func alloc (size: ArchInt): ptr;
    
    مطابقة لدالة malloc من POSIX.
  • أعد_الحجز (realloc)
    @تصدير[realloc] دالة أعد_الحجز (م: مؤشر، الحجم_الجديد: صـحيح_متكيف): مؤشر؛
    
    @expname[realloc] func realloc (p: ptr, newSize: ArchInt): ptr;
    
    مطابقة لدالة realloc من POSIX.
  • احجز_مرصوف (allocAligned)
    @تصدير[aligned_alloc]
    دالة احجز_مرصوف (رصف: صـحيح_متكيف، حجم: صـحيح_متكيف): مؤشر؛
    
    @expname[aligned_alloc]
    func allocAligned (alignment: ArchInt, size: ArchInt): ptr;
    
    مطابقة لدالة aligned_alloc من POSIX.
  • حرر (free)
    @تصدير[free] دالة حرر (م: مؤشر)؛
    
    @expname[free] func free (p: ptr);
    
    مطابقة لدالة free من POSIX.
  • انسخ (copy)
    @تصدير[memcpy] دالة (مقصد: مؤشر، مصدر: مؤشر، حجم: صـحيح_متكيف): مؤشر؛
    
    @expname[memcpy] func (target: ptr, src: ptr, size: ArchInt): ptr;
    
    مطابقة لدالة memcpy من POSIX.
  • قارن (compare)
    @تصدير[memcmp] دالة قارن (حيز1: مؤشر، حيز2: مؤشر: حجم: صـحيح_متكيف): صـحيح؛
    
    @expname[memcmp] func compare (s1: ptr, s2: ptr, size: ArchInt): Int;
    
    مطابقة لدالة memcmp من POSIX.
  • اضبط (set)
    @تصدير[memset] دالة (حيز: مؤشر، قيمة: صـحيح، عدد: صـحيح_متكيف): مؤشر؛
    
    @expname[memset] func (s: ptr, c: Int, n: ArchInt): ptr;
    
    مطابقة لدالة memset من POSIX.

الوحدة: ريـاضيات (Math)

تحتوي وحدة `ريـاضيات` على الدالات التالية:
  • مطلق (abs)
    @تصدير[abs] دالة مطلق (ع: صـحيح[32]): صـحيح[32]؛
    @تصدير[llabs] دالة مطلق (ع: صـحيح[64]): صـحيح[64]؛
    @تصدير[fabsf] دالة مطلق (ع: عـائم[32]): عـائم[32]؛
    @تصدير[fabs] دالة مطلق (ع: عـائم[64]): عـائم[64]؛
    
    @expname[abs] func abs (i: Int[32]): Int[32];
    @expname[llabs] func abs (i: Int[64]): Int[64];
    @expname[fabsf] func abs (f: Float[32]): Float[32];
    @expname[fabs] func abs (f: Float[64]): Float[64];
    
    للحصول على القيمة المطلقة لرقم.
  • باقي (mod)
    @تصدير[fmodf] دالة باقي (س: عـائم[32]، ص: عـائم[32]): عـائم[32]؛
    @تصدير[fmod] دالة باقي (س: عـائم[64]، ص: عـائم[64]): عـائم[64]؛
    
    @expname[fmodf] func mod (x: Float[32], y: Float[32]): Float[32];
    @expname[fmod] func mod (x: Float[64], y: Float[64]): Float[64];
    
    للحصول على باقي قسمة رقمين حقيقيين.
  • أس_طبيعي (exp)
    @تصدير[expf] دالة أس_طبيعي (س: عـائم[32]): عـائم[32]؛
    @تصدير[exp] دالة أس_طبيعي (س: عـائم[64]): عـائم[64]؛
    
    @expname[expf] func exp (x: Float[32]): Float[32];
    @expname[exp] func exp (x: Float[64]): Float[64];
    
    مطابقة لدالتي exp و expf من POSIX.
  • أس_طبيعي2 (exp2)
    @تصدير[exp2f] دالة أس_طبيعي2 (س: عـائم[32]): عـائم[32]؛
    @تصدير[exp2] دالة أس_طبيعي2 (س: عـائم[64]): عـائم[64]؛
    
    @expname[exp2f] func exp2 (x: Float[32]): Float[32];
    @expname[exp2] func exp2 (x: Float[64]): Float[64];
    
    مطابقة لدالتي exp2 و exp2f من POSIX.
  • لو (log)
    @تصدير[logf] دالة لو (س: عـائم[32]): عـائم[32]؛
    @تصدير[log] دالة لو (س: عـائم[64]): عـائم[64]؛
    
    @expname[logf] func log (x: Float[32]): Float[32];
    @expname[log] func log (x: Float[64]): Float[64];
    
    مطابقة لدالتي log و logf من POSIX.
  • لو2 (log2)
    @تصدير[log2f] دالة لو2 (س: عـائم[32]): عـائم[32]؛
    @تصدير[log2] دالة لو2 (س: عـائم[64]): عـائم[64]؛
    
    @expname[log2f] func log2 (x: Float[32]): Float[32];
    @expname[log2] func log2 (x: Float[64]): Float[64];
    
    مطابقة لدالتي log2 و log2f من POSIX.
  • لو10 (log10)
    @تصدير[log10f] دالة لو10 (س: عـائم[32]): عـائم[32]؛
    @تصدير[log10] دالة لو10 (س: عـائم[64]): عـائم[64]؛
    
    @expname[log10f] func log10 (x: Float[32]): Float[32];
    @expname[log10] func log10 (x: Float[64]): Float[64];
    
    مطابقة لدالتي log10 و log10f من POSIX.
  • جذر (sqrt)
    @تصدير[sqrtf] دالة جذر (س: عـائم[32]): عـائم[32]؛
    @تصدير[sqrt] دالة جذر (س: عـائم[64]): عـائم[64]؛
    
    @expname[sqrtf] func sqrt (x: Float[32]): Float[32];
    @expname[sqrt] func sqrt (x: Float[64]): Float[64];
    
    مطابقة لدالتي sqrt و sqrtf من POSIX.
  • جذر3 (cbrt)
    @تصدير[cbrtf] دالة جذر3 (س: عـائم[32]): عـائم[32]؛
    @تصدير[cbrt] دالة جذر3 (س: عـائم[64]): عـائم[64]؛
    
    @expname[cbrtf] func cbrt (x: Float[32]): Float[32];
    @expname[cbrt] func cbrt (x: Float[64]): Float[64];
    
    مطابقة لدالتي cbrt و cbrtf من POSIX.
  • ارفع (pow)
    @تصدير[powf] دالة ارفع (أساس: عـائم[32]، أس: عـائم[32]): عـائم[32]؛
    @تصدير[pow] دالة ارفع (أساس: عـائم[64]، أس: عـائم[64]): عـائم[64]؛
    
    @expname[powf] func pow (b: Float[32], e: Float[32]): Float[32];
    @expname[pow] func pow (b: Float[64], e: Float[64]): Float[64];
    
    مطابقة لدالتي pow و powf من POSIX.
  • جا (sin)
    @تصدير[sinf] دالة جا (س: عـائم[32]): عـائم[32]؛
    @تصدير[sin] دالة جا (س: عـائم[64]): عـائم[64]؛
    
    @expname[sinf] func sin (x: Float[32]): Float[32];
    @expname[sin] func sin (x: Float[64]): Float[64];
    
    مطابقة لدالتي sin و sinf من POSIX.
  • جا_عكسي (asin)
    @تصدير[asinf] دالة جا_عكسي (س: عـائم[32]): عـائم[32]؛
    @تصدير[asin] دلة جا_عكسي (س: عـائم[64]): عـائم[64]؛
    
    @expname[asinf] func asin (x: Float[32]): Float[32];
    @expname[asin] func asin (x: Float[64]): Float[64];
    
    مطابقة لدالتي asin و asinf من POSIX.
  • جا_زائدي (sinh)
    @تصدير[sinhf] دالة جا_زائدي (س: عـائم[32]): عـائم[32]؛
    @تصدير[sinh] دالة جا_زائدي (س: عـائم[64]): عـائم[64]؛
    
    @expname[sinhf] func sinh (x: Float[32]): Float[32];
    @expname[sinh] func sinh (x: Float[64]): Float[64];
    
    مطابقة لدالتي sinh و sinhf من POSIX.
  • جا_زائدي_عكسي (asinh)
    @تصدير[asinhf] دالة جا_زائدي_عكسي (س: عـائم[32]): عـائم[32]؛
    @تصدير[asinh] دالة جا_زائدي_عكسي (س: عـائم[64]): عـائم[64]؛
    
    @expname[asinhf] func asinh (x: Float[32]): Float[32];
    @expname[asinh] func asinh (x: Float[64]): Float[64];
    
    مطابقة لدالتي asinh و asinhf من POSIX.
  • جتا (cos)
    @تصدير[cosf] دالة جتا (س: عـائم[32]): عـائم[32]؛
    @تصدير[cos] دالة جتا (س: عـائم[64]): عـائم[64]؛
    
    @expname[cosf] func cos (x: Float[32]): Float[32];
    @expname[cos] func cos (x: Float[64]): Float[64];
    
    مطابقة لدالتي cos و cosf من POSIX.
  • جتا_عكسي (acos)
    @تصدير[acosf] دالة جتا_عكسي (س: عـائم[32]): عـائم[32]؛
    @تصدير[acos] دالة جتا_عكسي (س: عـائم[64]): عـائم[64]؛
    
    @expname[acosf] func acos (x: Float[32]): Float[32];
    @expname[acos] func acos (x: Float[64]): Float[64];
    
    مطابقة لدالتي acos و acosf من POSIX.
  • جتا_زائدي (cosh)
    @تصدير[coshf] دالة جتا_زائدي (س: عـائم[32]): عـائم[32]؛
    @تصدير[cosh] دالة جتا_عكسي (س: عـائم[64]): عـائم[64]؛
    
    @expname[coshf] func cosh (x: Float[32]): Float[32];
    @expname[cosh] func cosh (x: Float[64]): Float[64];
    
    مطابقة لدالتي cosh و coshf من POSIX.
  • جتا_زائجي_عكسي (acosh)
    @تصدير[acoshf] دالة جتا_زائجي_عكسي (س: عـائم[32]): عـائم[32]؛
    @تصدير[asoch] دالة جتا_زائجي_عكسي (س: عـائم[64]): عـائم[64]؛
    
    @expname[acoshf] func acosh (x: Float[32]): Float[32];
    @expname[acosh] func acosh (x: Float[64]): Float[64];
    
    مطابقة لدالتي acosh و acoshf من POSIX.
  • ظل (tan)
    @تصدير[tanf] دالة ظل (س: عـائم[32]): عـائم[32]؛
    @تصدير[tan] دالة ظل (س: عـائم[64]): عـائم[64]؛
    
    @expname[tanf] func tan (x: Float[32]): Float[32];
    @expname[tan] func tan (x: Float[64]): Float[64];
    
    مطابقة لدالتي tan و tanf من POSIX.
  • ظل_عكسي (atan)
    @تصدير[atanf] دالة ظل_عكسي (س: عـائم[32]): عـائم[32]؛
    @تصدير[atan] دالة ظل_عكسي (س: عـائم[64]): عـائم[64]؛
    
    @expname[atanf] func atan (x: Float[32]): Float[32];
    @expname[atan] func atan (x: Float[64]): Float[64];
    
    مطابقة لدالتي atan و atanf من POSIX.
  • ظل_عكسي2 (atan2)
    @تصدير[atan2f] دالة ظل_عكسي2 (ص: عـائم[32]، س: عـائم[32]): عـائم[32]؛
    @تصدير[atan2] دالة ظل_عكسي2 (ص: عـائم[64]، س: عـائم[64]): عـائم[64]؛
    
    @expname[atan2f] func atan2 (y: Float[32], x: Float[32]): Float[32];
    @expname[atan2] func atan2 (y: Float[64], x: Float[64]): Float[64];
    
    مطابقة لدالتي atan2 و atan2f من POSIX.
  • ظل_زائدي (tanh)
    @تصدير[tanhf] دالة ظل_زائدي (س: عـائم[32]): عـائم[32]؛
    @تصدير[tanh] دالة ظل_زائدي (س: عـائم[64]): عـائم[64]؛
    
    @expname[tanhf] func tanh (x: Float[32]): Float[32];
    @expname[tanh] func tanh (x: Float[64]): Float[64];
    
    مطابقة لدالتي tanh و tanhf من POSIX.
  • ظل_زائدي_عكسي (atanh)
    @تصدير[atanhf] دالة ظل_زائدي_عكسي (س: عـائم[32]): عـائم[32]؛
    @تصدير[atanh] جالة ظل_زائدي_عكسي (س: عـائم[64]): عـائم[64]؛
    
    @expname[atanhf] func atanh (x: Float[32]): Float[32];
    @expname[atanh] func atanh (x: Float[64]): Float[64];
    
    مطابقة لدالتي atanh و atanhf من POSIX.
  • سقف (ceil)
    @تصدير[ceilf] دالة سقف (س: عـائم[32]): عـائم[32]؛
    @تصدير[ceil] دالة سقف (س: عـائم[64]): عـائم[64]؛
    
    @expname[ceilf] func ceil (x: Float[32]): Float[32];
    @expname[ceil] func ceil (x: Float[64]): Float[64];
    
    مطابقة لدالتي ceil و ceilf من POSIX.
  • جزء_صحيح (floor)
    @تصدير[floorf] دالة جزء_صحيح (س: عـائم[32]): عـائم[32]؛
    @تصدير[floor] دالة جزء_صحيح (س: عـائم[64]): عـائم[64]؛
    
    @expname[floorf] func floor (x: Float[32]): Float[32];
    @expname[floor] func floor (x: Float[64]): Float[64];
    
    مطابقة لدالتي floor و floorf من POSIX.
  • تقريب (round)
    @تصدير[roundf] دالة تقريب (س: عـائم[32]): عـائم[32]؛
    @تصدير[round] دالة تقريب (س: عـائم[64]): عـائم[64]؛
    
    @expname[roundf] func round (x: Float[32]): Float[32];
    @expname[round] func round (x: Float[64]): Float[64];
    
    مطابقة لدالتي round و roundf من POSIX.
  • عشوائي (random)
    @تصدير[rand] دالة عشوائي (): صـحيح؛
    
    @expname[rand] func random (): Int;
    
    مطابقة لدالة rand من POSIX.
  • جهز_العشوائية (seedRandom)
    @تصدير[srand] دالة جهز_العشوائية (ب: طـبيعي[32])؛
    
    @expname[srand] func seedRandom (s: Word[32]);
    
    مطابقة لدالة srand من POSIX.

الوحدة: شـبكة (Net)

تحتوي وحدة `شـبكة` على العناصر التالية:
  • هات_اعتماديات_البناء (getBuildDependencies)
    دالة هات_اعتماديات_البناء (): مـصفوفة[نـص]؛
    
    func getBuildDependencies(): Array[String];
    
    ترجع أسماء الاعتماديات المطلوبة في حالة بناء نسخة تنفيذية من مشروع يعتمد على وحدة `شـبكة`. في حالة `شـبكة` ترجع الدالة مكتبة واحدة وهي Curl. القيمة المرجعة تحتوي المسار الكامل للملف وليس فقط الاسم لأن الأسس تعتمد على نسخة من Curl مضمنة مع مكتبات الأسس.
  • هات (get)
    1: دالة هات (
         الرابط: مؤشر[مصفوفة[مـحرف]]، الناتج: مؤشر[مؤشر]، حجم_الناتج: مؤشر[صـحيح]
       ) => ثـنائي؛
    2: دالة هات (
         الرابط: مؤشر[مصفوفة[مـحرف]]، اسم_الملف: مؤشر[مصفوفة[مـحرف]]
       ) => ثـنائي؛
    
    1: func get (
         url: ptr[array[Char]], result: ptr[ptr], resultCount: ptr[Int]
       ): Bool;
    2: func get (
         url: ptr[array[Char]], filename: ptr[array[Char]]
       ): Bool;
    
    1: تجلب المورد المحدد بالرابط وترجعه.
    2: تجلب المورد المحدد بالرابط وتخزنه في الملف المحدد.
  • شفر_عنوانيا (uriEncode)
    دالة شفر_عنوانيا (مـؤشر_محارف): نـص؛
    
    func uriEncode(CharsPtr): String;
    
    تشفر النص المعطى بتشفير الURI وترجع القيمة المشفرة.
  • فك_عنوانيا (uriDecode)
    دالة فك_عنوانيا (مـؤشر_محارف): نـص؛
    
    func uriDecode(CharsPtr): String;
    
    تفك تشفير النص المعطى المشفر بتشفير الURI.

الوحدة: طـرفية (Console)

تحتوي وحدة `طـرفية` على الدالات التالية:
  • أدخل_محرفا (getChar)
    @تصدير[getchar] دالة أدخل_محرفا (): صـحيح؛
    
    @expname[getchar] func getChar (): Int;
    
    مطابقة لدالة getchar من POSIX.
  • أخرج_محرفا (putChar)
    @تصدير[putchar] دالة أخرج_محرفا (محرف: صـحيح): صـحيح؛
    
    @expname[putchar] func putChar (c: Int): Int;
    
    مطابقة لدالة putchar من POSIX.
  • اطبع (print)
    1. @تصدير[printf] دالة اطبع (نسق: مؤشر[مصفوفة[مـحرف]]، ...أيما): صـحيح؛
    2. دالة اطبع (ص: صـحيح[64])؛
    3. دالة اطبع (ع: عـائم[64])؛
    4. دالة اطبع (ع: عـائم[64]، ص: صـحيح)؛
    
    1. @expname[printf] func print (fmt: ptr[array[Char]], ...any): Int;
    2. func print (i: Int[64]);
    3. func print (f: Float[64]);
    4. func print (f: Float[64], n: Int);
    
    1: مطابقة لدالة printf من POSIX.
    2: تطبع عدداً صحيحاً.
    3: تطبع عدداً عائماً.
    4: تطبع عدداً عائماً مع تحكم بعدد الأصفار على يمين الفاصلة.
  • امسح (scan)
    @تصدير[scanf] دالة امسح (نسق: مؤشر[مصفوفة[مـحرف]]، ...أيما): صـحيح؛
    
    @expname[scanf] func scan (fmt: ptr[array[Char]], ...any): Int;
    
    مطابقة لدالة scanf من POSIX.
  • أدخل_صحيح (getInt)
    دالة أدخل_صحيح (): صـحيح؛
    
    func getInt (): Int;
    
    تطلب من المستخدم إدخال عدد صحيح.
  • أدخل_عائم (getFloat)
    دالة أدخل_عائم (): عـائم؛
    
    print getFloat (): Float;
    
    تطلب من المستخدم إدخال عدد بفاصلة عائمة.
  • أدخل_محارف (getString)
    دالة أدخل_محارف (محارف: مؤشر[مصفوفة[مـحرف]]، عدد: طـبيعي)؛
    
    func getString (str: ptr[array[Char]], size: Word);
    
    تطلب من المستخدم إدخال سلسلة محارف.
طـراز (Style)
تحتوي وحدة 'طـراز' على دالات للتحكم بطراز الكتابة في الطرفية. كل واحدة من هذه الدالات ترجع مؤشراً على مصفوفة محارف يمكن طباعتها في الطرفية للحصول على الطراز المطلوب.
  • صفر (reset)
  • لقب (bright)
  • خافت (dim)
  • مائل (italic)
  • خط_تحتي (underscore)
  • وميض (blink)
  • عكس (reverse)
  • مخفي (hidden)
  • كتابة_سوداء (fgBlack)
  • كتابة_حمراء (fgRed)
  • كتابة_خضراء (fgGreen)
  • كتابة_صفراء (fgYellow)
  • كتابة_زرقاء (fgBlue)
  • كتابة_أرجوانية (fgMagenta)
  • كتابة_سماوية (fgCyan)
  • كتابة_بيضاء (fgWhite)
  • خلفية_سوداء (bgBlack)
  • خلفية_حمراء (bgRed)
  • خلفية_خضراء (bgGreen)
  • خلفية_صفراء (bgYellow)
  • خلفية_زرقاء (bgBlue)
  • خلفية_أرجوانية (bgMagenta)
  • خلفية_سماوية (bgCyan)
  • خلفية_بيضاء (bgWhite)

الوحدة: نـظام (System)

تحتوي وحدة `نـظام` على التعريفات التالية:
  • نم (sleep)
    @تصدير[usleep] دالة نم (ط: طـبيعي)؛
    
    @expname[usleep] func sleep (w: Word);
    
    مطابقة لدالة usleep من POSIX.
  • اضبط_متغير_محيطي (setEnv)
    @تصدير[setenv]
    دالة اضبط_متغير_محيطي (
        اسم: مؤشر[مصفوفة[مـحرف]]، قيمة: مؤشر[مصفوفة[مـحرف]]، استبدال: صـحيح
    ): صـحيح؛
    
    @expname[setenv]
    func setEnv (
        name: ptr[array[Char]], value: ptr[array[Char]], overwrite: Int
    ): Int;
    
    مطابقة لدالة setenv من POSIX.
  • هات_متغير_محيطي (getEnv)
    @تصدير[getenv]
    دالة هات_متغير_محيطي (اسم: مؤشر[مصفوفة[مـحرف]]): مؤشر[مصفوفة[مـحرف]]؛
    
    @expname[getenv]
    func getEnv (name: ptr[array[Char]]): ptr[array[Char]];
    
    مطابقة لدالة getenv من POSIX.
  • شغل (exec)
    @تصدير[system] دالة شغل (أمر: مؤشر[مصفوفة[مـحرف]]): صـحيح؛
    
    @expname[system] func exec (cmd: ptr[array[Char]]): Int;
    
    مطابقة لدالة system من POSIX.
  • اخرج (exit)
    @تصدير[exit] دالة اخرج (رمز_الخروج: صـحيح)؛
    
    @expname[exit] func exit (status: Int);
    
    مطابقة لدالة exit من POSIX.

الوحدة: نـم (Fs)

تحتوي وحدة `نـم` على الدالات والعناصر التالية للتعامل مع نظام الملفات:
  • قـيد_مجلد (DirEnt)
    صنف قـيد_مجلد {
      عرف نوع: صـحيح[8]؛
      عرف اسم: مصفوفة[مـحرف، 256]؛
    }
    
    class DirEnt {
      def dType: Int[8];
      def dName: array[Char, FILENAME_LENGTH];
    };
    
    سجل معلومات عنصر من عناصر المجلد.

  • اسـماء_ملفات (FileNames؛)
    صنف اسـماء_ملفات {
      عرف عدد: صـحيح؛
      عرف اسماء: مصفوفة[مصفوفة[مـحرف، 256]]؛
    }
    
    class FileNames {
      def count: Int;
      def names: array[array[Char, FILENAME_LENGTH]];
    }
    
    قائمة بأسماء ملفات.

  • انـتقال (Seek)
    عرف انـتقال: {
      عرف _بداية_: لقب 0؛
      عرف _حالي_: لقب 1؛
      عرف _نهاية_: لقب 2؛
    }؛
    
    def Seek: {
      def SET: 0;
      def CUR: 1;
      def END: 2;
    };
    
    ثوابت التعامل مع دالة الانتقال.

  • يوجد (exists)
    دالة يوجد (اسم_الملف: مؤشر[مصفوفة[مـحرف]]): ثـنائي؛
    
    func exists (filename: ptr[array[Char]]): Bool;
    
    تفحص وجود ملف أو مجلد معين.
  • اعد_التسمية (rename)
    @تصدير[rename]
    دالة أعد_التسمية (
        الاسم_القديم: مؤشر[مصفوفة[مـحرف]]، الاسم_الجديد: مؤشر[مصفوفة[مـحرف]]
    ): صـحيح؛
    
    @expname[rename]
    func rename (oldName: ptr[array[Char]], newName: ptr[array[Char]]): Int;
    
    تعيد تسمية ملف أو مجلد.
  • امح (remove)
    @تصدير[remove] دالة امح (اسم_الملف: مؤشر[مصفوفة[مـحرف]]): ثـنائي؛
    
    @expname[remove] func remove (filename: ptr[array[Char]]): Bool;
    
    تزيل ملفًا أو مجلدًا.
  • افتح_ملف (openFile)
    @تصدير[fopen]
    دالة افتح_ملف (
        اسم_الملف: مؤشر[مصفوفة[مـحرف]]، الوضع: مؤشر[مصفوفة[مـحرف]]
    ): مؤشر[مـلف]؛
    
    @expname[fopen]
    func openFile (filename: ptr[array[Char]], mode: ptr[array[Char]]): ptr[File];
    
    مطابقة لدالة fopen من POSIX.
  • اغلق_ملف (closeFile)
    @تصدير[fclose] دالة اغلق_ملف (ملف: مؤشر[مـلف]): صـحيح؛
    
    @expname[fclose] func closeFile(f: ptr[File]): Int;
    
    مطابقة لدالة fclose من POSIX.
  • اطبع (print)
    @تصدير[frpintf]
    دالة اطبع (ملف: مؤشر[مـلف]، نسق: مؤشر[مصفوفة[مـحرف]]، ...أيما): صـحيح؛
    
    @expname[fprintf]
    func print (f: ptr[File], fmt: ptr[array[Char]], ...any): Int;
    
    مطابقة لدالة fprintf من POSIX.
  • امسح (scan)
    @تصدير[fscanf]
    دالة امسح (ملف: مؤشر[مـلف]، نسق: مؤشر[مصفوفة[مـحرف]]، ...أيما): صـحيح؛
    
    @expname[scanf]
    func scan (f: ptr[File], fmt: ptr[array[Char]], ...any): Int;
    
    مطابقة لدالة fscanf من POSIX.
  • اكتب (write)
    @تصدير[fwrite]
    دالة اكتب (
        محتوى: مؤشر، حجم: صـحيح_متكيف، عدد: صـحيح_متكيف، ملف: مؤشر[مـلف]
    ): صـحيح_متكيف؛
    
    @expname[fwrite]
    func write (
        content: ptr, size: ArchInt, count: ArchInt, f: ptr[File]
    ): ArchInt;
    
    مطابقة لدالة fwrite من POSIX.
  • اقرأ (read)
    @تصدير[fread]
    دالة اقرأ (
        محتوى: مؤشر، حجم: صـحيح_متكيف، عدد: صـحيح_متكيف، ملف: مؤشر[مـلف]
    ): صـحيح_متكيف؛
    
    @expname[fread]
    func read (
        content: ptr, size: ArchInt, count: ArchInt, f: ptr[File]
    ): ArchInt;
    
    مطابقة لدالة fread من POSIX.
  • اطلق (flush)
    @تصدير[fflush] دالة اطلق (ملف: مؤشر[مـلف]): صـحيح؛
    
    @expname[fflush] func flush (f: ptr[File]): Int;
    
    مطابقة لدالة fflush من POSIX.
  • هات_الموقع (tell)
    @تصدير[ftell] دالة هات_الموقع (ملف: مؤشر[مـلف]): صـحيح_متكيف؛
    
    @expname[ftell] func tell (f: ptr[File]): ArchInt;
    
    مطابقة لدالة tell من POSIX.
  • انتقل (seek)
    @تصدير[fseek]
    دالة انتقل (ملف: مؤشر[مـلف]، إزاحة: صـحيح_متكيف، انتقال: صـحيح): صـحيح؛
    
    @expname[fseek]
    func seek (f: ptr[File], offset: ArchInt, seek: Int): Int;
    
    مطابقة لدالة tell من POSIX.
  • أنشئ_ملف (createFile)
    دالة أنشئ_ملف (
        اسم_الملف: مؤشر[مصفوفة[مـحرف]]، محتوى: مؤشر، حجم_المحتوى: صـحيح_متكيف
    ): ثـنائي؛
    
    func createFile (
        filename: ptr[array[Char]], content: ptr, contentSize: ArchInt
    ): Bool;
    
    تنشئ ملفًا وتخزن فيه المحتوى المعطى.
  • اقرأ_ملف (readFile)
    دالة اقرأ_ملف (
        اسم_الملف: مؤشر[مصفوفة[مـحرف]]، ناتج: مؤشر[مؤشر]، حجم: مؤشر[صـحيح_متكيف]
    ): ثـنائي؛
    
    func readFile (
        filename: ptr[array[Char]], result: ptr[ptr], size: ptr[ArchInt]
    ): Bool;
    
    تقرأ المحتوى الكامل لملف وترجعه.
  • انشئ_مجلد (makeDir)
    دالة أنشئ_مجلد (اسم_المجلد: مؤشر[مصفوفة[مـحرف]]، الوضع: صـحيح): ثـنائي؛
    
    func makeDir (folderName: ptr[array[Char]], mode: Int): Bool;
    
    تنشئ مجلدًا جديدًا.
  • افتح_مجلد (openDir)
    @تصدير[opendir] دالة (اسم_المجلد: مؤشر[مصفوفة[مـحرف]]): مؤشر[مـجلد]؛
    
    @expname[opendir] func (folderName: ptr[array[Char]]): ptr[Dir];
    
    مطابقة لدالة opendir من POSIX.
  • اغلق_مجلد (closeDir)
    @تصدير[closedir] دالة (مجلد: مؤشر[مـجلد]): صـحيح؛
    
    @expname[closedir] func (folder: ptr[Dir]): Int;
    
    طابقة لدالة closedir من POSIX.
  • صفر_مؤشر_مجلد (rewindDir)
    @تصدير[rewindDir] دالة صفر_مؤشر_مجلد (مجلد: مؤشر[مـجلد])؛
    
    @expname[rewindDir] func rewindDir (dir: ptr[Dir]);
    
    مطابقة لدالة rewinddir من POSIX.
  • اقرأ_مجلد (readDir)
    1. @تصدير[readdir] دالة اقرأ_مجلد (مجلد: مؤشر[مـجلد]): مؤشر[قـيد_مجلد]؛
    2. دالة اقرأ_مجلد (اسم_المجلد: مؤشر[مصفوفة[مـحرف]]): مؤشر[أسـماء_ملفات]؛
    
    1. @expname[readdir] func readDir (dir: ptr[Dir]): ptr[DirEnt];
    2. func readDir (name: ptr[array[Char]]): ptr[FileNames];
    
    1: مطابقة لدالة readdir من POSIX.
    2: ترجع قائمة بأسماء الملفات في مجلد معين.

الوحدة: نـمط (Regex)

تحتوي وحدة `نـمط` على دالات للتعامل مع التعابير النمطية.
  • طابق (match)
    دالة طابق (
        نمط: مؤشر[مصفوفة[مـحرف]]، محارف: مؤشر[مصفوفة[مـحرف]]، خيارات: صـحيح
    ): مـصفوفة[نـص]؛
    
    func match (
        pattern: ptr[array[Char]], str: ptr[array[Char]], flags: Int
    ): Array[String];
    
    تطبق النمط المعطى على سلسلة المحارف المعطاة وترجع مصفوفة من النصوص. في حالة وجود تطابق تحمل المصفوفة التطابق الكامل للنمط في أول عنصر من المصفوفة بينما تحمل العناصر التالية التطابقات الجزئية المحددة ضمن النمط بالأقواس. في حالة عدم وجود تطابق تكون النتيجة مصفوفة فارغة.
  • مـطابق (Matcher)
    صـنف مـطابق (
        عملية هذا~هيئ(نمط: مؤشر[مصفوفة[مـحرف]])؛
        عملية هذا~هيئ(نمط: مؤشر[مصفوفة[مـحرف]]، خيارات: صـحيح)؛
        عملية هذا.هيئ(نمط: مؤشر[مصفوفة[مـحرف]])؛
        عملية هذا.هيئ(نمط: مؤشر[مصفوفة[مـحرف]]، خيارات: صـحيح)؛
        عملية هذا.حرر()؛
        عملية هذا.طابق(محارف: مؤشر[مصفوفة[مـحرف]]): مـصفوفة[نـص]؛
    }
    
    class Matcher {
        handler this~init(pattern: ptr[array[Char]]);
        handler this~init(pattern: ptr[array[Char]], flags: Int);
        handler this.initialize(pattern: ptr[array[Char]]);
        handler this.initialize(pattern: ptr[array[Char]], flags: Int);
        handler this.release();
        handler this.match (str: ptr[array[Char]]): Array[String];
    }
    
    صنف يمكن المستخدم من تهيئة تعبير نمطي ثم استخدامه في عمليات بحث متعددة. الوظيفة `طابق` (match) تطبق التعبير النمطي على سلسلة المحارف المعطاة وترجع مصفوفة من النصوص. في حالة وجود تطابق تحمل المصفوفة التطابق الكامل للنمط في أول عنصر من المصفوفة بينما تحمل العناصر التالية التطابقات الجزئية المحددة ضمن النمط بالأقواس. في حالة عدم وجود تطابق تكون النتيجة مصفوفة فارغة.

الوحدة: وقـت (Time)

تحتوي وحدة `وقـت` على التعريفات التالية:
  • وقـت (Time)
    صنف وقـت_مفصل {
      عرف ثانية: صـحيح؛
      عرف دقيقة: صـحيح؛
      عرف ساعة: صـحيح؛
      عرف يوم: صـحيح؛
      عرف شهر: صـحيح؛
      عرف سنة: صـحيح؛
      عرف يوم_اسبوعي: صـحيح؛
      عرف يوم_سنوي: صـحيح؛
      عرف إزاحة_زمنية: صـحيح؛
      عرف منطقة_زمنية: صـحيح؛
    }؛
    
    class DetailedTime {
      def second: Int;
      def minute: Int;
      def hour: Int;
      def day: Int;
      def month: Int;
      def year: Int;
      def weekDay: Int;
      def yearDay: Int;
      def daylightSaving: Int;
      def timezoneOffset: Int[64];
      def timezone: ptr[array[Char]];
    };
    
    سجل لحمل معلومات الوقت والتاريخ.
  • هات_وقـت_مفصل (getDetailedTime)
    1. @تصدير[localtime] دالة هات_وقـت_مفصل (
         خز: مؤشر[طـبيعي[64]]
       ): مؤشر[وقـت_مفصل]؛
    2. @تصدير[localtime_r] دالة هات_وقت_مفصل (
         خز: مؤشر[طـبيعي[64]]، مؤشر[وقـت_مفصل]
       ): مؤشر[وقـت_مفصل]؛
    
    1. @expname[localtime] func getDetailedTime (
         ts: ptr[Word[64]]
       ): ptr[DetailedTime];
    2. @expname[localtime_r] func getDetailedTime (
         ts: ptr[Word[64]], ptr[DetailedTime]
       ): ptr[DetailedTime];
    
    1. مطابقة لدالة localtime من POSIX.
    2. مطابقة لدالة localtime_r من POSIX.
  • هات_الختم_الزمني (getTimestamp)
    @تصدير[time] دالة هات_الختم_الزمني (نتيجة: مؤشر[طـبيعي[64]]): مؤشر[طـبيعي[64]]؛
    
    @expname[time] func getTimestamp (result: ptr[Word[64]]): ptr[Word[64]];
    
    مطابقة لدالة time من POSIX.
  • هات_الساعة (getClock)
    @تصدير[clock] دالة هات_الساعة (): صـحيح[64]؛
    
    @expname[clock] func getClock (): Int[64];
    
    مطابقة لدالة clock من POSIX.
  • إلى_نص (toString)
    @تصدير[clock] دالة إلى_نص (خز: مؤشر[طـبيعي[64]]): مؤشر[مصفوفة[مـحرف]]؛
    
    @expname[clock] func toString (ts: ptr[Word[64]]): ptr[array[Char]];
    
    مطابقة لدالة ctime من POSIX.

تعريفات أخرى

  • مثل_سند (castRef)
    ماكرو لتسهيل تمثيل سند كسند لصنف مختلف. يستلم معطيين، الأول هو المتغير المراد تمثيله، والثاني هو الصنف المراد التمثيل إلى سنده.

  • سند_لعدم (nullRef)
    ماكرو يعطيك سندًا قيمة مؤشره 0. يأخذ معطىً واحدًا هو الصنف المراد الحصول على سنده.

  • هات_المسار_الكامل_لهذه_الشفرة (getThisSourceFullPath)
    ماكرو يعطيك سلسلة محارف حرفية (string literal) تحتوي على المسار الكامل لملف الشفرة المصدرية الحالي. لا يأخذ هذا الماكرو أي معطيات.

  • هات_مجلد_هذه_الشفرة (getThisSourceDirectory)
    ماكرو يعطيك سلسلة محارف حرفية (string literal) تحتوي على المسار الكامل للمجلد الذي يحتوي ملف الشفرة المصدرية الحالي. لا يأخذ هذا الماكرو أي معطيات.

دليل مكتبة `مغلفة` (closure)


مكتبة `مغلفة` توفر الدعم للدالات المُغلَّفة، وهي الدالات التي تُرفق بنسخة من البيئة التي تُغلفها، أي بنسخة من المتغيرات الخارجية التي تستخدمها الدالة.

يمكن للدالات الضمنية الولوج إلى المتغيرات العمومية خارجها، لكن لا يمكنها الولوج إلى المتغيرات المحلية ضمن دالة خارجية تحوي الدالة الضمنية، وذلك لأن الدالة الخارجية قد ينتهي تنفيذها وتُزال متغيراتها من الذاكرة قبل استدعاء الدالة الضمنية. على سبيل المثال:
عرف مد: مؤشر[دالة]؛
دالة جهز_دالة {
    عرف ع: صحيح = 10؛
    مد = دالة {
        طـرفية.اطبع("%d\ج"، ع)؛ // خطأ: في الوقت الذي يُنفذ فيه هذا السطر
            // يكون ع قد أزيل من الذاكرة
    }؛
}

جهز_دالة()؛
مد()؛
def pf: ptr[func];
func prepareFunc {
    def i: Int = 10;
    pf = func {
        Console.print("%d\n", i); // Error: by the time this line is executed
            // i would have been removed from memory
    };
}

prepareFunc();
pf();
لتمكين الدالة من الولوج إلى متغيرات الدالة الخارجية تحتاج هذه الدالة أن تُرفق بنسخة من البيانات التي تستخدمها من البيئة الخارجية، وهذا ما توفره الدالات المُغلَّفة التي توفرها مكتبة `مغلفة` (clsoure)، فهي دالات يغلفها المترجم تلقائيًا بالبيئة الخارجية، أي يُرفقها بنسخة من كل متغير خارجي مؤقت تستخدمه الدالة المغلفة. تعريف الدالة المغلفة يشبه تعريف الدالة الضمنية باستثناء استخدام الكلمة المفتاحية `مغلفة` (closure) بدل `دالة`. مثال:
اشمل "مغلفة"؛

عرف مغ: مغلفة ()؛
دالة جهز_مغلفة {
    عرف ع: صحيح = 10؛
    مغ = مغلفة () {
        طـرفية.اطبع("%d\ج"، ع)؛ // صحيح: سيبدل المترجم هذا الولوج تلقائيًا
            // إلى ولوج إلى نسخة من ع.
    }؛
}

جهز_مغلفة()؛
مغ()؛
import "closure";

def pc: closure ();
func prepareClosure {
    def i: Int = 10;
    pf = closure () {
        Console.print("%d\n", i); // Correct: access to i will be replaced
            // by the compiler to an access to a copy of i
    };
}

prepareClosure();
pc();
من الملاحظ أعلاه أن كتابة مغلفة دون متن يجعلها تعريفًا لمغلفة، ومن المهم معرفته أن قيد المغلفة يحتوي على مؤشر إلى دالة، بالإضافة إلى سند مشترك إلى قيد البيانات. تبقى المسؤولية على المبرمج لمراعاة عدم الولوج إلى سندات مشتركة تؤدي إلى حلقة مغلقة من السندات المشتركة، وبالتالي تسريب في الذاكرة. على سبيل المثال، إن ولجت من المغلفة إلى سند مشترك وكان هذا السند المشترك يؤشر للقيد الذي يحتوي المغلفة فسينتهي بك الأمر إلى تسرب في الذاكرة (القيد يمسك بالمغلفة والتي بدورها تمسك بالقيد فيبقى كلاهما في الذاكرة دائمًا). في مثل هذه الحالات كل ما تحتاج فعله أن تجعل المغلفة تمسك بسند غير مشترك لتجنب تسريب الذاكرة. مثال:
اشمل "مغلفة"؛

صنف قـيد {
    عرف مغ: مغلفة ()؛
    عرف ص: صحيح؛
}

عرف ق1: سـندنا[قـيد]؛
ق1.أنشئ()؛
ق1.ص = 10؛
ق1.مغ = مغلفة () {
    طـرفية.اطبع("%d\ج"، ق1.ص)؛
}؛
ق1.حرر()؛ // لن يُحرر هنا ق1 ولا المغلفة التي يملكها.

عرف ق2: سـندنا[قـيد]؛
ق2.أنشئ()؛
ق2.ص = 10؛
عرف ق22: سـندهم[قـيد] = ق2؛
ق2.مغ = مغلفة () {
    طـرفية.اطبع("%d\ج"، ق22.ص)؛
}}
ق2.حرر()؛ // هنا سيحرر ق2 مع المغلفة التي يملكها.
import "closure";

class Record {
    def c: closure ();
    def i: Int;
}

def r1: SrdRef[Record];
r1.construct();
r1.i = 10;
r1.c = closure() {
    Console.print("%d\n", r1.i);
};
r1.release(); // r1 will not be released and neither will the closure it owns.

def r2: SrdRef[Record];
r2.construct();
r2.i = 10;
def r22: WkRef[Record] = r2;
r2.c = closure() {
    Console.print("%d\n", r22.i);
};
r2.release(); // r2 will be released along with the closure it owns.
يمكن للمغلفة أن تستلم قيمًا وترجع قيمًا كما هو الحال مع الدالات:
اشمل "مغلفة"؛

عرف مغ: مغلفة (عائم): صحيح؛
دالة جهز_مغلفة {
    عرف ع: صحيح = 10؛
    مغ = مغلفة (ن: عائم): صحيح {
        أرجع ع * ن؛
    }؛
}

جهز_مغلفة()؛
طـرفية.اطبع("%d\ج"، مغ(3.5))؛ // سيطبع 35
import "closure";

def pc: closure (Float): Int;
func prepareClosure {
    def i: Int = 10;
    pf = closure (j: Float): Int {
        return i * j;
    };
}

prepareClosure();
Console.print("%d\n", pc(3.5)); // Prints 35

أسلوب التقاط البيانات المحيطة

يمكنك تحديد الأسلوب الذي تُلتقط فيه البيانات من محيط الدالة المغلفة، ويمكنك تحديد ذلك لكل متغير على حدة. على سبيل المثال إذا أردت قراءة قيمة من محيد الدالة لكنك لا تحتاج لتغييرها داخل المغلفة فقد يكفيك التقاط نسخة من ذلك المتغير، بينما إذا أردت تغيير قيمة المتغير داخل الدالة المغلفة فستحتاج لالتقاط سند إلى المتغير بدلاً من ذلك. للتحكم بأسلوب التقاط البيانات نتبع الصيغة التالية في تعريف المغلفة:
مغلفة (/*تعريفات_اسلوب_الالتقاط*/)&(/*تعريفات_المدخلات*/): /*صنف_الإرجاع*/ {
  // متن المغلفة
}
closure (/*capture_mode_defs*/)&(/*args_defs*/): /*ret_type*/ {
  // closure body
}
في المثال التالي نحدد أسلوب الالتقاط للمتغير `ن` (n) بـ `كسند` (by_ref) وذلك يخبر يجعل المغلفة تحتفظ بسند للمتغير بدل الاحتفاظ بنسخة، وبالتالي فإن تغير قيمة المتغير داخل المغلفة سيؤدي لتغيير المنغير الأصلي خارج المغلفة.
دالة اختبر_التقط_كسند (ن: صحيح) {
    عرف م: مغلفة (ع: صحيح): صحيح؛
    م = مغلفة (ن: كسند)&(ع: صحيح): صحيح {
        أرجع ع * ن++؛
    }
    اطبع("ن قبل استدعاء المغلفة: %d\ج"، ن)؛
    اطبع("نتيجة المغلفة: %d\ج"، م(3))؛
    اطبع("ن بعد استدعاء المغلفة: %d\ج"، ن)؛
}
اختبر_التقط_كسند(5)؛
/*
النتيجة:
ن قبل استدعاء المغلفة: 5
نتيجة المغلفة: 15
ن بعد استدعاء المغلفة: 6
*/
func testCaptureByRef (n: Int) {
    def c: closure (i: Int): Int;
    c = closure (n: by_ref)&(i: Int): Int {
        return i * n++;
    };
    print("n before calling c: %d\n", n);
    print("closure result: %d\n", c(3));
    print("n after calling c: %d\n", n);
}
testCaptureByRef(5);
/*
output:
n before calling c: 5
closure result: 15
n after calling c: 6
*/

في هذا المثال لو غيرنا أسلوب التقاط ن من `كسند` إلى `كقيمة` لكانت القيمة المطبوعة بعد استعداء المغلفة 5 بدلاً من 6.

تتوفر الأنماط التالية لالتقاط البيانات:
  • كسند (by_ref): تلتقط المغلفة سندًا على المتغير. إذا كان المتغير سندًا فإن المغلفة ستلتقط ذلك السند وليس سندا إلى السند.
  • كقيمة (by_val): تلتقط المغلفة قيمة المتغير. إذا كان المتغير المذكور سندا فإن الدالة ستلتقط القيمة التي يشير إليها السند وليس السند نفسه.
  • مطابق (identical): تلتقط المغلفة المتغير حرفيًا، فإذا كان المتغير سندا فتلتقط ذلك السند وإذا كان قيمة فتلتقط تلك القيمة..
  • تلقائي: إذا لم تحدد نمط الالتقاط يدويا فإن النمط المعتمد هو التلقائي وفي هذا النمط يحدد المترجم أسلوب الالتقاط اعتمادًا على صنف المتغير، فإن كان الصنف من أصناف المستخدم وليس صنف `سـندنا` (SrdRef) فيستخدم الأسلوب `مطابق` وإلا (أي إذا كان `سـندنا` أو صنفًا أساسيًا) فيستخدم الأسلوب `كقيمة`.
يمكن التحقق فيما إن كان مؤشر المغلفة صفرا أم لا باستخدام الدالة `أهو_عدم` (isNull).
    عرف م: مغلفة (ع: صحيح): صحيح؛
    م.أهو_عدم() // يرجع 1
    م = مغلفة (ع: صحيح): صحيح { أرجع 0؛ }؛
    م.أهو_عدم() // يرجع 0
    def c: closure (i: Int): Int;
    c.isNull() // returns true
    c = closure (i: Int): Int { return 0 };
    c.isNull() // returns false

دليل مكتبة `بـناء` (Build)


مكتبة `بـناء` تمكن المستخدم من بناء ملف تنفيذي لبرنامجه. تحتوي المكتبة على العناصر التالية:

الصنف: تـنفيذي (Exe)

يمكّن المستخدم من بناء ملف تنفيذي لبرنامجه يعمل على نظام التشغيل الحالي. يحتاج هذا الصنف لتوفر أدوات gcc على نظام التشغيل. بناء ملف تنفيذي يتم بالخطوات التالي:
  • إنشاء كائن من صنف `تـنفيذي` (Exe) وإعطائه مؤشرًا على عنصر الشفرة المصدرية المراد تحويله إلى ملف تنفيذي بالإضافة إلى اسم الملف التنفيذي المراد بناؤه. يمكن الحصول على مؤشر العنصر باستخدام الأمر `~شبم` (~ast).
  • إضافة أي اعتماديات باستخدام الدالة `تـنفيذي.اضف_اعتمادية` (addDependency) وإعطائها مؤشرا على الوحدة التي يعتمد عليها البرنامج. لاحظ أن إضافة الاعتمادية مطلوب فقط في حالة احتياج الوحدة إلى مكتبات خارجية (تحدد الوحدة ما تحتاجه من مكتبات خارجية باستخدام المبدل `@اعتماديات` (@deps))، أما لو لم تحتج الوحدة لمكتبات خارجية فلا حاجة لإضافتها كإعتمادية بشكل يدوي وإنما يفعل المترجم ذلك تلقائيا.
    يمكن أيضًا إعطاء الدالة إسم ملف الاعتمادية بدل إعطائها مؤشرا على وحدة، ويمكن في حالة استخدام أسماء ملفات للاعتماديات استخدام الدالة `أضف_اعتماديات` (addDependencies) لتمرير عدة اعتماديات مرة واحدة.
  • إضافة أي خيارات إضافية يحتاجها المُجمِّع (linker) باستخدام الدالة `أضف_خيار` (addFlag) أو الدالة `أضف_خيارات` (addFlags).
  • إنشاء الملف التنفيذي باستدعاء الدالة `تـنفيذي.أنتج` (generate).
المثال التالي يوضح هذه الخطوات:
  عرف تنفيذي: مؤشر[بـناء.تـنفيذي](الـبسملة.ابدأ~شبم، "البسملة")؛
  تنفيذي.أضف_اعتمادية(جـتك~شبم)؛ // أو: تنفيذي.أضف_اعتمادية(نـص("libgtk..."))؛
  تنفيذي.أضف_اعتماديات(مـصفوفة[نـص]({ نـص("libcurl.so")، ... }))؛
  تنفيذي.أضف_خيار("-Wl,-rpath,@executable_path")؛
  إذا تنفيذي.أنتج() {
    مـتم.طـرفية.اطبع("اكتمل البناء.\ج")؛
  } وإلا {
    مـتم.طـرفية.اطبع("فشل البناء.\ج")؛
  }؛
  def exe: ptr[Build.Exe](WidgetGuide.start~ast, "hello_world");
  exe.addDependency(Gtk~ast); // or exe.addDependency(String("libgtk...."));
  exe.addDependencies(Array[String]({ String("libcurl.so"), ... }));
  exe.addFlag("-Wl,-rpath,@executable_path");
  if exe.generate() {
    Srl.Console.print("Build complete.\n");
  } else {
    Srl.Console.print("Build failed.\n");
  };
الشفرة التالية توضح كيف يمكن لمطوري المكتبات إضافة معلومات الاعتماديات الخارجية إلى وحداتهم:
  @اعتماديات["libmyextlib.so"] وحدة مـكتبتي {
    ...
  }؛
  @deps["libmyextlib.so"] module MyLib {
    ...
  };
بدون إضافة المبدل `@اعتماديات` فإن الدالة `أضف_اعتمادية` لا تفعل شيئا.

الصنف: ويـب_أسمبلي (Wasm)

هذا الصنف مشابه لصنف `تـنفيذي` ويستخدم بنفس الطريقة لكنه يولد شفرة ويب أسيمبلي بدل شفرة تستهدف نظام التشغيل ومعمارية الجهاز الحالي. مثال:
  عرف ويب_أسمبلي: مؤشر[بـناء.ويـب_أسمبلي](الـبسملة.ابدأ~شبم، "البسملة")؛
  ويب_أسمبلي.أضف_اعتمادية(نـص("stdlib.wasm"))؛
  ويب_أسمبلي.أضف_خيارات({ نـص("--export=malloc"), نـص("--export=realloc") });
  إذا ويب_أسمبلي.أنتج() {
    مـتم.طـرفية.اطبع("اكتمل البناء.\ج")؛
  } وإلا {
    مـتم.طـرفية.اطبع("فشل البناء.\ج")؛
  }؛
  def wasm: ptr[Build.Wasm](HelloWorld.start~ast, "hello_world");
  wasm.addDependency(String("stdlib.wasm"));
  wasm.addFlags({ String("--export=malloc"), String("--export=realloc") });
  if wasm.generate() {
    Srl.Console.print("Build complete.\n");
  } else {
    Srl.Console.print("Build failed.\n");
  };

الدالة: أنشئ_تنفيذي (genExeceutable)

دالة مساعدة لإنشاء ملف تنفيذي في خطوة واحدة. تنفع هذه الدالة فقط في حالة عدم احتياج عملية البناء لأي اعتماديات أو خيارات إضافية. هذه الدالة مجرد وسيط للصنف `تـنفيذي` (Exe)، فهي داخليا تستخدم الصنف `تـنفيذي` لإنجاز العمل.
  بـناء.أنشئ_تنفيذي(ابدأ~شبم، "بسملة")؛
  Build.genExecutable(start~ast, "hello_world");

الدالة: أنشئ_ويب_أسمبلي (genWasm)

دالة مساعدة لإنشاء ملف ويب أسمبلي في خطوة واحدة. تنفع هذه الدالة فقط في حالة عدم احتياج عملية البناء لأي اعتماديات أو خيارات إضافية. هذه الدالة مجرد وسيط للصنف `ويـب_أسمبلي` (Wasm)، فهي داخليا تستخدم الصنف `ويـب_أسمبلي` لإنجاز العمل.
  بـناء.أنشئ_ويب_أسمبلي(ابدأ~شبم، "بسملة")؛
  Build.genWasm(start~ast, "hello_world");

دليل مكتبة `ضـغط` (Zip)


تحتوي وحدة `ضـغط` على الدالات التالية:
  • استخرج_من_ملف (extractFromFile)
    دالة استخرج_من_ملف (
      اسم_الملف: مؤشر[مصفوفة[مـحرف]]، اسم_المجلد: مؤشر[مصفوفة[مـحرف]]،
      مستلم_الاشعارات: مؤشر[دالة (مؤشر[مصفوفة[مـحرف]]، مؤشر) => صـحيح]، معطيات: مؤشر
    ) => صـحيح؛
    
    func extractFromFile (
        filename: ptr[array[Char]], folderName: ptr[array[Char]],
        callback: ptr[func (ptr[array[Char]], ptr): Int], arguments: ptr
    ): Int;
    
    تستخرج ملفًا مضغوطا إلى المجلد المحدد.
  • اضغط_إلى_ملف (compressToFile)
    دالة اضغط_إلى_ملف (
      اسم_المف: مؤشر[مصفوفة[مـحرف]]، ملفات: مؤشر[مصفوفة[مؤشر[مصفوفة[مـحرف]]]]، عدد_الملفات: صـحيح،
      نوع_الاستخراج: مؤشر[مصفوفة[مـحرف]]
    ) => صـحيح؛
    
    func compressToFile (
        filename: ptr[array[Char]], files: ptr[array[ptr[array[Char]]]], fileCount: Int,
        extractType: ptr[array[Char]]
    ): Int;
    
    تنشئ ملفًا مضغوطا يحتوي على الملفات المعطاة.

دليل مدير الحزم


مدير حزم الأسس (محا أو apm) ينزل الحزم مباشرة من موقع GitHub ويمكن استخدامه عبر سطر الأوامر أو من داخل البرنامج مباشرة.
للحصول على تعليمات استخدام مدير الحزم من سطر الأوامر اكتب الأمر التالي:
$ محا مساعدة
$ apm help
أما استخدام مدير الحزم من داخل البرنامج فيتم باستخدام دالة `اشمل_ملف` (importFile).
اشمل "مـحا.أسس"؛
مـحا.اشمل_ملف("<الناشر>/<اسم الحزمة>" [، "<اسم الملف>"])؛
مـحا.اشمل_ملف("<الناشر>/<اسم الحزمة>"، { "<اسم الملف 1>"، "<اسم الملف 2>"، ... })؛
import "Apm.alusus";
Apm.importFile("<author>/<pkg name>" [, "<filename>"]);
Apm.importFile("<author>/<pkg name>", { "<filename1>", "<filename2>", ... });
الصيغة الثانية من الدالة تمكن المستخدم من شمول عدة ملفات من الحزمة دفعة واحدة. استخدام الصيغة الثانية لشمول عدة ملفات أسرع من استدعاء الصيغة الأولى عدة مرات، لأن كل استدعاء لهذه الدالة يؤدي إلى قراءة بيانات من موقع GitHub.
. أثناء تطوير الحزم غالبا ما يحتاج المطور لتجربة الحزمة محليًا قبل دفع التعديلات إلى المستودع. يمكن للمستخدم استخدام أمر الربط لربط حزمة معينة مع مجلد محلي فيقوم عندها مدير الحزم باستخدام النسخة المحلية بدل تنزيل نسخة المستودع. أمر الربط يجب أن يُنفذ داخل مجلد المشروع الذي يستخدم الحزمة ويكون بهذه الصيغة:
$ cd <example_project_folder>
$ apm link <author>/<package_name>@<release> <path_to_local_package_copy>
يمكن إزالة الرابط باستخدام الأمر `افصل` وبهذه الصيغة:
$ cd <example_project_folder>
$ apm unlink <author>/<package_name>@<release>

دليل الوحدة `الـقلب` (Core)


تحوي الوحدة `الـقلب` على التعريفات التي تتيح للمبرمج التعامل مع القلب بشكل مباشر داخل برنامجه أو مكتبته. هذه الوحدة تحوي تعريفات لبعض الأصناف والدالات التي يستخدمها القلب أثناء معالجة الملفات المصدرية وبالتالي تتيح للمبرمج التعامل المباشر مع القلب ومع البيانات التي ينشئها. ليس كل ما في الـقلب موجود ضمن تعريفات هذه الوحدة، فبعض الأصناف معرفة فقط ضمن شفرة السي++ التي كُتب بها القلب وهي داخلية لا يحتاج المبرمج التعامل معها من داخل شفرة الأسس.

الدالة: اشمل_ملف (importFile)

دالة اشمل_ملف (اسم_الملف: مؤشر[مصفوفة[مـحرف]])؛
func importFile (filename: ptr[array[Char]]);
تشمل الملف المعطى اسمه. هذه الدالة تعمل عمل الإيعاز `اشمل` (import) ولا تختلف عن ذلك الإيعاز سوى بقدرتها على شمول الملفات بشكل ديناميكي، أي باستخدام اسم ملف مولّد ديناميكيًا أثناء التنفيذ.

الدالة: أضف_ترجمة (addLocalization)

دالة أضف_ترجمة (
    رمز_اللغة: مؤشر[مصفوفة[مـحرف]]،
    المفتاح: مؤشر[مصفوفة[مـحرف]]،
    القيمة: مؤشر[مصفوفة[مـحرف]]
)؛
func addLocalization (
    locale: ptr[array[Char]],
    key: ptr[array[Char]],
    value: ptr[array[Char]]
);
تضيف ترجمة إلى قائمة الترجمات للغة معينة. إن لم توجد مدخلة مسبقًا للمفتاح المطلوب فإن الترجمة ستضاف حتى لو كانت اللغة الحالية مختلفة عن لغة الترجمة المقدمة والسبب في ذلك أن وجود النص بلغة مغايرة خير من عدم وجود نص على الإطلاق. أما إن وجدت مدخلة بهذا المفتاح فإن الترجمة ستُضاف فقط إذا طابقت لغة الترجمة لغة النظام الحالية.
تستخدم هذه الدالة لإضافة نصوص لإشعارات الأخطاء المخصصة، وتكون قيمة مفتاح الترجمة مساوية لرمز الخطأ.

هوية الأصناف

في الوحدة القـلب.أسـاسيات (Core.Basic) يوجد تعريفات لتمكين الأصناف من توفير معلومات عن هوية الصنف بشكل ديناميكي (run time type info). أغلب الأصناف المستخدمة في القلب ومكتبة نمط البناء المعياري تحمل معها معلومات الهوية. فيما يلي التعريفات التي توفر معلومات هوية الأصناف:
الصنف: مـصنع_كائن_بهوية (TiObjectFactory)
معرف داخل الوحدة الـقلب.أسـاسيات (Core.Basic).
هذا الصنف يستخدم لتمكين إنشاء كائنات جديدة ديناميكيًا من هوية صنف معين، أي أن هوية الصنف تحوي سندًا لهذا المصنع. وبالتالي إن كان عندك سند لكائن بهوية فيمكن عن طريق هوية الكائن الوصول لمصنعه وإنشاء كائنات جديدة من نفس الصنف. يحتوي مـصنع_كائن_بهوية على مؤشرات الدالات التالية:
  • أنشئ_محتكر (createPlain)
      عرف أنشئ_محتكر: مؤشر[@مشترك @دون_ربط دالة (): سند[كـائن_بهوية]]؛
    
      def createPlain: ptr[@shared @no_bind function ():ref[TiObject]];
    
    تنشئ كائنًا وترجع سندا اعتياديًا له بعد تهيئته.
  • أنشئ_مشترك (createShared)
      عرف أنشئ_مشترك: مؤشر[@مشترك @دون_ربط دالة (): سـندنا[كـائن_بهوية]]؛
    
      def createShared؛: ptr[@shared @no_bind function ():SrdRef[TiObject]];
    
    تنشئ كائنًا وترجع سندا مشتركًا له بعد تهيئته.
  • هيئ (initialize)
      عرف هيئ: مؤشر[@مشترك @دون_ربط دالة (سند[كـائن_بهوية])]؛
    
      def initialize: ptr[@shared @no_bind function (ref[TiObject])];
    
    تهيئ كائنًا محجوز في الذاكرة مسبقًا.
  • أتلف (terminate)
      عرف أتلف: مؤشر[@مشترك @دون_ربط دالة (سند[كـائن_بهوية])]؛
    
      def terminate: ptr[@shared @no_bind function (ref[TiObject])];
    
    تتلف كائنًا دون تحرير ذاكرته.
الصنف: هـوية_صنف (TypeInfo)
معرف داخل الوحدة الـقلب.أسـاسيات (Core.Basic).
يحمل معلومات عن هوية صنف معين. تشمل هذه المعلومات اسم الصنف والوحدة التي ينتمي إليها ومصنع الكائنات وغيرها، ويحوي المتغيرات التالية:
  • اسم_الصنف (typeName): نـص (String)
    نص يحمل اسم الصنف دون المسار الكامل.
  • مسار_الصنف (typeNamespace): نـص (String)
    نص يحمل مسار الصنف الكامل دون اسم الصنف. فإذا كان عندك صنف وحـدة_خارجية.وحـدة_داخلية.صـنفي فإن هذا المتغير سيحوي القيمة `وحـدة_خارجية.وحـدة_داخلية`.
  • اسم_الحزمة (packageName): نـص (String)
    نص يحمل اسم الحزمة التي تحوي الصنف. على سبيل المثال، كل الأصناف المعرفة داخل القلب تحمل اسم الحزمة Core، بينما الأصناف المعرفة داخل مكتبة نمط البناء المعياري تحمل اسم الحزمة Spp.
  • الرابط (url): نـص (String)
    رابط الحزمة على الشبكة العنكبوتية. الأسس لا تتعامل مع الرابط بشكل مباشر وإنما تعامله فقط كمعلومة للمستخدم لتمييز الصنف في حالة تشابه الأسماء.
  • الاسم_الفريد (uniqueName): نـص (String)
    سلسلة محارف تتكون من جمع المعلومات أعلاه في معرف واحد فريد.
  • هوية_صنف_السلف (baseTypeInfo): سند[هـوية_صنف] (ref[TypeInfo])
    سند لهوية سلف هذا الصنف، أي لهوية الصنف الذي أُشتُق منه هذا الصنف. تكون السند صفرًا إن لم يمكن لهذا الصنف سلف.
  • مصنع_الكائنات (objectFactory): سند[مـصنع_كائن_بهوية] (ref[TiObjectFactory])
    سند للمصنع الذي يُنشئ كائنات من هذا الصنف.
الصنف: كـائن_بهوية (TiObject)
معرف داخل الوحدة الـقلب.أسـاسيات (Core.Basic).
الجذر لكل الأصناف الحاملة لهوية. يوفر إمكانية الوصول إلى هوية الصنف بالإضافة إلى الوصول إلى الوسطاء التي يدعمها الصنف ويوفر أيضًا إمكانية التمثيل الديناميكي (dynamic casting). يحتوي هذا الصنف على العناصر التالية:
  • هات_هويتي (getMyTypeInfo)
      عملية هذا.هات_هويتي (): سند[هـوية_صنف]؛
    
      handler this.getMyTypeInfo (): ref[TypeInfo];
    
    تعطيك سندًا لهوية هذا الكائن.
  • أمشتق_من (isDerivedFrom)
      عملية هذا.أمشتق_من (سند[هـوية_صنف]): ثـنائي؛
    
      handler this.isDerivedFrom (ref[TypeInfo]): Bool;
    
    تُعلمك إن كان الكائن من الصنف ذي الهوية المعطاة، أو من صنف مشتق من ذلك الصنف.
  • هات_وسيط (getInterface)
      عملية هذا.هات_وسيط (سند[هـوية_صنف]): سند[وسـيط_بهوية]؛
    
      handler this.getInterface (ref[TypeInfo]): ref[TiInterface];
    
    تستقبل سندًا لهوية وسيط وترجع سندًا لذلك الوسيط إن وجد، وإن لم يكن ذلك الوسيط مدعوما من هذا الكائن فترجع صفرًا.
الصنف: وسـيط_بهوية (TiInterface)
معرف داخل الوحدة الـقلب.أسـاسيات (Core.Basic).
الجذر لكل أصناف الوسطاء. يوفر إمكانية الوصول إلى هوية الوسيط بالإضافة للوصول إلى الكائن الذي يملك الوسيط. يحتوي هذا الصنف على العناصر التالية:
  • هات_هويتي (getMyInterfaceInfo)
      عملية هذا.هات_هويتي (): سند[هـوية_صنف]؛
    
      handler this.getMyInterfaceInfo (): ref[TypeInfo];
    
    تعطيك سندًا لهوية هذا الوسيط.
  • هات_الكائن (getTiObject)
      عملية هذا.هات_الكائن (): سند[كـائن_بهوية]؛
    
      handler this.getTiObject (): ref[TiObject];
    
    تُرجع الكائن الذي يملك هذا الوسيط.
الماكرو: هات_الوسيط (getInterface)
معرف داخل الوحدة الـقلب.أسـاسيات (Core.Basic).
ماكرو لتسهيل الحصول على وسيط من كائن محدد. يستخدم بهذه الطريقة:
  وسيط~عطل_التتبع = هات_الوسيط[كائن، صـنف_الوسيط]
  interface~no_deref = getInterface[obj, InterfaceType];
الماكرو: أمشتق_من (isDerivedFrom)
معرف داخل الوحدة الـقلب.أسـاسيات (Core.Basic).
يفحص ما إذا كان الكائن المعطى مشتقًا من الصنف المعطى، ويستخدم كالتالي:
  إذا أمشتق_من[كائن، صـنف_الكائن] { ... }
  if isDerivedFrom[obj, ObjType] { ... }
الماكرو: عرف_سندا_بتمثيل_آمن (defDynCastedRef)
معرف داخل الوحدة الـقلب.أسـاسيات (Core.Basic).
ماكرو مساعد يختصر عملية تمثيل الصنف ديناميكيًا وخزن النتيجة في متغير جديد. مثال:
  دالة اختبار (كائن_جذري: سند[صـنف_الجذر]) {
    عرف_سندا_بتمثيل_آمن[كائن_فرعي، كائن_جذري، صـنف_الفرع]؛
    إذا كائن_فرعي~مؤشر != 0 كائن_فرعي.عملية(...)؛
  }
  func test (parentObj: ref[ParentType]) {
    defDynCastedRef[childObj, parentObj, ChildType];
    if childObj~ptr != 0 childObj.someFunc(...);
  }

أصناف أساسية

معرفة داخل الوحدة الـقلب.أسـاسيات (Core.Basic).
تتوفر مجموعة من الأصناف تقابل الأصناف الأساسية مثل الأعداد الصحيحة والنصوص، لكنها مشتقة من كـائن_بهوية وبالتالي يمكن التعرف عليها والتعامل معها بسهولة أثناء التنفيذ. هذه الأصناف تعرف عمليات المساواة والتهيئة بالإضافة للعناصر التالية:
  • القيمة (value)
    المتغير الذي يحوي القيمة الأصلية بصنفها الأساسي.
  • أنشئ (create)
      دالة أنشئ (ق: الـصنف_الأساسي): سـندنا[صـنف_المعلومة]
    
      func create (v: BasicType): SrdRef[ObjType]
    
    تنشئ كائنًا من هذا الصنف بالقيمة المعطاة وترجع سندًا مشتركًا للكائن.
  • هات_هوية_الصنف (getTypeInfo)
      دالة هات_هوية_الصنف (): سند[هـوية_صنف]؛
    
      func getTypeInfo (): ref[TypeInfo];
    
    هذه الدالة تُرجع سندًا لهوية هذا الصنف، أي لهوية الكائنات المشتقة من هذا الصنف.
المثال التالي يوضح طريقة تعريف واستخدام هذه الأصناف:
  عرف ص: صـحيح_بهوية(45)؛
  اطبع_صحيح(ص.القيمة)؛
  ص = 7؛

  عرف ك: سند[كـائن_بهوية](ص)؛
  إذا أمشتق_من[ك، صـحيح_بهوية] {
    عرف س: سند[صـحيح_بهوية](مثل_سند[ك، صـحيح_بهوية])؛
    اطبع_صحيح(س.القيمة)؛
  }
  def i: TiInt(45);
  printInt(i.value);
  i = 7;
  
  def o: ref[TiObject](i);
  if isDerivedFrom[o, TiInt] {
    def x: ref[TiInt](castRef[o, TiInt]);
    printInt(x.value);
  }
فيما يلي قائمة الأصناف الأساسية بهوية:
  • صـحيح_بهوية (TiInt)
  • طـبيعي_بهوية (TiWord)
  • عـائم_بهوية (TiFloat)
  • ثـنائي_بهوية (TiBool)
  • نـص_بهوية (TiStr)
  • مـؤشر_بهوية (TiPtr)

الوصول الديناميكي للبيانات

الأصناف المستخدمة في شجرة البنية المجردة (Abstract Syntax Tree) تدعم مجموعة من الوسطاء لتمكين تصفح الشجرة بشكل ديناميكي. هذه الوسطاء تمكن من الاستعلام عن عناصر الكائن وتمكن من الوصول لتلك القيم لقراءتها أو تعديلها.
الوسيط: ربـط (Binding)
معرف داخل الوحدة الـقلب.أسـاسيات (Core.Basic).
هذا الوسيط يمكن المستخدم من الوصول إلى أعضاء الكائن، ويحتوي على الدالات التالية:
  • حدد_عضوا (setMember)
      عملية هذا.حدد_عضوا (اسم_العضو: مؤشر[مصفوفة[مـحرف]]، قيمة: سند[كـائن_بهوية])؛
      عملية هذا.حدد_عضوا (تسلسل_العضو: صـحيح، قيمة: سند[كـائن_بهوية])؛
    
      handler this.setMember (memberName: ptr[array[Char]], value: ref[TiObject]);
      handler this.setMember (memberIndex: Int, value: ref[TiObject]);
    
    تحدد قيمة عضو من أعضاء الكائن. الصيغة الأولى لتحديد العضو اعتمادا على اسمه بينما الثانية تعتمد على تسلسل العضو بين أعضاء الكائن.
  • هات_عدد_الأعضاء (getMemberCount)
      عملية هذا.هات_عدد_الأعضاء (): طـبيعي؛
    
      handler this.getMemberCount(): Word;
    
    تستعلم عن عدد الأعضاء التي يمتلكها الكائن.
  • هات_عضوا (getMember)
      عملية هذا.هات_عضوا (اسم_ألعضو: مؤشر[مصفوفة[مـحرف]]): سند[كـائن_بهوية]؛
      عملية هذا.هات_عضوا (تسلسل_العضو: صـحيح): سند[كـائن_بهوية]؛
    
      handler this.getMember (memberName: ptr[array[Char]]): ref[TiObject];
      handler this.getMember (memberIndex: Int): ref[TiObject];
    
    تجلب قيمة العضو ذي الإسم المعطى في الصيغة الأولى، أو التسلسل المعطى في الصيغة الثانية.
  • هات_الصنف_المطلوب_للعضو (getMemberNeededType)
      عملية هذا.هات_الصنف_المطلوب_للعضو (اسم_العضو: مؤشر[مصفوفة[مـحرف]]): سند[هـوية_صنف]؛
      عملية هذا.هات_الصنف_المطلوب_للعضو (تسلسل_العضو: صـحيح): سند[هـوية_صنف]؛
    
      handler this.getMemberNeededType (memberName: ptr[array[Char]]): ref[[TypeInfo];
      handler this.getMemberNeededType (memberIndex: Int): ref[TypeInfo];
    
    تجلب هوية الصنف المطلوب للعنصر ذي الإسم المعطى في الصيغة الأولى، أو التسلسل المعطى في الصيغة الثانية.
  • هات_اسم_العضو (getMemberKey)
      عملية هذا.هات_اسم_العضو (تسلسل_العضو: صـحيح): نـص؛
    
      handler this.getMemberKey (index: Int): String;
    
    تجلب اسم العضو ذي التسلسل المعطى.
  • جد_تسلسل_العضو (findMemberIndex)
      عملية هذا.جد_تسلسل_العضو (اسم_العضو: مؤشر[مصفوفة[مـحرف]]): صـحيح؛
    
      handler this.findMemberIndex (name: ptr[array[Char]]): Int;
    
    ترجع تسلسل العضو ذي الاسم المعطى، أو -1 إن لم يوجد عضو بهذا الاسم.
الوسيط: احـتواء (Containing)
معرف داخل الوحدة الـقلب.أسـاسيات (Core.Basic).
يُستخدم هذا الوسيط للاستعلام عن الكائنات الأخرى التي يحتويها هذا الكائن، أي عن العقد الأخرى التي يمتلكها هذا الكائن ضمن الشجرة.
الفرق بين هذا الوسيط ووسيط ربـط أن الأخير يستخدم للاستعلام عن صفات الكائن نفسه والتي تعتبر وصفًا لتلك العقدة بينما وسيط احـتواء يستعلم عن عقد أخرى مستقلة عن الكائن لكنها مرتبطة به. على سبيل المثال لو كان عندك كائن يمثل مؤثرًا ثنائيا بين قيمتين فإن نوع المؤثر يعتبر صفة ويُستعلم عنه باستخدام ربـط بينما العنصرين الذين على جانبي المؤثر يُستعلم عنهما باستخدام احـتواء.
يحوي هذا الوسيط الدالات التالية:
  • حدد_عنصرا (setElement)
      عملية هذا.حدد_عنصرا (تسلسل_العنصر: صـحيح، قيمة: سند[كـائن_بهوية])؛
    
      handler this.setElement (index: Int, value: ref[TiObject]);
    
    تحديد كائن جديد للعنصر ذي التسلسل المعطى.
  • هات_عدد_العناصر (getElementCount)
      عملية هذا.هات_عدد_العناصر (): طـبيعي؛
    
      handler this.getElementCount (): Word;
    
    تجلب عدد العناصر التي يحتويها الكائن.
  • هات_عنصرا (getElement)
      عملية هذا.هات_عنصرا (تسلسل_ألعنصر: صـحيح): سند[كـائن_بهوية]؛
    
      handler this.getElement (index: Int): ref[TiObject];
    
    تجلب العنصر الواقع عند التسلسل المعطى.
  • هات_الصنف_المطلوب_للعنصر (getElementNeededType)
      عملية هذا.هات_الصنف_المطلوب_للعنصر (تسلسل_العنصر: صـحيح): سند[هـوية_صنف]؛
    
      handler this.getElementNeededType (index: Int): ref[TypeInfo];
    
    تجلب هوية الصنف المطلوب للعنصر ذي التسلسل المعطى.
الوسيط: احـتواء_مرن (DynamicContaining)
معرف داخل الوحدة الـقلب.أسـاسيات (Core.Basic).
مُشتق من احـتواء ويضيف إمكانية تغيير عدد العناصر التي يحتويها الكائن. يُستخدم هذا الوسيط مع الحاويات متغيرة الحجم، ويحوي الدالات التالية بالإضافة للدالات التي يحويها الوسيط احـتواء.
  • أضف_عنصرا (addElement)
      عملية هذا.أضف_عنصرا (القيمة: سند[كـائن_بهوية]): صـحيح؛
    
      handler this.addElement (value: ref[TiObject]): Int;
    
    تضيف عنصرا جديدا إلى نهاية الحاوية وترجع تسلسل العنصر الجديد.
  • احشر_عنصرا (insertElement)
      عملية هذا.احشر_عنصرا (تسلسل: صـحيح، قيمة: سند[كـائن_بهوية])؛
    
      handler this.insertElement (index: Int, value: ref[TiObject]);
    
    تضيف عنصرا جديدا إلى الحاوية عند التسلسل المعطى بعد تزحيف كل العناصر التي عند ذلك التسلسل.
  • أزل_عنصرا (removeElement)
      عملية هذا.أزل_عنصرا (تسلسل_العنصر: صـحيح)؛
    
      handler this.removeElement (index: Int);
    
    تزيل العنصر الذي عند التسلسل المعين ثم تزحف كل العناصر التي تلي ذلك التسلسل.
  • هات_الصنف_المطلوب_للعناصر (getElementsNeededType)
      عملية هذا.هات_الصنف_المطلوب_للعناصر (): سند[هـوية_صنف]؛
    
      handler this.getElementsNeededType (): ref[TypeInfo];
    
    تجلب هوية الصنف المطلوب لعناصر هذه الحاوية دون الحاجة لتحديد عنصر معين.
الوسيط: احـتواء_تطبيقي (MapContaining)
معرف داخل الوحدة الـقلب.أسـاسيات (Core.Basic).
مُشتق من احـتواء ويضيف إمكانية الوصول للعناصر عبر أسمائها بدل تسلسلها. يحوي هذا الوسيط الدالات التالية:
  • حدد_عنصرا (setElement)
      عملية هذا.حدد_عنصرا (
        اسم_ألعنصر: مؤشر[مصفوفة[مـحرف]]، قيمة: سند[كـائن_بهوية]
      ): صـحيح؛
    
      handler this.setElement (
        elementName: ptr[array[Char]], value: ref[TiObject]
      ): Int;
    
    تحدد قيمة جديدة للعنصر ذي الاسم المعطى وترجع تسلسل هذا العنصر.
  • هات_عنصرا (getElement)
      عملية هذا.هات_عنصرا (اسم_العنصر: مؤشر[مصفوفة[مـحرف]]): سند[كـائن_بهوية]؛
    
      handler this.getElement (elementName: ptr[array[Char]]): ref[TiObject];
    
    تجلب قيمة العنصر ذي الاسم المعطى.
  • هات_الصنف_المطلوب_للعنصر (getElementNeededType)
      عملية هذا.هات_الصنف_المطلوب_للعنصر (
        اسم_العنصر: مؤشر[مصفوفة[مـحرف]]
      ): سند[هـوية_صنف]؛
    
      handler this.getElementNeededType (
        elementName: ptr[array[Char]]
      ): ref[TypeInfo];
    
    تجلب هوية الصنف المطلوب للعنصر ذي الاسم المعطى.
  • هات_اسم_العنصر (getElementKey)
      عملية هذا.هات_اسم_العنصر (تسلسل_العنصر: صـحيح): نـص)
    
      handler this.getElementKey (index: Int): String;
    
    تجلب اسم العنصر ذي التسلسل المعطى.
  • جد_تسلسل_العنصر (findElementIndex)
      عملية هذا.جد_تسلسل_العنصر (اسم_العنصر: مؤشر[مصفوفة[مـحرف]]): صـحيح؛
    
      handler this.findElementIndex (name: ptr[array[Char]]): Int;
    
    ترجع تسلسل العنصر ذي الاسم المعطى، أو -1 إن لم يوجد عنصر بهذا الاسم.
الوسيط: احـتواء_تطبيقي_مرن (DynamicMapContaining)
معرف داخل الوحدة الـقلب.أسـاسيات (Core.Basic).
مُشتق من احـتواء_تطبيقي ويضيف إمكانية إزالة عناصر أو إضافة عناصر جديدة ديناميكيا. يحوي هذا الوسيط الدالات التالية:
  • أضف_عنصرا (addElement)
      عملية هذا.أضف_عنصرا (
        اسم_العنصر: مؤشر[مصفوفة[مـحرف]]، قيمة: سند[كـائن_بهوية]
      ): صـحيح؛
    
      handler this.addElement (
        name: ptr[array[Char]], value: ref[TiObject]
      ): Int;
    
    يضيف عنصرا جديدا باسم الجديد إلى الحاوية ويرجع تسلسل العنصر الجديد.
  • احشر_عنصرا (insertElement)
      عملية هذا.احشر_عنصرا (
        تسلسل: صـحيح، اسم: مؤشر[مصفوفة[مـحرف]]، قيمة: سند[كـائن_بهوية]
      )؛
    
      handler this.insertElement (
        index: Int, name: ptr[array[Char]], value: ref[TiObject]
      );
    
    يضيف عنصرا جديدا عند التسلسل المحدد بعد تزحيف العناصر التي عند ذلك التسلسل أو تليه.
  • أزل_عنصرا (removeElement)
      عملية هذا.أزل_عنصرا (تسلسل_العنصر: صـحيح)؛
      عملية هذا.أزل_عنصرا (اسم_ألعنصر: مؤشر[مصفوفة[مـحرف]])؛
    
      handler this.removeElement (index: Int);
      handler this.removeElement (name: ptr[array[Char]]);
    
    تزيل العنصر ذي التسلسل المعطى في الصيغة الأولى أو الاسم المعطى في الصيغة الثانية.
  • هات_الصنف_المطلوب_للعناصر (getElementsNeededType)
      عملية هذا.هات_الصنف_المطلوب_للعناصر (): سند[هـوية_صنف]؛
    
      handler this.getElementsNeededType (): ref[TypeInfo];
    
    تجلب هوية الصنف المطلوب لعناصر هذه الحاوية دون الحاجة لتحديد عنصر معين.

أصناف شجرة البنية المجردة (AST)

كل الأصناف المكونة لشجرة البنية المجردة مشتقة من الصنف عـقدة (Node) وكلها تدعم وسطاء الوصول الديناميكي للبيانات، لذلك يمكن أثناء التنفيذ تصفح شجرة بنية مجردة بشكل ديناميكي وهو ما يمكن المستخدم من قراءة وإنشاء أشجار البنية المجردة من داخل برنامجه بما يمكنه من تطوير تراكيب نحوية جديدة تسهل عليه عمله.
الصنف: عـقدة (Node)
معرف داخل الوحدة الـقلب.بـيانات (Core.Data).
مُشتق من كـائن_بهوية.
جذر لأصناف بيانات أخرى مثل أصناف شجرة البنية المجردة. يمكن هذا الصنف من الوصول من كائن إلى مالكه.
  • المالك (owner): سند[عـقدة]
    سند إلى مالك هذا الكائن.
  • هات_هوية_الصنف (getTypeInfo)
      دالة هات_هوية_الصنف (): سند[هـوية_صنف]؛
    
      func getTypeInfo (): ref[TypeInfo];
    
    هذه الدالة تُرجع سندًا لهوية هذا الصنف، أي لهوية الكائنات المشتقة من هذا الصنف.
الأصناف النصية
معرف داخل الوحدة الـقلب.بـيانات.شـبم (Core.Data.Ast).
مُشتق من عـقدة.
هذه الأصناف التي تحوي مقطعًا نصيّا مفردًا من الشفرة المصدرية، أي دون مؤثرات أو تراكيب. المقطع النصي هنا يُقصد به أي سلسلة محارف يُفسرها المرمّز (lexer) كرمز واحد ولذا قد تكون معرفا أو رقما أو سلسلة محارف. تحوي هذه الأصناف العناصر التالية:
  • القيمة (value): نـص_بهوية (TiStr)
    سلسلة المحارف المقروءة من الشفرة المصدرية.
  • هات_هوية_الصنف (getTypeInfo)
      دالة هات_هوية_الصنف (): سند[هـوية_صنف]؛
    
      func getTypeInfo (): ref[TypeInfo];
    
    هذه الدالة تُرجع سندًا لهوية هذا الصنف، أي لهوية الكائنات المشتقة من هذا الصنف.
  • أنشئ (create)
      دالة أنشئ (قيمة: مؤشر[مصفوفة[مـحرف]]): سـندنا[الـصنف]؛
    
      func create (value: ptr[array[Char]]): SrdRef[TheType];
    
    تنشئ كائنًا من هذا الصنف بالقيمة المعطاة وترجع سندًا مشتركًا له.
فيما يلي قائمة بالأصناف النصية:
  • مـعرف (Identifier)
    أي معرف كان من الشفرة المصدرية مثل اسم متغير أو اسم دالة أو ما شابه.
  • نـص_حرفي (StringLiteral)
    يحوي سلسلة محارف، أي سلسلة المحارف المحصورة بين علامتي اقتباس. القيمة المخزنة في هذا الكائن لا تشمل علامات الاقتباس كما أنها لا تشمل علامات المحارف المركبة (مثل رمز \) وإنما تشمل المحرف نفسه فقط. على سبيل المثال، عندما يكتب المستخدم \" فإن قيمة هذا الكائن ستحوي فقط على " دون علامة \.
    في حالة تقسيم المستخدم سلسلته النصية إلى عدة مقاطع (بإغلاق علامة الاقتباس ثم فتحها من جديد) فإن القيمة التي في هذا الكائن ستكون سلسلة محارف تشمل جميع المقاطع ودون فراغات. على سبيل المثال، إذا أدخل المستخدم "السلام" " عليكم" فإن قيمة هذا الكائن ستكون السلام عليكم.
  • مـحرف_حرفي (CharLiteral)
    يحوي محرفًا، أي المحرف المحصور في الشفرة المصدرية بين علامتي اقتباس مفردة، لكن القيمة في هذا الكائن بدون علامتي الاقتباس.
  • صـحيح_حرفي (IntegerLiteral)
    يحوي عددا صحيحًا مع الرموز المتعلقة بصنف العدد الصحيح، مثلا: "456ص32".
  • عـائم_حرفي (FloatLiteral)
    يحوي عددا بفاصلة مع الرموز المتعلقة بصنف العدد، مثلا: "1.2f32".
أصناف الأوامر والتراكيب
معرف داخل الوحدة الـقلب.بـيانات.شـبم (Core.Data.Ast).
مُشتق من عـقدة.
فيما يلي قائمة الأصناف الممثلة للأوامر والتراكيب وما شابه. باستثناء دالة هات_هوية_الصنف لا تملك هذه الأصناف دالات أخرى وإنما يمكن الوصول لأعضائها وعناصرها باستخدام وسطاء الوصول الديناميكي للبيانات.
  • لـقب (Alias)
  • قـوس (Bracket)
  • جـسر (Bridge)
    يمثل هذا الصنف عبارة `استخدم` (use) التي تنشئ جسرًا من مجال يمكنه من الوصول تلقائيًا لعناصر مجال آخر.
  • تـعريف (Definition)
  • إيـعاز (GenericCommand)
    صنف عمومي يمكن استخدامه لحمل بيانات إيعاز غير محدد. يحمل نصا للكلمة المفتاحية مع فائمة مرنة من البيانات.
  • قـائمة (List)
  • تـطبيق (Map)
  • قـائمة_دمج (MergeList)
    صنف خاص يبلغ المعرب أن يدمج عناصره مباشرة في المجال العلوي بدل أن تبقى كقائمة فرعية داخل المجال العلوي.
  • مـمرر_معطيات (ParamPass)
    يمثل عملية تمرير بيانات إلى عنصر ما مثل استدعاء دالة أو ماكرو أو قالب.
  • مـجال (Scope)
  • رمـز (Token)
  • مـؤثر_قبلي (PrefixOperator)
  • مـؤثر_بعدي (PostfixOperator)
  • مـؤثر_تعيين (AssignmentOperator)
  • مـؤثر_مقارنة (ComparisonOperator)
  • مـؤثر_جمع (AdditionOperator)
    لعملبات الجمع والطرح.
  • مـؤثر_ضرب (MultiplicationOperator)
    لعمليات الضرب والقسمة.
  • مـؤثر_بتي (BitwiseOperator)
  • مـؤثر_منطقي (LogOperator)
  • مـؤثر_ربط (LinkOperator)
    لمؤثرات الربط بين عنصر وعضو منه مثل مرثر النفطة أو مؤثر -> أو ما شابه.
  • مـؤثر_شرط (ConditionalOperator)

دليل الوحدة `نـبم`


الوحدة `نـبم` (نمط البرمجة المعياري) تحتوي على دالات للتعامل مباشرة مع مكتبة spp، وهي المكتبة المسؤولة عن دعم نمط البرمجة المعياري. عناصر هذه الوحدة تمكن المستخدم من التعامل مباشرة مع المترجم من خلال برنامجه.

الكائن: مدير_البناء (buildMgr)

هذا الكائن المفرد يمكن المستخدم من التعامل مع مولد الشفرة التنفيذية ويحوي الدالات التالية:
أدرج_تو_لعنصر (dumpLlvmIrForElement)
  عملية هذا.أدرج_تو_لعنصر (عنصر: سند[كـائن_بهوية])؛
  handler this.dumpLlvmIrForElement (element: ref[TiObject]);
دالة `أدرج_تو_لعنصر` تقوم بطبع الترميز الوسطي لعنصر معين من الشفرة المصدرية. الترميز الوسطي المطبوع هو ترميز LLVM IR. تستقبل الدالة معطى واحد وهو مؤشر على شبكة البنية المجردة لذلك العنصر (Abstract Syntax Tree). يمكنك الحصول على هذا المؤشر باستخدام الأمر `~شبم` كما في المثال التالي:
  نـبم.مدير_البناء.أدرج_تو_لعنصر(دالتي~شبم)؛
  Spp.buildMgr.dumpLlvmIrForElement(myFunc~ast);
أنشء_ملفا_رقميا_لعنصر (buildObjectFileForElement)
  عملية هذا.أنشء_ملفا_رقميا_لعنصر (
    عنصر: سند[كـائن_بهوية]،
    اسم_الملف: مؤشر[مصفوفة[محرف]]،
    وصف_المعمارية: مؤشر[مصفوفة[محرف]]
  ): ثنائي
  handler this.buildObjectFileForElement (
    element: ref[TiObject],
    filename: ptr[array[Char]],
    targetTriple: ptr[array[Char]]
  ): Bool;
تنشئ هذه الدالة ملف شفرة مترجمة للعنصر المعني (object file). يمكن لاحقا تمرير هذا الملف إلى مُجمِّع (linker) لإنشاء ملف تنفيذي. المعطى الثالث قيمة target triple تحدد المعمارية التي ستستخدم في البناء. في حالة تمرير 0 لهذا المعطى تُستخدم المعمارية الحالية للنظام. على سبيل المثال لبناء شفرة تنفيذية بمعمارية ويب أسمبلي تُمرر القيمة "wasm32-unknown-unknown". يمكن مراجعة وثائق LLVM لمزيد من المعلومات حول هذه القيمة.
ترجع الدالة 1 في حال نجح البناء، وبعكسه ترجع 0.
  نـبم.مدير_البناء.أنشء_ملفا_رقميا_لعنصر(وحـدتي~شبم، "اسم_الملف_الناتج"، 0)؛
  Spp.buildMgr.buildObjectFileForElement(MyModule~ast, "output_filename", 0);
ارفع_إشعار_بناء (raiseBuildNotice)
  دالة ارفع_إشعار_بناء (
    رمز: مؤشر[مصفوفة[مـحرف]]، حدة: صـحيح، عنصر_شبم: سند[الـقلب.أسـاسيات.كـائن_بهوية]
  )؛
  func raiseBuildNotice (
    code: ptr[array[Char]], severity: Int, astNode: ref[TiObject]
  );
تمكن هذه الدالة المبرمج من رفع إشعار بناء بشكل برمجي أثناء المعالجة التمهيدية. تأخذ هذه الدالة ثلاث معطيات:
  • رمز: رمز إشعار الخطأ المراد إظهاره للمستخدم. قائمة الرموز المتوفرة تجدها داخل المجلد Notices_L18n.
  • حدة: قيمة تبين حدة الإشعار ويمكن أن تكون واحدا من هذه القيم:
    • 0: الإشعاء لخطأ جذري لا يُمكن استمرار البناء معه.
    • 1: إشعار خطأ، لكن الترجمة يمكنها الاستمرار لاكتشاف أخطاء أخرى إن وجدت.
    • 2: إشعاء لتحذير مهم يجب على المستخدم مراجعته.
    • 3: إشعار لتحذير قليل الأهمية يمكن للمستخدم تجاهله.
    • 4: إشعار إعلامي فقط وليس لخطأ.
  • عنصر_شبم: سند لعنصر شبم المعني بالإشعار. سيشير الإشعار إلى موقع الشفرة المصدرية الذي يظهر عنده العنصر.
مثال:
  عرف رمز_خطأ: "SPPH1006"؛
  نـبم.مدير_البناء.ارفع_إشعار_بناء(رمز_خطأ، 1، عنصر_معطى_الدالة)؛
  // السطر أعلاه سيظهر إشعار خطأ: اسم معطى الدالّة غير صالح.
  def errorCode: "SPPH1006";
  Spp.buildMgr.raiseBuildNotice(errorCode, 1, funcArgNode);
  // The above line will show an build error: Invalid function argument name.

الكائن: مدير_القواعد (grammarMgr)

هذا الكائن المفرد يمكن المستخدم من إنشاء قواعد جديدة للغة، ويحوي الدالات التالية:
أضف_أمرا_مخصصا (addCustomCommand)
عرف كـائن_بهوية: لقب الـقلب.أسـاسيات.كـائن_بهوية؛

عملية هذا.أضف_أمرا_مخصصا (
    معرف: مؤشر[مصفوفة[مـحرف]]،
    شجرة_القاعدة: سند[كـائن_بهوية]
    معالج: مؤشر[دالة (سـندنا[كـائن_بهوية]): سـندنا[كـائن_بهوية]]
)؛
def TiObject: alias Core.Basic.TiObject;

handler this.addCustomCommand (
    identifier: ptr[array[Char]],
    grammarAst: ref[TiObject],
    handler: ptr[func (SrdRef[TiObject]): SrdRef[TiObject]]
);
تستخدم هذه الدالة لإضافة قاعدة لأمر جديد إلى قواعد اللغة ديناميكيًا. تستلم هذه الدالة ثلاث معطيات:
  • معرف: سلسلة محارف تستخدم كمعرف للقاعدة الجديدة. يمكن تمرير أي قيمة لهذا المعرف طالما أنها من حروف وأرقام فقط ولا تتضارب مع معرف موجود مسبقًا.
  • شجرة_القاعدة: شجرة بنية مجردة تصف قاعدة الأمر الجديد. تأخذ هذه الشجرة الشكل التالي:
    شبم {
        مفاتيح: <الكلمات المفتاحية للأمر>؛
        معطيات: <وصف للمعطيات التي تتبع الكلمة المفتاحية>؛
    }
    
    ast {
        keywords: <keywords of the command>;
        args: <description of the args following the keyword>;
    }
    
    يمكن للأمر أن يملك كلمة مفتاحية واحدة، أو مجموعة كلمات (يفصلها في التعريف مؤثر |). يمكن للأمر أن لا يستقبل أي معطيات، أو أن يستقبل معطى واحد أو مجموعة معطيات (يفصلها في التعريف مؤثر +). كل معطى من هذه المعطيات يتكون من المسار المؤدي إلى القاعدة الإعرابية للمعطى، متبوعًا بعلامة * متبوعة بقوسين بينهما الحدين الأدنى والأعلى (على التوالي) لظهور هذا المعطى ضمن الأمر. راجع الشفرة المصدرية لقواعد لغة الأسس لمزيد من المعلومات حول القواعد المتوفرة التي يمكن استخدامها كمعطيات.
  • معالج: دالة تستقبل شجرة البناء المجردة التي أنشأها المترجم أثناء إعراب الشفرة المصدرية وتعالجها ثم تعيد شجرة بناء مجردة يتم حشرها كنتيجة نهائية لإعراب هذا الأمر.
مثال:
نـبم.مدير_القواعد.أضف_أمرا_مخصصا(
    "أمـر_اختبار"،
    شبم {
        مفاتيح: "أمر_اختبار" | "test_cmd"؛
        معطيات: "module".Expression*(0,2) +
                "module".Set*(1,1)؛
    }،
    دالة (معطيات: سـندنا_بهوية): سـندنا_بهوية { ... }
)؛
Spp.grammarMgr.addCustomCommand(
    "TestCommand",
    ast {
        keywords: "test_cmd";
        args: "module".Expression(0, 2) + "module".Set*(1,1);
    },
    func (args: SrdRef[TiObject]): SrdRef[TiObject] { ... }
);
المثال أعلاه يعرف أمرًا جديدا يبدأ إما بالكلمة المفتاحية `أمر_اختبار` أو بالكلمة المفتاحية `test_cmd`، ثم يتبع الكلمة المفتاحية معطى من نوع تركيب يمكن أن يظهر مرة واحدة أو مرتين متتابعتين أو لا يظهر أساسًا، ويتبع هذه التراكيب معطى من نوع كتلة (set) يجب أن يظهر مرة واحدة تحديدًا.
أضف_قاعدة_مخصصة (addCustomGrammar)
عرف كـائن_بهوية: لقب الـقلب.أسـاسيات.كـائن_بهوية؛

عملية هذا.أضف_قاعدة_مخصصة (
    معرف: مؤشر[مصفوفة[مـحرف]]،
    معرف_الأصل: مؤشر[مصفوفة[مـحرف]]،
    شجرة_القاعدة: سند[كـائن_بهوية]
)؛
def TiObject: alias Core.Basic.TiObject;

handler this.addCustomGrammar (
    identifier: ptr[array[Char]],
    baseIdentifier: ptr[array[Char]],
    grammarAst: ref[TiObject]
);
تستخدم هذه الدالة لإضافة قاعدة جديدة إلى قواعد اللغة ديناميكيًا. تختلف هذه الدالة عن دالة `أضف_أمرا_مخصصا` (addCustomCommand) بأنها القاعدة الجديدة لا يشترط أن تكون أمرًا (وإنما يمكنها أن تكون تركيبا أو أي شيء) وتكون القاعدة الجديدة مشتقة من قاعدة أخرى. تستلم هذه الدالة ثلاث معطيات:
  • معرف: سلسلة محارف تستخدم كمعرف للقاعدة الجديدة. يمكن تمرير أي قيمة لهذا المعرف طالما أنها من حروف وأرقام فقط ولا تتضارب مع معرف موجود مسبقًا.
  • معرف_الأصل: معرف القاعد الأصل التي ستُشتق منها القاعدة الجديدة.
  • شجرة_القاعدة: شجرة بنية مجردة تصف التغييرات التي ستطبق على القاعدة الجديدة مقارنة بالقاعدة الأصل. تأخذ هذه الشجرة الشكل التالي:
    شبم {
        <مسار_القيمة_المراد_تعديلها>: { <القيمة_الجديدة> }؛
        ...
    }
    
    ast {
        <path_to_value_to_update>: { <new_value> };
        ...
    }
    
    شجرة القاعدة تحتوي مجموعة من المدخلات، كل مدخلة تتكون من المسار للقيمة المراد تعديلها ثم القيمة الجديدة. المسار يكون نسبة لجذر القاعدة.
في المثال التالي سيتم إنشاء قاعدة جديدة مشتقة من القاعدة FuncSigExpression مع تعديل واحد وهو تغيير معطيات القاعدة الفرعية BitwiseExp. اطلع على قواعد لغة الأسس لتعرف القاعدات التي يمكنك الاشتقاق منها وما تحتاج لتعديله عند الاشتقاق.
Spp.grammarMgr.addCustomGrammar(
    "ClosureSigExp",
    "FuncSigExpression",
    ast {
        BitwiseExp.vars: { enable: 1 }
    }
);

الكائن: مدير_شبم (astMgr)

هذا الكائن المفرد يحتوي دالات للتعامل مع شجرة البنية المجردة (Abstract Syntax Tree). يحتوي على الدالات التالية:
جد_عناصر (findElements)
  عملية هذا.جد_عناصر (
    معيار_البحث: سند[الـقلب.أسـاسيات.كـائن_بهوية]،
    موقع_البحث: سند[الـقلب.أسـاسيات.كـائن_بهوية]،
    خيارات: طـبيعي
  ): مـصفوفة[سند[الـقلب.أسـاسيات.كـائن_بهوية]]؛
handler this.findElements (
    comparison: ref[Core.Basic.TiObject],
    target: ref[Core.Basic.TiObject],
    flags: Word
): Array[ref[Core.Basic.TiObject]];
تبحث ضمن الشفرة المصدرية عن عناصر تطابق معيار البحث المعطى. المعطيان الأول والثاني سندان على شجرتي بنية مجردة، الأولى لتركيب يمثل معيار البحث بينما الثانية هي الشجرة التي سيتم البحث فيها.
الخيار الثالث يمكن أن يكون واحدا من هذه القيم:
  • خـيارات_الساعي._تخطى_المالكين_ (SeekerFlags.SKIP_OWNERS)
    تُعلم الساعي أن لا يبحث في المجالات التي يقعل موقع البحث الحالي داخلها. على سبيل المثال، إذا بحثت ضمن مسار `عـام.فـرعي` فإنه مبدئيًا سيبحث ضمن `فـرعي` ثم ضمن `عـام`، فإذا أضفت هذا الخيار فإنه سيبحث ضمن `فـرعي` فقط.
  • خـيارات_الساعي._تخطى_الاستخدامات_ (SeekerFlags.SKIP_USES)
    تُبلغ الساعي أن يتجاهل عبارات `استخدم` (use) أثناء البحث. بدون هذا الخيار فإن الساعي سيبحث في المجالات التي تشير إليها هذه العبارات.
  • خـيارات_الساعي._تخطى_الأبناء_ (SeekerFlags.SKIP_CHILDREN)
    تُعلم الساعي أن لا يبحث في المجالات الفرعية. مثلا إذا بحثت ضمن المجال `عـام` وكان هذا المجال يحتوي على المجال `فـرعي` فإن الساعي سيبحث في `عـام` ثم `فـرعي` ما لم تُعطه هذا الخيار، فإن فعلت فسيبحث في `عـام` فقط.
المثال التالي يبحث عن كل الدالات ضمن صنف محدد:
  العناصر = نـبم.مدير_شبم.جد_عناصر(
    شبم { نوع_العنصر == "دالة" }،
    صـنفي~شبم،
    نـبم.خـيارات_الساعي._تخطى_المالكين_ | نـبم.خـيارات_الساعي._تخطى_الاستخدامات_ | نـبم.خـيارات_الساعي._تخطى_الأبناء_
  )؛
  elements = Spp.astMgr.findElements(
    ast { elementType == "function" },
    MyClass~ast,
    Spp.SeekerFlags.SKIP_OWNERS | Spp.SeekerFlags.SKIP_USES | Spp.SeekerFlags.SKIP_CHILDREN
  );
يمكن باستخدام معيار البحث البحث حسب نوع العنصر أو حسب المبدلات المطبقة على العنصر. ويمكن أيضا استخدام شرط مركب يحتوي على مؤثري `و` و `أو`. فيما يلي بعض الأمثلة على معايير البحث:
  نوع_العنصر == "دالة" // بحث عن دالات
  نوع_العنصر == "صنف" // بحث عن أصناف المستخدم
  نوع_العنصر == "وحدة" // بحث عن وحدات
  نوع_العنصر == "متغير" // بحث عن متغيرات
  مبدل == "عمومي" // بحث عن عناصر مطبق عليها مبدل @عمومي
  نوع_العنصر == "دالة" و مبدل == "عمومي" // بحث عن دالات عليها مبدل @عمومي
  elementType == "function" // search for functions
  elementType == "type" // search for types
  elementType == "module" // search for modules
  elementType == "var" // serach for variables
  modifier == "public" // search for elements with @public modifier
  elementType == "func" && modifier == "public" // search for functions with @public modifier
هات_المبدلات (getModifiers)
  عملية هذا.هات_المبدلات (
    عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]
  ): سند[الـقلب.أسـاسيات.احـتواء]؛
  handler this.getModifiers (
      element: ref[Core.Basic.TiObject]
  ): ref[Core.Basic.Containing];
تجلب قائمة المبدلات المطبقة على العنصر المُعطى.
جد_مبدلا (findModifier)
  عملية هذا.جد_مبدلا (
    مبدلات: سند[الـقلب.أسـاسيات.احـتواء]،
    كلمة_مفتاحية: مؤشر[مصفوفة[مـحرف]]
  ): سند[الـقلب.أسـاسيات.كـائن_بهوية]
  handler this.findModifier(
      modifiers: ref[Core.Basic.Containing],
      kwd: ptr[array[Char]]
  ): ref[Core.Basic.TiObject];
إيجاد مبدل ضمن قائمة مبدلات. يتم البحث باستخدام الكلمة المفتاحية للمبدل. مثلا، للبحث عن مبدل `@تصدير[...]` نحتاج لتمرير الكلمة المفتاحية `تصدير`.
جد_مبدلا_لعنصر (findModifierForElement)
  عملية هذا.جد_مبدلا_لعنصر (
    عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]،
    كلمة_مفتاحية: مؤشر[مصفوفة[مـحرف]]
  ): سند[الـقلب.أسـاسيات.كـائن_بهوية]
  handler this.findModifierForElement(
    element: ref[Core.Basic.TiObject],
    kwd: ptr[array[Char]]
  ): ref[Core.Basic.TiObject];
إيجاد المبدل بالكلمة المعيارية المعطاة على العنصر المعطى.
هات_كلمة_المبدل_المفتاحية (getModifierKeyword)
  عملية هذا.هات_كلمة_المبدل_المفتاحية (
    مبدل: سند[الـقلب.أسـاسيات.كـائن_بهوية]
  ): نـص
  handler this.getModifierKeyword(
    modifier: ref[Core.Basic.TiObject]
  ): Srl.String;
تُرجع الكلمة المفتاحية للمبدل المعطى.
هات_المعطيات_النصية_لمبدل (getModifierStringParams)
عملية هذا.هات_المعطيات_النصية_لمبدل (
    مبدل: سند[الـقلب.أسـاسيات.كـائن_بهوية]،
    الناتج: سند[مـصفوفة[نـص]]
): ثـنائي
handler this.getModifierStringParams(
    modifier: ref[Core.Basic.TiObject],
    result: ref[Array[String]]
) => Bool;
تُرجع قائمة بكل المعطيات النصية الممررة للمبدل. مثلاً لو كان عندنا مبدل `@اعتماديات["مكتبة1"، "مكتبة2"]` واستخدمنا هذه الدالة فإننا سنحصل منها على مصفوفة من عنصرين، الأول قيمته "مكتبة1" والثاني "مكتبة2". تُرجع الدالة قيمة ثنائية تكون 1 عند نجاح العملية و0 عند فشلها.
هات_المسار_الكامل_لشفرة_عنصر (getSourceFullPathForElement)
عملية هذا.هات_المسار_الكامل_لشفرة_عنصر (
    عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]
): نـص
handler this.getSourceFullPathForElement(
    element: ref[Core.Basic.TiObject]
) => String;
ترجع اسم الملف الكامل مع المسار لملف الشفرة المصدرية الذي يحتوي العنصر المعطى.
هات_مجلد_شفرة_عنصر (getSourceDirectoryForElement)
عملية هذا.هات_مجلد_شفرة_عنصر (
    عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]
): نـص
handler this.getSourceDirectoryForElement(
    element: ref[Core.Basic.TiObject]
) => String;
ترجع المسار الكامل للمجلد الذي يحتوي ملف الشفرة المصدرية الذي يحتوي العنصر المعطى.
احشر_شبم (insertAst)
عملية هذا.احشر_شبم (
    عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]،
    استعاضات: سند[تـطبيق[نـص، سند[الـقلب.أسـاسيات.كـائن_بهوية]]]
): ثـنائي
عملية هذا.احشر_شبم (
    عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]،
    استعاضات: سند[تـطبيق[نـص، سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]]]
): ثـنائي
handler this.insertAst(
    element: ref[Core.Basic.TiObject],
    interpolations: ref[Map[String, ref[Core.Basic.TiObject]]]
) => Bool;
handler this.insertAst(
    element: ref[Core.Basic.TiObject],
    interpolations: ref[Map[String, SrdRef[Core.Basic.TiObject]]]
) => Bool;
تحشر شجرة البنية المجردة المعطاة في الموضع الحالي بعد تطبيق الاستعاضات المعطاة على الشجرة المعطاة بنفس طريقة عمل الماكروهات. المعطى الأول للدالة هو الشجرة التي سيتم حشرها بينما المعطى الثاني يحمل قائمة الاستعاضات.
الموضع الذي ستُحشر فيه الشفرة هو الموضع الحالي للمعالجة التمهيدية، أي الموضع الذي ظهرت فيه عبارة `تمهيد` التي استدعت دالة `احشر_شبم`. المثال التالي يحشر عشرة تعريفات لمتغيرات من صنف صحيح أسماؤها من ن0 إلى ن9:
  عرف ع: صـحيح؛
  لكل ع = 0، ع < 5، ++ع {
      عرف عداد: نـص_بهوية = نـص.املأ("%i"، ع)؛
      نـبم.مدير_شبم.أنشئ_شبم(
          شبم { عرف ن__عداد__: صـحيح }،
          تـطبيق[نـص، سند[كـائن_بهوية]]().حدد(نـص("عداد")، عداد)
      )؛
  }
  def i: Int;
  for i = 0, i < 10, ++i {
      def counter: TiStr = String.format("%i", i);
      Spp.astMgr.insertAst(
          ast { def n__counter__: Int },
          Map[String, ref[TiObject]]().set(String("counter"), counter)
      );
  }
أنشئ_شبم (buildAst)
عملية هذا.أنشئ_شبم (
    عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]،
    استعاضات: سند[تـطبيق[نـص، سند[الـقلب.أسـاسيات.كـائن_بهوية]]]،
    النتيجة: سند[سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]]
): ثـنائي
عملية هذا.أنشئ_شبم (
    عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]،
    استعاضات: سند[تـطبيق[نـص، سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]]]،
    النتيجة: سند[سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]]
): ثـنائي
عملية هذا.أنشئ_شبم (
    عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]،
    استعاضات: سند[تـطبيق[نـص، سند[الـقلب.أسـاسيات.كـائن_بهوية]]]
): سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]؛
handler this.buildAst(
    element: ref[Core.Basic.TiObject],
    interpolations: ref[Map[String, ref[Core.Basic.TiObject]]],
    result: ref[SrdRef[Core.Basic.TiObject]]
) => Bool;
handler this.buildAst(
    element: ref[Core.Basic.TiObject],
    interpolations: ref[Map[String, SrdRef[Core.Basic.TiObject]]],
    result: ref[SrdRef[Core.Basic.TiObject]]
) => Bool;
handler this.buildAst(
    element: ref[Core.Basic.TiObject],
    interpolations: ref[Map[String, ref[Core.Basic.TiObject]]]
): SrdRef[Core.Basic.TiObject];
هذه الدالة مشابهة لدالة `احشر_شبم` غير أنها تنشئ شجرة البنية المجردة وترجعها للمستدعي بدل أن تحشرها مباشرة في الموضع الحالي للمعالجة التميهدية. يمكن للمستخدم لاحقًا أن يحشر النتيجة المستلمة في الموضع الحالي باستخدام دالة `احشر_شبم`. المثال التالي تعديل على المثال أعلاه ليستخدم هذه الدالة وليضيف أيضًا تصفيرًا للمتغيرات التي يعرفها. المثال ينشئ تعريفًا ثم يستخدم التعريف الناتج كاستعاضة في استدعاء لاحق لدالة `احشر_شبم`:
  عرف ع: صـحيح؛
  لكل ع = 0، ع < 5، ++ع {
      عرف عداد: نـص_بهوية = نـص.املأ("%i"، ع)؛
      عرف نتيجة: سـندنا[كـائن_بهوية]؛
      نـبم.مدير_شبم.أنشئ_شبم(
          شبم { عرف ن__عداد__: صـحيح }،
          تـطبيق[نـص، سند[كـائن_بهوية]]().حدد(نـص("عداد")، عداد)،
          نتيجة
      )؛
      نـبم.مدير_شبم.احشر_شبم(
          شبم{
              تعريف؛
              ن__عداد__ = 0؛
          }،
          تـطبيق[نـص، سند[كـائن_بهوية]]()
              .حدد(نـص("عداد")، عداد)
              .حدد(نـص("تعريف")، نتيجة)
      )؛
  }
  def i: Int;
  for i = 0, i < 10, ++i {
      def counter: TiStr = String.format("%i", i);
      def result: SrdRef[TiObject];
      Spp.astMgr.buildAst(
          ast { def n__counter__: Int },
          Map[String, ref[TiObject]]().set(String("counter"), counter),
          result
      );
      Spp.astMgr.insertAst(
          ast {
              definition;
              n__counter = 0;
          },
          Map[String, ref[TiObject]]()
              .set(String("counter"), counter)
              .set(String("definition"), result)
      );
  }
هات_مالك_عبارة_التمهيد_الحالية (getCurrentPreprocessOwner)
عملية هذا.هات_مالك_عبارة_التمهيد_الحالية (): سند[الـقلب.أسـاسيات.كـائن_بهوية]
handler this.getCurrentPreprocessOwner(): ref[Core.Basic.TiObject];
ترجع هذه الدالة سندًا لعنصر شبم الذي يملك عبارة التمهيد قيد التنفيذ.
هات_محشر_عبارة_التمهيد_الحالية (getCurrentPreprocessInsertionPosition)
عملية هذا.هات_محشر_عبارة_التمهيد_الحالية (): صـحيح
handler this.getCurrentPreprocessInsertionPosition(): Int;
ترجع هذه الدالة التسلسل (ضمن مالك عبارة التمهيد الحالية) الذي ستُحشر عنده عناصر شبم عند استدعاء دالة `احشر_شبم`.
هات_نطاق_المتغير (getVariableDomain)
عملية هذا.هات_نطاق_المتغير (
    عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]
): صـحيح
handler this.getVariableDomain(element: ref[Core.Basic.TiObject]) => Int;
ترجع هذه الدالة قيمة توضح النطاق الذي عُرف فيه المتغير المعطى للدالة. الناتج واحد هذه القيم:
  عرف نـطاق_التعريف: {
      عرف _دالة_:  0؛ // المتغير معرَّف داخل دالة كمتغير محلي.
      عرف _كائن_:  1؛ // المتغير عضو في كائن.
      عرف _عمومي_: 2؛ // المتغير عمومي أو متغير مشترك داخل دالة.
  }
  def DefinitionDomain: {
      def FUNCTION: 0; // Var is a function local variable.
      def OBJECT:   1; // Var is a class member.
      def GLOBAL:   2; // Var is a global or shared variable.
  }
تتبع_الصنف (traceType)
عملية هذا.تتبع_الصنف (عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]): سند[نـبم.شـبم.صـنف]
handler this.traceType(element: ref[Core.Basic.TiObject]) => ref[Spp.Ast.Type];
تتبع هذه الدالة الصنف المشار إليه بعنصر ش.ب.م المعطى وترجع ذلك الصنف.
استنبط_صنف_الناتج (computeResultType)
عملية هذا.استنبط_صنف_الناتج (
    عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]،
    ناتج: سند[سند[الـقلب.أسـاسيات.كـائن_بهوية]]،
    الناتج_قيمة: سند[ثـنائي]
): سند[ثـنائي]
handler this.computeResultType(
    element: ref[Core.Basic.TiObject],
    result: ref[ref[Core.Basic.TiObject]],
    resultIsValue: ref[Bool]
) => Bool;
تستنبط هذه الدالة الناتج من التركيب المعطى وترجعه. الناتج قد يكون صنفًا وقد يكون أي تعريف آخر مثل وحدة أو صنف. المعطى الأخير يخبرك إن كان الناتج قيمة (مثلاً متغير من الصنف المعطى) أم الصنف نفسه (أي يخبرك فيما لو كان التركيب معرفا لصنف أم معرفًا لمتغير من ذلك الصنف).
كرر_شبم (cloneAst)
عملية هذا.كرر_شبم (
    عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]
): مـتم.سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]؛
عملية هذا.كرر_شبم (
    عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]،
    عنصر_موقع_الشفرة_المصدرية: سند[الـقلب.أسـاسيات.كـائن_بهوية]
): مـتم.سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]؛
handler this.cloneAst(element: ref[Core.Basic.TiObject]): Srl.SrdRef[Core.Basic.TiObject] {
    return this.cloneAst(element, nullRef[Core.Basic.TiObject]);
}
handler this.cloneAst(
    element: ref[Core.Basic.TiObject], sourceLocationNode: ref[Core.Basic.TiObject]
): Srl.SrdRef[Core.Basic.TiObject];
تنسخ هذه الدالة شجرة الكائنات المعطاة. النسخة الثانية من هذه الدالة تتيح لك إضافة موقع في الشفرة المصدرية إلى مكدس مواقع الشفرة المصدرية المرتبطة بالشجرة المولدة. المعطى الثاني في النسخة الثانية ليس موقع الشفرة المصدرية المراد إضافته إلى المكدس وإنما عنصر ش.ب.م المراد أخذ الموقع منه.
أدرج_بيانات (dumpData)
عملية هذا.أدرج_بيانات (عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية])؛
handler this.dumpData(obj: ref[Core.Basic.TiObject]);
تطبع شجرة البيانات المعطاة في الطرفية بصيغة نصية.
هات_صنف_السند_ل (getReferenceTypeFor)
عملية هذا.هات_صنف_السند_ل (
    صنف_شبم: سند[الـقلب.أسـاسيات.كـائن_بهوية]
): سند[نـبم.شـبم.صـنف_سند]؛
handler this.getReferenceTypeFor(
    astType: ref[Core.Basic.TiObject]
): ref[Spp.Ast.ReferenceType];
ترجع صنف السند للصنف المعطى.
حاول_جلب_صنف_المحتوى_العميق (tryGetDeepReferenceContentType)
عملية هذا.حاول_جلب_صنف_المحتوى_العميق (
    صنف_شبم: سند[نـبم.شـبم.صـنف]
): سند[نـبم.شـبم.صـنف]؛
handler this.tryGetDeepReferenceContentType(
    astType: ref[Spp.Ast.Type]
): ref[Spp.Ast.Type];
ترجع صنف المحتوى للصنف المعطى. إن كان الصنف المعطى سندا فإن الدالة ترجع المحتوى الذي يشير إليه ذلك السند، وإلا فإنها ترجع الصنف نفسه. إن كان الصنف المعطى سندا لسند فإن الدالة تستمر بالبحث عن المحتوى بشكل تعاودي (recursive) حتى تصل إلى صنف غير سند فترجعه.

أصناف شجرة البنية المجردة (AST)

الأصناف
معرف داخل الوحدة نـبم.شـبم (Spp.Ast).
  • صـنف (Type)
    مُشتق من عـقدة (Node).
    الجذر لكل الأصناف في لغة الأسس.
  • صـنف_بيانات (DataType)
    مُشتق من صـنف.
    الجذر لكل أصناف البيانات.
  • صـنف_صحيح (IntegerType)
    مُشتق من صـنف_بيانات.
  • صـنف_عائم (FloatType)
    مُشتق من صـنف_بيانات.
  • صـنف_مصفوفة (ArrayType)
    مُشتق من صـنف_بيانات.
  • صـنف_مؤشر (PointerType)
    مُشتق من صـنف_بيانات.
  • صـنف_سند (ReferenceType)
    مُشتق من صـنف_بيانات.
  • صـنف_عدم (VoidType)
    مُشتق من صـنف_بيانات.
  • صـنف_مستخدم (UserType)
    مُشتق من صـنف_بيانات.
  • صـنف_دالة (FunctionType)
    مُشتق من صـنف.
مؤثرات
معرف داخل الوحدة نـبم.شـبم (Spp.Ast).
مُشتق من عـقدة.
  • مـؤثر_إشارة_لشبم (AstRefOp)
  • مـؤثر_تمثيل (CastOp)
  • مـؤثر_تهيئة (InitOp)
  • مـؤثر_إتلاف (TerminateOp)
  • مـؤثر_التالي (NextArgOp)
  • مـؤثر_تتبع (DerefOp)
  • مـؤثر_تعطيل_التتبع (NoDerefOp)
  • مـؤثر_محتوى (ContentOp)
  • مـؤثر_مؤشر (PointerOp)
  • مـؤثر_حجم (SizeOp)
  • مـؤثر_صنف (TypeOp)
  • مـؤثر_استخدم_في (UseInOp)
عبارات
معرف داخل الوحدة نـبم.شـبم (Spp.Ast).
مُشتق من عـقدة.
  • عـبارة_إذا (IfStatement)
  • عـبارة_بينما (WhileStatement)
  • عـبارة_لكل (ForStatement)
  • عـبارة_أكمل (ContinueStatement)
  • عـبارة_اقطع (BreakStatement)
  • عـبارة_ارجع (ReturnStatement)
  • عـبارة_تمهيد (PreprocessStatement)
  • عـبارة_ترجمة_قبلية (PreGenTransformStatement)
أخرى
معرف داخل الوحدة نـبم.شـبم (Spp.Ast).
مُشتق من عـقدة.
  • قـالب (Template)
  • تـعريف_معطى_قالب (TemplateVarDef)
  • مـتن (Block)
  • دالـة (Function)
  • مـاكرو (Macro)
  • وحـدة (Module)
  • مـتغير (Variable)
  • رزمـة_معطيات (ArgPack)
  • إيـعاز_شبم_حرفي (AstLiteralCommand)
  • إشـارة_لهذا_الصنف (ThisTypeRef)

معالجة شجرة البنية المجردة


قابلية برامج الأسس على قراءة وإنشاء شجرة البنية المجردة أثناء التنفيذ تمكن المبرمج من تطوير اللغة من داخل برنامجه بإضافة قواعد جديدة لترجمة الشفرة المصدرية. في المثال التالي نعرف ماكرو يترجم التركيب المعطى إلى سلسلة محارف تحتوي عبارة الشرط، مع استبدال المتغيرات بقيمها الحقيقية أثناء التنفيذ.
  اشمل "مـتم/طـرفية"؛
  اشمل "مـتم/سندات"؛
  اشمل "مـتم/نـظام"؛
  اشمل "الـقلب/بـيانات"؛
  اشمل "مـتم/نـص"؛
  اشمل "مـتم/تـطبيق"؛
  اشمل "نـبم"؛

  استخدم مـتم؛
  استخدم الـقلب.أسـاسيات؛
  استخدم الـقلب.بـيانات؛
  استخدم الـقلب.بـيانات.شـبم؛
  عرف سـندنا_لكائن_بهوية: لقب سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]؛

  دالة أنشئ_حيثما (كائن: سند[كـائن_بهوية]): سـندنا_لكائن_بهوية {
      عرف نتيجة: سـندنا_لكائن_بهوية؛
      إذا كائن~مؤشر == 0 {
          نـظام.فشل(1، "أنشئ_حيثما: الكائن معدوم.\ج")؛
      }

      إذا أمشتق_من[كائن، مـؤثر_مقارنة] {
          عرف ربط: سند[ربـط](هات_وسيط[كائن، ربـط])؛
          عرف حاوية_تطبيق: سند[احـتواء_تطبيقي](هات_وسيط[كائن، احـتواء_تطبيقي])؛
          إذا !نـبم.مدير_شبم.أنشئ_شبم(
              شبم { نـص("{{اسم}}") + نـص(" {{مؤثر}} '") + القيمة + نـص("'") }،
              تـطبيق[نـص، سند[كـائن_بهوية]]()
                  .حدد(نـص("اسم")، حاوية_تطبيق.هات_عنصرا("first"))
                  .حدد(نـص("مؤثر")، ربط.هات_عضوا("type"))
                  .حدد(نـص("القيمة")، حاوية_تطبيق.هات_عنصرا("second"))،
              نتيجة
          ) {
              نـظام.فشل(1، "أنشئ_حيثما/مـؤثر_مقارنة: خطأ\ج")؛
          }
      } وإلا إذا أمشتق_من[كائن، مـؤثر_منطقي] {
          عرف ربط: سند[ربـط](هات_وسيط[كائن، ربـط])؛
          عرف حاوية_تطبيق: سند[احـتواء_تطبيقي](هات_وسيط[كائن، احـتواء_تطبيقي])؛
          عرف مؤثر: نـص_بهوية؛
          إذا مثل_سند[ربط.هات_عضوا("type")، نـص_بهوية].القيمة == "and" مؤثر = "و" وإلا مؤثر = "أو"؛
          إذا !نـبم.مدير_شبم.أنشئ_شبم(
              شبم { (شرط1) + نـص(" {{مؤثر}} ") + (شرط2) }،
              تـطبيق[نـص، سند[كـائن_بهوية]]()
                  .حدد(نـص("شرط1")، أنشئ_حيثما(حاوية_تطبيق.هات_عنصرا("first")).كائن)
                  .حدد(نـص("مؤثر")، مؤثر)
                  .حدد(نـص("شرط2")، أنشئ_حيثما(حاوية_تطبيق.هات_عنصرا("second")).كائن)،
              نتيجة
          ) {
              نـظام.فشل(1، "أنشئ_حيثما/مـؤثر_منطقي: خطأ\ج")؛
          }
      } وإلا إذا أمشتق_من[كائن، قـوس] {
          عرف حاوية_تطبيق: سند[احـتواء_تطبيقي](هات_وسيط[كائن، احـتواء_تطبيقي])؛
          إذا !نـبم.مدير_شبم.أنشئ_شبم(
              شبم { نـص("(") + (شرط) + نـص(")") }،
              تـطبيق[نـص، سند[كـائن_بهوية]]()
                  .حدد(نـص("شرط")، أنشئ_حيثما(حاوية_تطبيق.هات_عنصرا("operand")).كائن)،
              نتيجة
          ) {
              نـظام.فشل(1، "أنشئ_حيثما/قـوس: خطأ\ج")؛
          }
      } وإلا {
          إذا !نـبم.مدير_شبم.أنشئ_شبم(
              كائن،
              تـطبيق[نـص، سند[كـائن_بهوية]]()،
              نتيجة
          ) {
              نـظام.فشل(1، "فشل بناء الشرط.\ج")؛
          }
      }
      أرجع نتيجة؛
  }

  ماكرو حيثما [شرط] {
      تمهيد {
          إذا !نـبم.مدير_شبم.احشر_شبم(
              أنشئ_حيثما(شبم شرط).كائن
          ) {
              نـظام.فشل(1، "فشل حشر الشرط.\ج")؛
          }
      }
  }

  دالة اختبر {
      عرف الاسم_الأول: نـص("محمد")؛
      عرف الوظيفة: نـص("مهندس")؛
      عرف حيثما: نـص = حيثما[الاسم == الاسم_الأول و (الوظيفة == الوظيفة أو الوظيفة == "محامي")]؛
      طـرفية.اطبع("%s\ج"، حيثما.صوان)؛
      // نتيجة التنفيذ: الاسم == 'محمد' و (الوظيفة == 'مهندس' أو الوظيفة == 'محامي')
  }
  اختبر()؛
  import "Srl/Console";
  import "Srl/refs";
  import "Srl/System";
  import "Core/Data";
  import "Spp";

  use Srl;
  use Core.Basic;
  use Core.Data;
  use Core.Data.Ast;
  def TioSrdRef: alias SrdRef[Core.Basic.TiObject];

  func generateWhere (obj: ref[TiObject]): TioSrdRef {
      def result: TioSrdRef;
      if obj~ptr == 0 {
          System.fail(1, "generateWhere: obj is null.\n");
      }

      if isDerivedFrom[obj, ComparisonOperator] {
          def binding: ref[Binding](getInterface[obj, Binding]);
          def mapContaining: ref[MapContaining](getInterface[obj, MapContaining]);
          if !Spp.astMgr.buildAst(
              ast { String("{{name}}") + String(" {{op}} '") + val  + String("'") },
              Map[String, ref[TiObject]]()
                  .set(String("name"), mapContaining.getElement("first"))
                  .set(String("op"), binding.getMember("type"))
                  .set(String("val"), mapContaining.getElement("second")),
              result
          ) {
              System.fail(1, "generateWhere/ComparisonOperator: error\n");
          }
      } else if isDerivedFrom[obj, LogOperator] {
          def binding: ref[Binding](getInterface[obj, Binding]);
          def mapContaining: ref[MapContaining](getInterface[obj, MapContaining]);
          if !Spp.astMgr.buildAst(
              ast { (cond1) + String(" {{op}} ") + (cond2) },
              Map[String, ref[TiObject]]()
                  .set(String("cond1"), generateWhere(mapContaining.getElement("first")).obj)
                  .set(String("op"), binding.getMember("type"))
                  .set(String("cond2"), generateWhere(mapContaining.getElement("second")).obj),
              result
          ) {
              System.fail(1, "generateWhere/LogOperator: error\n");
          }
      } else if isDerivedFrom[obj, Bracket] {
          def mapContaining: ref[MapContaining](getInterface[obj, MapContaining]);
          if !Spp.astMgr.buildAst(
              ast { String("(") + (cond) + String(")") },
              Map[String, ref[TiObject]]()
                  .set(String("cond"), generateWhere(mapContaining.getElement("operand")).obj),
              result
          ) {
              System.fail(1, "generateWhere/Bracket: error\n");
          }
      } else {
          if !Spp.astMgr.buildAst(
              obj,
              Map[String, ref[TiObject]](),
              result
          ) {
              System.fail(1, "Failed to build condition.\n");
          }
      }
      return result;
  }

  macro where [condition] {
      preprocess {
          if !Spp.astMgr.insertAst(
              generateWhere(ast condition).obj
          ) {
              System.fail(1, "Failed to insert condition.\n");
          }
      }
  }

  func test {
      def firstName: String("Mohammed");
      def position: String("Engineer");
      def query: String = where[name == firstName && (pos == position || pos == "Lawyer")];
      Console.print("%s\n", query.buf);
      // Execution output: name == 'Mohammed' && (pos == 'Engineer' || pos == 'Lawyer')
  }
  test();