دالة رئيسي { عرف م: مـصفوفة[صـحيح] = هات_مصفوفة()؛ م.أضف(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.
عملية هذا.هات_الطول (): صـحيح_متكيف؛
handler this.getLength (): ArchInt;ترجع عدد العناصر في المصفوفة.
عملية هذا.هات_حجم_الصوان (): صـحيح_متكيف؛
handler this.getBufSize (): ArchInt;ترجع عدد العناصر التي تتسع لها الذاكرة المحجوزة حاليًا. عند تجاوز هذا الحجم يقوم الكائن تلقائيا بتوسيع حجز الذاكرة.
عملية هذا.عين (م: سند[مـصفوفة[صـنف_المحتوى]])؛
handler this.assign (a: ref[Array[ContentType]]);تعيين محتوى جديد للمصفوفة من مصفوفة أخرى. هذه الدالة لا تنسخ المحتوى من المصفوفة الأخرى وإنما تتشارك معها بنفس الصوان لحين حاجة إحدى المصفوفتين لتغيير المحتوى، حينها تنسخ تلك المصفوفة الصوان وتنتهي المشاركة.
عملية هذا.أضف (م: صـنف_المحتوى)؛ عملية هذا.أضف (عدد_العناصر: صـحيح، العناصر: ...صـنف_المحتوى)؛ عملية هذا.أضف (م: مـصفوفة[صـنف_المحتوى])؛
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.
عملية هذا.احشر (موقع: صـحيح_متكيف، عنصر: صـنف_المحتوى)؛
handler this.insert (index: ArchInt, element: ContentType);إضافة عنصر جديد إلى المصفوفة في الموقع المحدد بعد توسيع حجز الذاكرة إن وجب. إذا كان المحتوى مشارك مع مصفوفة أخرى تقوم الدالة بنسخ المحتوى إلى صوان جديد.
عملية هذا.أزل (موقع: صـحيح_متكيف)؛
handler this.remove (index: ArchInt);إزالة العنصر الذي في الموقع المحدد. إذا كان المحتوى مشارك مع مصفوفة أخرى تقوم الدالة بنسخ المحتوى إلى صوان جديد.
عملية هذا.اجتزئ (بداية: صـحيح_متكيف، عدد: صـحيح_متكيف)؛
handler this.slice (start: ArchInt, count: ArchInt);نسخ جزء من المصفوفة وإرجاعه كمصفوفة جديدة. يبدأ النسخ من العنصر `بداية` ويستمر حتى نسخ `عدد` من العناصر، أو حتى وصول نهاية المصفوفة (إن وصلنا نهاية المصفوفة قبل استيفاء العدد المطلوب).
عملية هذا.فرّغ ()؛
handler this.clear ();إزالة جميع العناصر من المصفوفة. إذا كان المحتوى غير مشارَك مع مصفوفة أخرى سيُحرر الصوان.
دالة رئيسي { عرف نص: نـص = هات_نص()؛ نص += " والحمد لله"؛ // هنا يتم تمديد حجم الذاكرة المحجوزة عرف نص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]]. }يحتوي الصنف `نـص` على المتغيرات والدالات التالية:
عرف صوان: مؤشر[مصفوفة[مـحرف]]؛
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تقارن هذا النص مع النص المعطى.
1: عملية هذا.هات_الطول (): صـحيح_متكيف؛ 2: دالة هات_الطول (م: مؤشر[مصفوفة[مـحرف]]): صـحيح_متكيف؛
1: handler this.getLength (): ArchInt; 2: func getLength (p: ptr[array[Char]]): ArchInt;1. ترجع طول هذا النص.
عملية هذا.احجز (صـحيح_متكيف)؛
handler this.alloc (ArchInt);تقوم بحجز مسبق للذاكرة. تمكن هذه الدالة المستخدم من حجز الذاكرة مسبقًا قبل تعبئتها بالمحتوى باستخدام التعامل المباشر مع صوان هذا النص. تنفع هذه الطريقة عند التعامل مع مكتبات تتعامل مع مؤشرات المحارف، مع الاستفادة من خاصيات إدارة الذاكرة التي يوفرها هذا الصنف.
عملية هذا.غير_الحجز (صـحيح_متكيف)؛
handler this.realloc (ArchInt);تغير حجم الذاكرة المحجوزة لهذا النص. تمكن هذه الدالة المستخدم من تغيير حجم الذاكرة المحجوزة قبل تغيير المحتوى باستخدام التعامل المباشر مع صوان هذا النص.
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. تعيين محتوى جديد للنص من نص آخر. هذه الدالة لا تنسخ محتوى النص الآخر وإنما تتشارك معه بنفس الصوان لحين حاجة أحد النصين لتغيير المحتوى، حينها ينسخ ذاك النص الصوان وتنتهي المشاركة.
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. ألحق الصوان المعطى بنهاية محتوى هذا النص.
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 بالمؤثر +.
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 إذا فشل العثورة عليها.
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]];هذه الدالات مشابهة لدالات `جد` لكنهن تبدأن البحث من نهاية النص بدل البحث من البداية.
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 إذا كانا متطابقين.
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. تبدل جزءا من النص بآخر وترجع الناتج في نص جديد.
عملية هذا.شذب (): نـص؛
handler this.trim (): String;تزيل الفراغات (المحارف غير المرئية سواء محرف المسافة أو غيرها) من طرفي النص وترجع الناتج في نص جديد.
عملية هذا.شذب_البداية (): نـص؛
handler this.trimStart (): String;مشابهة لدالة `شذب` لكنها تشذب البداية فقط.
عملية هذا.شذب_النهاية (): نـص؛
handler this.trimEnd (): String;مشابهة لدالة `شذب` لكنها تشذب النهاية فقط.
عملية هذا.كبر (): نـص؛
handler this.toUpperCase (): String;تستبدل الأحرف اللاتينية الصغيرة بمثيلاتها الكبيرة وترجع الناتج في نص جديد.
عملية هذا.صغر (): نـص؛
handler this.toLowerCase (): String;تستبدل الأحرف اللاتينية الكبيرة بمثيلاتها الصغيرة وترجع الناتج في نص جديد.
عملية هذا.اجتزئ (بداية: صـحيح_متكيف، عدد: صـحيح_متكيف): نـص؛
handler this.slice (start: ArchInt, count: ArchInt): String;ترجع جزءا من النص الحالي كنص جديد.
عملية هذا.قطع (فاصل: مؤشر[مصفوفة[مـحرف]]): مـصفوفة[نـص]؛
handler this.split (separator: ptr[array[Char]]): Array[String];ترجع أجزاء النص الحالي التي يفصلها الفاصل المعطى. إذا لم يوجد هذا النص فإنها ترجع عنصرا واحدا يحتوي النص كاملا.
دالة ادمج (أجزاء: مـصفوفة[نـص]، فاصل: مؤشر[مصفوفة[مـحرف]]): نـص؛
func merge (parts: Array[String], separator: ptr[array[Char]]): String;ترجع نصًا جديدا يحتوى الأجزاء المعطاة مفصولة بالفاصل المعطى.
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. تنسخ سلسلة المحارف من المصدر إلى المقصد. يجب على المستخدم ضمان أن تكون الذاكرة المحجوزة للمقصد كافية لاستيعاب كامل مصفوفة المصدر.
دالة امسح (المصدر: مؤشر[مصفوفة[مـحرف]]، نسق: مؤشر[مصفوفة[مـحرف]]، ...أيما): صـحيح؛
func scan (source: ptr[array[Char]], fmt: ptr[array[Char]], ...any): Int;امسح سلسلة المحارف المعطاة بحثًا عن العناصر المحددة في النسق وإرجاع هذه العناصر في المعطيات الملحقة بعد النسق. هذه الدالة مطابقة لدالة النظام sscanf.
دالة أهو_مسافة (م: مـحرف): ثـنائي؛
func isSpace (c: Char): Bool;تخبرك فيما إذا كان المحرف المعطى مسافة أو إزاحة (tab) أو سطر جديد أو محرف الرجوع لبداية السطر.
دالة أمتطابق (نص1: مؤشر[مصفوفة[مـحرف]]، نص2: مؤشر[مصفوفة[مـحرف]]): ثـنائي؛
func isEqual (str1: ptr[array[Char]], str2: ptr[array[Char]]): Bool;تخبرك فيما لو كانت سلسلتا المحارف المعطاتان متطابقتين.
دالة أزل (محارف: مؤشر[مصفوفة[مـحرف]]، م: مـحرف): مؤشر[مصفوفة[مـحرف]]؛
func remove (chars: ptr[array[Char]], c: Char): ptr[array[Char]];تزيل كل مطابقة للمحرف المعطى من سلسلة المحارف المعطاة. إزالة المحرف تؤدي إلى تزحيف المحارف التي بعده لتحل محله.
دالة املأ (صيغة: مؤشر[مصفوفة[مـحرف]]، قيم: ...أيما): نـص؛
func format (fmt: ptr[array[Char]], values: ...any): String;تنشئ نصًا جديدًا من الصيغة المعطاة بعد ملئها بالقيم المطاة. تعمل هذه الدالة بشكل مشابه لدالة sprintf، وذلك باستبدال الرموز البادئة ب% في الصيغة بقيمة من قائمة المعطيات تطابق الصنف المحدد. الرمز % يتبعه محرف يدل على صنف القيمة المعطاة، وهي كالتالي:
دالة اقرأ_صحيح (نص: مؤشر[مصفوفة[مـحرف]]): صـحيح[64]؛
func parseInt (str: ptr[array[Char]]): Int[64];تقرأ عددًا صحيحًا من سلسلة المحارف المعطاة وترجعه.
دالة اقرأ_عائم (نص: مؤشر[مصفوفة[مـحرف]]): عـائم[64]؛
func parseFloat (str: ptr[array[Char]]): Float[64];تقرأ عددًا عائمًا من سلسلة المحارف المعطاة وترجعه.
دالة اقرأ_محرف_هكس (م: مـحرف): صـحيح؛
func parseHexDigit (c: Char): Int;تحول محرفا يمثل رقمًا ست عشريًا إلى قيمته الرقمية.
صنف مـنشئ_نص [مكون_الملء: سند_شبم = _مكون_فارغ] { عملية هذا~هيئ()؛ عملية هذا~هيئ(الحجم_الأولي: صـحيح_متكيف, الزيادة: صـحيح_متكيف)؛ عملية هذا~هيئ(نص: نـص, الزيادة: صـحيح_متكيف)؛ عملية هذا.الحق (صوان: مـؤشر_محارف)؛ عملية هذا.ألحق (صوان: مـؤشر_محارف, طول_الصوان: صـحيح_متكيف)؛ عملية هذا.ألحق (م: مـحرف)؛ عملية هذا.ألحق (ص: صـحيح[64])؛ عملية هذا.ألحق (ع: عـائم[64])؛ عملية هذا.املأ(صيغة: مـؤشر_محارف, معطيات: ...أيما)؛ عملية هذا.فرغ()؛ عملية هذا.هات_الطول()؛ عملية هذا += مـؤشر_محارف؛ عملية هذا += مـحرف؛ عملية هذا += صـحيح[64]؛ عملية هذا += عـائم[64]؛ عملية هذا~مثل[سند[نـص]]؛ }
class StringBuilder [formatMixin: ast_ref = _emptyMixin] { handler this~init(); handler this~init(initialSize: ArchInt, growSize: ArchInt); handler this~init(str: String, growSize: ArchInt); handler this.append (buf: CharsPtr); handler this.append (buf: CharsPtr, bufLen: ArchInt); handler this.append (c: Char); handler this.append (i: Int[64]); handler this.append (f: Float[64]); handler this.format(fmt: ptr[array[Char]], args: ...any); handler this.clear(); handler this.getLength(); handler this += CharsPtr this.append(value); handler this += Char this.append(value); handler this += Int[64] this.append(value); handler this += Float[64] this.append(value); handler this~cast[ref[String]]; }المثال التالي يوضح استخدام هذا الصنف:
دالة رئيسي { عرف من: مـنشئ_نص( 1024، // احجز 1024 بايت من الذاكرة مسبقا 512 // وسع الذاكرة بمقدار 512 بايت كلما امتلأت )؛ من.ألحق("ناتج ")؛ من.املأ("7 + 7 = %i\ج"، 7 + 7)؛ عرف ن: نـص = من؛ طـرفية.اطبع(ن)؛ // سيطبع: ناتج 7 + 7 = 14 }
func main { def sb: StringBuilder( 1024, // preallocate 1024 bytes 512 // enlarge memory block by 512 whenever it's full ); sb.append("Result of "); sb.format("7 + 7 = %i\n", 7 + 7); def s: String = sb; Console.print(s); // Prints: Result of 7 + 7 = 14 }
عملية هذا~هيئ()؛ عملية هذا~هيئ(الحجم_المبدئي: صـحيح_متكيف، الزيادة: صـحيح_متكيف)؛ عملية هذا~هيئ(نص: نـص، الزيادة: صـحيح_متكيف)؛
handler this~init(); handler this~init(initialSize: ArchInt, growSize: ArchInt); handler this~init(str: String, growSize: ArchInt);الصيغة الثانية تهيئ الكائن بحجز ذاكرة مسبقًا بالحجم المعطى، والمعطى الثاني يحدد مقدار الزيادة في حجم الذاكرة المحجوزة كلما امتلأ الصوان. حتى لو احتاج الكائن بايتا إضافيا واحدا فإنه سيوسع الذاكرة بهذا المقدار لكي يقلل من عمليات حجز الذاكرة.
عرف مـكون_منشئ_نص { @بنية["gd"] عملية هذا.املأ_ختما_زمنيا(خز: صـحيح[64]) { هذا.ألحق(وقـت.إلى_نص(خز))؛ } } دالة رئيسي { عرف من: مـنشئ_نص[مـكون_منشئ_نص](1024، 512)؛ عرف خز: صـحيح[64] = ...؛ من.املأ("تاريخ اليوم هو %gd\ج"، خز)؛ ... }
def StringBuilderMixin { @format["gd"] handler this.formatTimestamp(ts: Int[64]) { this.append(Time.toString(ts)); } } func main { def sb: StringBuilder[StringBuilderMixin](1024, 512); def timestamp: Int[64] = ...; sb.format("Today's date is %gd", timestamp); ... }
دالة رئيسي { عرف ت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);الصيغة الأولى تهيئ تطبيقًا فارغًا مع الاختيار بين استخدام فهرس من عدمه. استخدام الفهرس يسرع البحث عن العناصر في التطبيق، على حساب استهلاك الذاكرة وتبطيء إضافة العناصر.
عرف مفاتيح: مـصفوفة[صـنف_المفتاح]؛
def keys: Array[KeyType];مصفوفة المفاتيح التي في هذا التطبيق.
عرف قيم: مـصفوفة[صـنف_المحتوى]؛
def values: Array[ValueType];مصفوفة المحتويات التي في هذا التطبيق.
عملية هذا.هات_الطول (): صـحيح_متكيف؛
handler this.getLength (): ArchInt;ترجع عدد العناصر في التطبيق.
عملية هذا.المفتاح_عند (صـحيح_متكيف): سند[صـنف_المفتاح]؛
handler this.keyAt (ArchInt): ref[KeyType];ترجع سندًا للمفتاح الذي عند الموقع المطلوب.
عملية هذا.القيمة_عند (صـحيح_متكيف): سند[صـنف_المحتوى]؛
handler this.valAt (ArchInt): ref[ValueType];ترجع سندًا للقيمة التي عند الموقع المطلوب.
عملية هذا.حدد ( مفتاح: صـنف_المفتاح، قيمة: صـنف_القيمة ): سند[تـطبيق[صـنف_المفتاح، صـنف_المحتوى]]؛
handler this.set ( key: KeyType, value: ValueType ): ref[Map[KeyType, ValueType]];تحدد قيمة للمفتاح المعطى. إن كان لهذا المفتاح قيمة فإنها ستبدل بالقيمة الجديدة. هذه الدالة ترجع سندا للتطبيق نفسه، ما يمكن المستخدم من سلسلة عدة عمليات تحديد في جملة واحدة.
عملية هذا.حدد_عند ( تسلسل: صـحيح_متكيف، قيمة: صـنف_القيمة ): سند[تـطبيق[صـنف_المفتاح، صـنف_المحتوى]]؛
handler this.setAt ( index: ArchInt, value: ValueType ): ref[Map[KeyType, ValueType]];تحدد قيمة جيدة عند التسلسل المعطى، أي تغيير القيمة باستخدام تسلسلها بدلاً من مفتاحها. هذه الدالة ترجع سندا للتطبيق نفسه، ما يمكن المستخدم من سلسلة عدة عمليات تحديد في جملة واحدة.
عملية هذا.احشر (تسلسل: صـحيح_متكيف، مفتاح: صـنف_المفتاح، قيمة: صـنف_القيمة)؛
handler this.insert (index: ArchInt, key: KeyType, value: ValueType);تضيف مفتاحًا جديدًا وقيمته عند التسلسل المحدد.
عملية هذا.أزل (مفتاح: صـنف_المفتاح): ثـنائي؛
handler this.remove (key: KeyType): Bool;تزيل المفتاح المحدد وقيمته. ترجع 1 إذا أُزيل المفتاح، و 0 إذا لم يوجد المفتاح ابتداءًا.
عملية هذا.أزل_عند (تسلسل: صـحيح_متكيف)؛
handler this.removeAt (index: ArchInt);تزيل المفتاح عند التسلسل المحدد وقيمتَه.
عملية هذا.فرغ ()؛
handler this.clear ();تفرغ كل المحتوى وتبدأ بتطبيق فارغ.
عملية هذا.جد_الموقع (مفتاح: صـنف_المفتاح): صـحيح_متكيف؛
handler this.findPos (key: KeyType): ArchInt;ترجع تسلسل المفتاح المعطى، أو -1 إن لم يوجد هذا المفتاح.
دالة رئيسي { عرف س: سـندنا[صـنفي] = سـندنا[صـنفي].أنشئ()؛ عرف ص: سـندنا[صـنفي] = س؛ // الآن كلا السندين يشيران لنفس الكائن وعداده الآن 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. }يحتوي الصنف `سـندنا` على المتغيرات والدالات التالية:
عملية هذا.احجز (): سند[صـنف_الكائن]؛ دالة احجز (): سـندنا[صـنف_الكائن]؛
handler this.alloc (): ref[ObjType]; func alloc (): SrdRef[ObjType];تقوم هذه الدالة بحجز ذاكرة للكائن، لكنها لا تهيئ الكائن وتترك للمستخدم مسؤولية التهيئة باستخدام `~هيئ`.
عملية هذا.أنشئ ()؛ دالة أنشئ (): سـندنا[صـنف_الكائن]؛
handler this.construct (); func construct (): SrdRef[ObjType];تقوم هذه الدالة بحجز ذاكرة للكائن وتهيئته أيضًا. تهيئة الكائن تتم دون أي معطيات لذا لاستخدام هذه الدالة يحتاج الكائن لتمكين التهيئة دون معطيات. إذا احتجت تهيئة الكائن بمعطيات فستحتاج لاستخدام دالة `احجز` بدلًا من هذه الدالة ثم التهيئة يدويا باستخدام `~هيئ`.
عملية هذا.تملك (كائن: سند[صـنف_الكائن])؛ دالة تملك (كائن: سند[صـنف_الكائن]): سـندنا[صـنف_الكائن]؛
handler this.own (obj: ref[ObType]); func own (obj: ref[ObjType]): SrdRef[ObjType];هذه الدالة تعين كائن هذا السند بكائن متوفر سلفًا. بعد استدعاء هذه الدالة يتولى هذا السند مسؤولية تحرير الكائن تلقائيًا. يجب تجنب هذه الدالة إذا لم يكن الكائن المعطى محجوزًا ديناميكيًا أو إذا تولت شفرة أخرى مسؤولية تحرير الكائن لأن ذلك سيؤدي إلى segmentation fault.
عملية هذا.حرر()؛
handler this.release();تصفر هذا السند وإذا كان هذا آخر سند يشير إلى الكائن فتُحرر الكائن قبل تصفير السند.
عملية هذا.عين (س: سند[سـندنا[صـنف_الكائن]])؛ عملية هذا.عين (س: سند[سـندهم[صـنف_الكائن]])؛ عملية هذا.عين (ع: سند[عـداد_السندات]، ك: سند[صـنف_الكائن])؛
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.
عملية هذا.أهو_عدم(): ثـنائي؛
handler this.isNull(): Bool;تتحقق فيما لو كان السند يشير لعدم، أي فيما لو كان مؤشره صفرًا.
عملية هذا.حرر()؛
handler this.release();تصفر هذا السند دون تغيير شيء في عداد السندات.
عملية هذا.عين (س: سند[سـندنا[صـنف_الكائن]])؛ عملية هذا.عين (س: سند[سـندهم[صـنف_الكائن]])؛ عملية هذا.عين (ع: سند[عـداد_السندات]، ك: سند[صـنف_الكائن])؛
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.
عملية هذا.أهو_عدم(): ثـنائي؛
handler this.isNull(): Bool;تتحقق فيما لو كان السند يشير لعدم، أي فيما لو كان مؤشره صفرًا.
عرف س: سـندي[صـنفي]؛ س.أنشئ()؛ عرف ص: سـندي[صـنفي]؛ ص = س؛ // خطأ. س.حرر()؛ // يُحرر الكائن هنا تلقائيا.
def x: UnqRef[MyType]; x.construct(); def y: UnqRef[MyType]; y = x; // Error. x.release(); // Object will be released here.يحتوي هذا الصنف على العناصر التالية:
عملية هذا.أنشئ()؛
handler this.construct();تقوم هذه الدالة بحجز ذاكرة للكائن وتهيئته أيضًا. تهيئة الكائن تتم دون أي معطيات لذا لاستخدام هذه الدالة يحتاج الكائن لتمكين التهيئة دون معطيات.
عملية هذا.حرر()؛
handler this.release();تصفر هذا السند وتحرر الكائن.
عملية هذا.أهو_عدم(): ثـنائي؛
handler this.isNull(): Bool;تتحقق فيما لو كان السند يشير لعدم، أي فيما لو كان مؤشره صفرًا.
عملية هذا.هات_الرمز(): نـص كمؤشر؛
handler this.getCode(): String as_ptr;
عملية هذا.هات_الرسالة(): نـص كمؤشر؛
handler this.getMessage(): String as_ptr;
@حقنة عرف القيمة: صـنف_البيانات؛
@injection def value: DataType;
عرف الخطأ: سـندنا[خـطأ]؛
def error: SrdRef[Error];
عملية هذا~مثل[سند[صـنف_البيانات]] أرجع هذا.القيمة؛ عملية هذا~مثل[ثـنائي] أرجع هذا.الخطأ.أهو_عدم()؛
handler this~cast[ref[DataType]] return this.value; handler this~cast[Bool] return this.error.isNull();عملية التمثيل كـ`ثـنائي` (`Bool`) ترجع 1 إن كانت العملية ناجحة، أي إن كانت البيانات صالحة للاستخدام.
دالة نجاح (ق: صـنف_البيانات): لـا_مضمون[صـنف_البيانات]؛
func success (v: DataType): Possible[DataType];
دالة فشل (خ: سـندنا[خـطأ]): لـا_مضمون[صـنف_البيانات]؛
func failure (err: SrdRef[Error]): Possible[DataType];
@حقنة عرف القيمة: صـنف_البيانات؛
@injection def value: DataType;
عرف أهو_عدم: ثـنائي؛
def isNull: Bool;
عملية هذا~مثل[سند[صـنف_البيانات]] أرجع هذا.القيمة؛
handler this~cast[ref[DataType]] return this.value;
@تصدير[malloc] دالة احجز (حجم: صـحيح_متكيف): مؤشر؛
@expname[malloc] func alloc (size: ArchInt): ptr;مطابقة لدالة malloc من POSIX.
@تصدير[realloc] دالة أعد_الحجز (م: مؤشر، الحجم_الجديد: صـحيح_متكيف): مؤشر؛
@expname[realloc] func realloc (p: ptr, newSize: ArchInt): ptr;مطابقة لدالة realloc من POSIX.
@تصدير[aligned_alloc] دالة احجز_مرصوف (رصف: صـحيح_متكيف، حجم: صـحيح_متكيف): مؤشر؛
@expname[aligned_alloc] func allocAligned (alignment: ArchInt, size: ArchInt): ptr;مطابقة لدالة aligned_alloc من POSIX.
@تصدير[free] دالة حرر (م: مؤشر)؛
@expname[free] func free (p: ptr);مطابقة لدالة free من POSIX.
@تصدير[memcpy] دالة (مقصد: مؤشر، مصدر: مؤشر، حجم: صـحيح_متكيف): مؤشر؛
@expname[memcpy] func (target: ptr, src: ptr, size: ArchInt): ptr;مطابقة لدالة memcpy من POSIX.
@تصدير[memcmp] دالة قارن (حيز1: مؤشر، حيز2: مؤشر: حجم: صـحيح_متكيف): صـحيح؛
@expname[memcmp] func compare (s1: ptr, s2: ptr, size: ArchInt): Int;مطابقة لدالة memcmp من POSIX.
@تصدير[memset] دالة (حيز: مؤشر، قيمة: صـحيح، عدد: صـحيح_متكيف): مؤشر؛
@expname[memset] func (s: ptr, c: Int, n: ArchInt): ptr;مطابقة لدالة memset من POSIX.
دالة خصص_الحجز( احجز_مخصص: مؤشر[دالة (حجم: صـحيح_متكيف) => مؤشر]، أعد_الحجز_مخصص: مؤشر[دالة (م: مؤشر، الحجم_الجديد: صـحيح_متكيف) => مؤشر]، احجز_مرصوف_مخصص: مؤشر[دالة (رصف: صـحيح_متكيف، حجم: صـحيح_متكيف) => مؤشر]، حرر_مخصص: مؤشر[دالة (م: مؤشر)] )؛ دالة أعد_ضبط_الحجز()؛
function overrideAllocator( customAlloc: ptr[function (size: ArchInt) => ptr[Void]], customRealloc: ptr[function (p: ptr[Void], newSize: ArchInt) => ptr[Void]], customAllocAligned: ptr[function (alignment: ArchInt, size: ArchInt) => ptr[Void]], customFree: ptr[function (pointer: ptr[Void])] ); function resetAllocator();الدالات المخصصة ستحتاج الوصول المباشر لدالات الججز التابعة للنظام، والتي تحمل الأسماء التالية:
@تصدير[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];للحصول على القيمة المطلقة لرقم.
@تصدير[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];للحصول على باقي قسمة رقمين حقيقيين.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[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.
@تصدير[rand] دالة عشوائي (): صـحيح؛
@expname[rand] func random (): Int;مطابقة لدالة rand من POSIX.
@تصدير[srand] دالة جهز_العشوائية (ب: طـبيعي[32])؛
@expname[srand] func seedRandom (s: Word[32]);مطابقة لدالة srand من POSIX.
دالة هات_اعتماديات_البناء (): مـصفوفة[نـص]؛
func getBuildDependencies(): Array[String];ترجع أسماء الاعتماديات المطلوبة في حالة بناء نسخة تنفيذية من مشروع يعتمد على وحدة `شـبكة`. في حالة `شـبكة` ترجع الدالة مكتبة واحدة وهي Curl. القيمة المرجعة تحتوي المسار الكامل للملف وليس فقط الاسم لأن الأسس تعتمد على نسخة من Curl مضمنة مع مكتبات الأسس.
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: تجلب المورد المحدد بالرابط وترجعه.
دالة شفر_عنوانيا (مـؤشر_محارف): نـص؛
func uriEncode(CharsPtr): String;تشفر النص المعطى بتشفير الURI وترجع القيمة المشفرة.
دالة فك_عنوانيا (مـؤشر_محارف): نـص؛
func uriDecode(CharsPtr): String;تفك تشفير النص المعطى المشفر بتشفير الURI.
@تصدير[getchar] دالة أدخل_محرفا (): صـحيح؛
@expname[getchar] func getChar (): Int;مطابقة لدالة getchar من POSIX.
@تصدير[putchar] دالة أخرج_محرفا (محرف: صـحيح): صـحيح؛
@expname[putchar] func putChar (c: Int): Int;مطابقة لدالة putchar من POSIX.
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.
@تصدير[scanf] دالة امسح (نسق: مؤشر[مصفوفة[مـحرف]]، ...أيما): صـحيح؛
@expname[scanf] func scan (fmt: ptr[array[Char]], ...any): Int;مطابقة لدالة scanf من POSIX.
دالة أدخل_صحيح (): صـحيح؛
func getInt (): Int;تطلب من المستخدم إدخال عدد صحيح.
دالة أدخل_عائم (): عـائم؛
print getFloat (): Float;تطلب من المستخدم إدخال عدد بفاصلة عائمة.
دالة أدخل_محارف (محارف: مؤشر[مصفوفة[مـحرف]]، عدد: طـبيعي)؛
func getString (str: ptr[array[Char]], size: Word);تطلب من المستخدم إدخال سلسلة محارف.
@تصدير[usleep] دالة نم (ط: طـبيعي)؛
@expname[usleep] func sleep (w: Word);مطابقة لدالة usleep من POSIX.
@تصدير[setenv] دالة اضبط_متغير_محيطي ( اسم: مؤشر[مصفوفة[مـحرف]]، قيمة: مؤشر[مصفوفة[مـحرف]]، استبدال: صـحيح ): صـحيح؛
@expname[setenv] func setEnv ( name: ptr[array[Char]], value: ptr[array[Char]], overwrite: Int ): Int;مطابقة لدالة setenv من POSIX.
@تصدير[getenv] دالة هات_متغير_محيطي (اسم: مؤشر[مصفوفة[مـحرف]]): مؤشر[مصفوفة[مـحرف]]؛
@expname[getenv] func getEnv (name: ptr[array[Char]]): ptr[array[Char]];مطابقة لدالة getenv من POSIX.
@تصدير[system] دالة شغل (أمر: مؤشر[مصفوفة[مـحرف]]): صـحيح؛
@expname[system] func exec (cmd: ptr[array[Char]]): Int;مطابقة لدالة system من POSIX.
@تصدير[exit] دالة اخرج (رمز_الخروج: صـحيح)؛
@expname[exit] func exit (status: Int);مطابقة لدالة exit من POSIX.
صنف قـيد_مجلد { عرف نوع: صـحيح[8]؛ عرف اسم: مصفوفة[مـحرف، 256]؛ }
class DirEnt { def dType: Int[8]; def dName: array[Char, FILENAME_LENGTH]; };سجل معلومات عنصر من عناصر المجلد.
صنف اسـماء_ملفات { عرف عدد: صـحيح؛ عرف اسماء: مصفوفة[مصفوفة[مـحرف، 256]]؛ }
class FileNames { def count: Int; def names: array[array[Char, FILENAME_LENGTH]]; }قائمة بأسماء ملفات.
عرف انـتقال: { عرف _بداية_: لقب 0؛ عرف _حالي_: لقب 1؛ عرف _نهاية_: لقب 2؛ }؛
def Seek: { def SET: 0; def CUR: 1; def END: 2; };ثوابت التعامل مع دالة الانتقال.
دالة يوجد (اسم_الملف: مؤشر[مصفوفة[مـحرف]]): ثـنائي؛
func exists (filename: ptr[array[Char]]): Bool;تفحص وجود ملف أو مجلد معين.
@تصدير[rename] دالة أعد_التسمية ( الاسم_القديم: مؤشر[مصفوفة[مـحرف]]، الاسم_الجديد: مؤشر[مصفوفة[مـحرف]] ): صـحيح؛
@expname[rename] func rename (oldName: ptr[array[Char]], newName: ptr[array[Char]]): Int;تعيد تسمية ملف أو مجلد.
@تصدير[remove] دالة امح (اسم_الملف: مؤشر[مصفوفة[مـحرف]]): ثـنائي؛
@expname[remove] func remove (filename: ptr[array[Char]]): Bool;تزيل ملفًا أو مجلدًا.
@تصدير[fopen] دالة افتح_ملف ( اسم_الملف: مؤشر[مصفوفة[مـحرف]]، الوضع: مؤشر[مصفوفة[مـحرف]] ): مؤشر[مـلف]؛
@expname[fopen] func openFile (filename: ptr[array[Char]], mode: ptr[array[Char]]): ptr[File];مطابقة لدالة fopen من POSIX.
@تصدير[fclose] دالة اغلق_ملف (ملف: مؤشر[مـلف]): صـحيح؛
@expname[fclose] func closeFile(f: ptr[File]): Int;مطابقة لدالة fclose من POSIX.
@تصدير[frpintf] دالة اطبع (ملف: مؤشر[مـلف]، نسق: مؤشر[مصفوفة[مـحرف]]، ...أيما): صـحيح؛
@expname[fprintf] func print (f: ptr[File], fmt: ptr[array[Char]], ...any): Int;مطابقة لدالة fprintf من POSIX.
@تصدير[fscanf] دالة امسح (ملف: مؤشر[مـلف]، نسق: مؤشر[مصفوفة[مـحرف]]، ...أيما): صـحيح؛
@expname[scanf] func scan (f: ptr[File], fmt: ptr[array[Char]], ...any): Int;مطابقة لدالة fscanf من POSIX.
@تصدير[fwrite] دالة اكتب ( محتوى: مؤشر، حجم: صـحيح_متكيف، عدد: صـحيح_متكيف، ملف: مؤشر[مـلف] ): صـحيح_متكيف؛
@expname[fwrite] func write ( content: ptr, size: ArchInt, count: ArchInt, f: ptr[File] ): ArchInt;مطابقة لدالة fwrite من POSIX.
@تصدير[fread] دالة اقرأ ( محتوى: مؤشر، حجم: صـحيح_متكيف، عدد: صـحيح_متكيف، ملف: مؤشر[مـلف] ): صـحيح_متكيف؛
@expname[fread] func read ( content: ptr, size: ArchInt, count: ArchInt, f: ptr[File] ): ArchInt;مطابقة لدالة fread من POSIX.
@تصدير[fflush] دالة اطلق (ملف: مؤشر[مـلف]): صـحيح؛
@expname[fflush] func flush (f: ptr[File]): Int;مطابقة لدالة fflush من POSIX.
@تصدير[ftell] دالة هات_الموقع (ملف: مؤشر[مـلف]): صـحيح_متكيف؛
@expname[ftell] func tell (f: ptr[File]): ArchInt;مطابقة لدالة tell من POSIX.
@تصدير[fseek] دالة انتقل (ملف: مؤشر[مـلف]، إزاحة: صـحيح_متكيف، انتقال: صـحيح): صـحيح؛
@expname[fseek] func seek (f: ptr[File], offset: ArchInt, seek: Int): Int;مطابقة لدالة tell من POSIX.
دالة أنشئ_ملف ( اسم_الملف: مؤشر[مصفوفة[مـحرف]]، محتوى: مؤشر، حجم_المحتوى: صـحيح_متكيف ): ثـنائي؛
func createFile ( filename: ptr[array[Char]], content: ptr, contentSize: ArchInt ): Bool;تنشئ ملفًا وتخزن فيه المحتوى المعطى.
دالة اقرأ_ملف ( اسم_الملف: مؤشر[مصفوفة[مـحرف]]، ناتج: مؤشر[مؤشر]، حجم: مؤشر[صـحيح_متكيف] ): ثـنائي؛
func readFile ( filename: ptr[array[Char]], result: ptr[ptr], size: ptr[ArchInt] ): Bool;تقرأ المحتوى الكامل لملف وترجعه.
دالة أنشئ_مجلد (اسم_المجلد: مؤشر[مصفوفة[مـحرف]]، الوضع: صـحيح): ثـنائي؛
func makeDir (folderName: ptr[array[Char]], mode: Int): Bool;تنشئ مجلدًا جديدًا.
@تصدير[opendir] دالة (اسم_المجلد: مؤشر[مصفوفة[مـحرف]]): مؤشر[مـجلد]؛
@expname[opendir] func (folderName: ptr[array[Char]]): ptr[Dir];مطابقة لدالة opendir من POSIX.
@تصدير[closedir] دالة (مجلد: مؤشر[مـجلد]): صـحيح؛
@expname[closedir] func (folder: ptr[Dir]): Int;طابقة لدالة closedir من POSIX.
@تصدير[rewindDir] دالة صفر_مؤشر_مجلد (مجلد: مؤشر[مـجلد])؛
@expname[rewindDir] func rewindDir (dir: ptr[Dir]);مطابقة لدالة rewinddir من POSIX.
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.
دالة طابق ( نمط: مؤشر[مصفوفة[مـحرف]]، محارف: مؤشر[مصفوفة[مـحرف]]، خيارات: صـحيح ): مـصفوفة[نـص]؛
func match ( pattern: ptr[array[Char]], str: ptr[array[Char]], flags: Int ): Array[String];تطبق النمط المعطى على سلسلة المحارف المعطاة وترجع مصفوفة من النصوص. في حالة وجود تطابق تحمل المصفوفة التطابق الكامل للنمط في أول عنصر من المصفوفة بينما تحمل العناصر التالية التطابقات الجزئية المحددة ضمن النمط بالأقواس. في حالة عدم وجود تطابق تكون النتيجة مصفوفة فارغة.
صـنف مـطابق ( عملية هذا~هيئ(نمط: مؤشر[مصفوفة[مـحرف]])؛ عملية هذا~هيئ(نمط: مؤشر[مصفوفة[مـحرف]]، خيارات: صـحيح)؛ عملية هذا.هيئ(نمط: مؤشر[مصفوفة[مـحرف]])؛ عملية هذا.هيئ(نمط: مؤشر[مصفوفة[مـحرف]]، خيارات: صـحيح)؛ عملية هذا.حرر()؛ عملية هذا.طابق(محارف: مؤشر[مصفوفة[مـحرف]]): مـصفوفة[نـص]؛ }
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) تطبق التعبير النمطي على سلسلة المحارف المعطاة وترجع مصفوفة من النصوص. في حالة وجود تطابق تحمل المصفوفة التطابق الكامل للنمط في أول عنصر من المصفوفة بينما تحمل العناصر التالية التطابقات الجزئية المحددة ضمن النمط بالأقواس. في حالة عدم وجود تطابق تكون النتيجة مصفوفة فارغة.
صنف وقـت_مفصل { عرف ثانية: صـحيح؛ عرف دقيقة: صـحيح؛ عرف ساعة: صـحيح؛ عرف يوم: صـحيح؛ عرف شهر: صـحيح؛ عرف سنة: صـحيح؛ عرف يوم_اسبوعي: صـحيح؛ عرف يوم_سنوي: صـحيح؛ عرف إزاحة_زمنية: صـحيح؛ عرف منطقة_زمنية: صـحيح؛ }؛
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]]; };سجل لحمل معلومات الوقت والتاريخ.
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.
@تصدير[time] دالة هات_الختم_الزمني (نتيجة: مؤشر[طـبيعي[64]]): مؤشر[طـبيعي[64]]؛
@expname[time] func getTimestamp (result: ptr[Word[64]]): ptr[Word[64]];مطابقة لدالة time من POSIX.
@تصدير[clock] دالة هات_الساعة (): صـحيح[64]؛
@expname[clock] func getClock (): Int[64];مطابقة لدالة clock من POSIX.
@تصدير[clock] دالة إلى_نص (خز: مؤشر[طـبيعي[64]]): مؤشر[مصفوفة[مـحرف]]؛
@expname[clock] func toString (ts: ptr[Word[64]]): ptr[array[Char]];مطابقة لدالة ctime من POSIX.
مكتبة `مغلفة` توفر الدعم للدالات المُغلَّفة، وهي الدالات التي تُرفق بنسخة من البيئة التي تُغلفها، أي بنسخة من المتغيرات الخارجية التي تستخدمها الدالة.
يمكن للدالات الضمنية الولوج إلى المتغيرات العمومية خارجها، لكن لا يمكنها الولوج إلى المتغيرات المحلية ضمن دالة خارجية تحوي الدالة الضمنية، وذلك لأن الدالة الخارجية قد ينتهي تنفيذها وتُزال متغيراتها من الذاكرة قبل استدعاء الدالة الضمنية. على سبيل المثال:عرف مد: مؤشر[دالة]؛ دالة جهز_دالة { عرف ع: صحيح = 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.
تتوفر الأنماط التالية لالتقاط البيانات:عرف م: مغلفة (ع: صحيح): صحيح؛ م.أهو_عدم() // يرجع 1 م = مغلفة (ع: صحيح): صحيح { أرجع 0؛ }؛ م.أهو_عدم() // يرجع 0
def c: closure (i: Int): Int; c.isNull() // returns true c = closure (i: Int): Int { return 0 }; c.isNull() // returns false
عرف مـكوني: { عملية هذا.اطبع() { طـرفية.اطبع(هذا.إلى_نص())؛ } } صنف صـنفي { نـبم.مدير_شبم.احشر_مكون[مـكوني]؛ // الآن هذا الصنف يحتوي على الوظيفة `اطبع`. ... }
def MyMixin: { handler this.print() { Console.print(this.toString()); } } class MyType { Spp.astMgr.insertMixin[MyMixin]; // Now the class has the `print` method. ... }يمكن أيضًا إنشاء مكون من دمج مكونات عدة باستخدام المؤثر &، كما في المثال التالي:
عرف مـكون1: { عملية هذا.اطبع() { طـرفية.اطبع(هذا.إلى_نص())؛ } } عرف مـكون2: { عملية هذا.احفظ(اسم_الملف: نـص) { عرف المحتوى: نـص = هذا.إلى_نص()؛ نـم.أنشئ_ملف(اسم_الملف، المحتوى.صوان، المحتوى.هات_الطول)؛ } } عرف مـكونات: مـكون1 & مـكون2؛ صنف صـنفي { نـبم.مدير_شبم.احشر_مكون[مـكونات]؛ // الآن هذا الصنف يحتوي على الوظيفتين `اطبع` و `احفظ`. ... }
def Mixin1: { handler this.print() { Console.print(this.toString()); } } def Mixin2: { handler this.save(filename: String) { def content: String = this.toString(); Fs.createFile(filename, content.buf, content.getLength()); } } def Mixins: Mixin1 & Mixin2; class MyType { Spp.astMgr.insertMixin[Mixins]; // Now the class has the `print` and the `save` methods. ... }
عرف تنفيذي: بـناء.تـنفيذي(الـبسملة.ابدأ~شبم، "البسملة")؛ تنفيذي.أضف_اعتمادية(جـتك~شبم)؛ // أو: تنفيذي.أضف_اعتمادية(نـص("libgtk..."))؛ تنفيذي.أضف_اعتماديات(مـصفوفة[نـص]({ نـص("libcurl.so")، ... }))؛ تنفيذي.أضف_خيار("-Wl,-rpath,@executable_path")؛ إذا تنفيذي.أنتج() { مـتم.طـرفية.اطبع("اكتمل البناء.\ج")؛ } وإلا { مـتم.طـرفية.اطبع("فشل البناء.\ج")؛ }؛
def exe: 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 { ... };بدون إضافة المبدل `@اعتماديات` فإن الدالة `أضف_اعتمادية` لا تفعل شيئا.
يمكن التحكم بنتيجة البناء عبر تغيير قيمة المتغير `معرف_النتيجة` (`targetTriple`) العضو في الصنف `تـنفيذي` (`Exe`) مما يسمح للمستخدم باستهداف نظام تشغيل مختلف عن النظام الحالي. ويمكن تحديد برنامج التجميع (linker) مختلف عن البرنامج المستخدم مبدئيا عبر تحديد اسمه في المتغير `اسم_المجمع` (`linkerFilename`) التابع للصنف `تـنفيذي` (`Exe`). عبر التحكم بهذين المتغيرين يمكن إنتاج شفرة تنفيذية لنظام غير النظام الحالي. على سبيل المثال، لإنشاء شفرة تنفيذية لنظام ويندوز من نظام لينكس يمكن فعل التالي:
عرف تنفيذي: بـناء.تـنفيذي(الـبسملة.ابدأ~شبم، "البسملة")؛ تنفيذي.معرف_النتيجة = "x86_64-pc-win32"؛ تنفيذي.اسم_المجمع = "x86_64-w64-mingw32-g++"؛ تنفيذي.أنتج()؛
def exe: Build.Exe(WidgetGuide.start~ast, "hello_world"); exe.targetTriple = "x86_64-pc-win32"; exe.linkerFilename = "x86_64-w64-mingw32-g++"; exe.generate();
عرف ويب_أسمبلي: بـناء.ويـب_أسمبلي(الـبسملة.ابدأ~شبم، "البسملة")؛ ويب_أسمبلي.أضف_اعتمادية(نـص("stdlib.wasm"))؛ ويب_أسمبلي.أضف_خيارات({ نـص("--export=malloc"), نـص("--export=realloc") }); إذا ويب_أسمبلي.أنتج() { مـتم.طـرفية.اطبع("اكتمل البناء.\ج")؛ } وإلا { مـتم.طـرفية.اطبع("فشل البناء.\ج")؛ }؛
def wasm: 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"); };
بـناء.أنشئ_تنفيذي(ابدأ~شبم، "بسملة")؛
Build.genExecutable(start~ast, "hello_world");
بـناء.أنشئ_ويب_أسمبلي(ابدأ~شبم، "بسملة")؛
Build.genWasm(start~ast, "hello_world");
دالة استخرج_من_ملف ( اسم_الملف: مؤشر[مصفوفة[مـحرف]]، اسم_المجلد: مؤشر[مصفوفة[مـحرف]]، مستلم_الاشعارات: مؤشر[دالة (مؤشر[مصفوفة[مـحرف]]، مؤشر) => صـحيح]، معطيات: مؤشر ) => صـحيح؛
func extractFromFile ( filename: ptr[array[Char]], folderName: ptr[array[Char]], callback: ptr[func (ptr[array[Char]], ptr): Int], arguments: ptr ): Int;تستخرج ملفًا مضغوطا إلى المجلد المحدد.
دالة اضغط_إلى_ملف ( اسم_المف: مؤشر[مصفوفة[مـحرف]]، ملفات: مؤشر[مصفوفة[مؤشر[مصفوفة[مـحرف]]]]، عدد_الملفات: صـحيح، نوع_الاستخراج: مؤشر[مصفوفة[مـحرف]] ) => صـحيح؛
func compressToFile ( filename: ptr[array[Char]], files: ptr[array[ptr[array[Char]]]], fileCount: Int, extractType: ptr[array[Char]] ): Int;تنشئ ملفًا مضغوطا يحتوي على الملفات المعطاة.
$ محا مساعدة
$ 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>
دالة اشمل_ملف (اسم_الملف: مؤشر[مصفوفة[مـحرف]])؛
func importFile (filename: ptr[array[Char]]);تشمل الملف المعطى اسمه. هذه الدالة تعمل عمل الإيعاز `اشمل` (import) ولا تختلف عن ذلك الإيعاز سوى بقدرتها على شمول الملفات بشكل ديناميكي، أي باستخدام اسم ملف مولّد ديناميكيًا أثناء التنفيذ.
دالة أضف_ترجمة ( رمز_اللغة: مؤشر[مصفوفة[مـحرف]]، المفتاح: مؤشر[مصفوفة[مـحرف]]، القيمة: مؤشر[مصفوفة[مـحرف]] )؛
func addLocalization ( locale: ptr[array[Char]], key: ptr[array[Char]], value: ptr[array[Char]] );تضيف ترجمة إلى قائمة الترجمات للغة معينة. إن لم توجد مدخلة مسبقًا للمفتاح المطلوب فإن الترجمة ستضاف حتى لو كانت اللغة الحالية مختلفة عن لغة الترجمة المقدمة والسبب في ذلك أن وجود النص بلغة مغايرة خير من عدم وجود نص على الإطلاق. أما إن وجدت مدخلة بهذا المفتاح فإن الترجمة ستُضاف فقط إذا طابقت لغة الترجمة لغة النظام الحالية.
عرف أنشئ_محتكر: مؤشر[@مشترك @دون_ربط دالة (): سند[كـائن_بهوية]]؛
def createPlain: ptr[@shared @no_bind function ():ref[TiObject]];تنشئ كائنًا وترجع سندا اعتياديًا له بعد تهيئته.
عرف أنشئ_مشترك: مؤشر[@مشترك @دون_ربط دالة (): سـندنا[كـائن_بهوية]]؛
def createShared؛: ptr[@shared @no_bind function ():SrdRef[TiObject]];تنشئ كائنًا وترجع سندا مشتركًا له بعد تهيئته.
عرف هيئ: مؤشر[@مشترك @دون_ربط دالة (سند[كـائن_بهوية])]؛
def initialize: ptr[@shared @no_bind function (ref[TiObject])];تهيئ كائنًا محجوز في الذاكرة مسبقًا.
عرف أتلف: مؤشر[@مشترك @دون_ربط دالة (سند[كـائن_بهوية])]؛
def terminate: ptr[@shared @no_bind function (ref[TiObject])];تتلف كائنًا دون تحرير ذاكرته.
عملية هذا.هات_هويتي (): سند[هـوية_صنف]؛
handler this.getMyTypeInfo (): ref[TypeInfo];تعطيك سندًا لهوية هذا الكائن.
عملية هذا.أمشتق_من (سند[هـوية_صنف]): ثـنائي؛
handler this.isDerivedFrom (ref[TypeInfo]): Bool;تُعلمك إن كان الكائن من الصنف ذي الهوية المعطاة، أو من صنف مشتق من ذلك الصنف.
عملية هذا.هات_وسيط (سند[هـوية_صنف]): سند[وسـيط_بهوية]؛
handler this.getInterface (ref[TypeInfo]): ref[TiInterface];تستقبل سندًا لهوية وسيط وترجع سندًا لذلك الوسيط إن وجد، وإن لم يكن ذلك الوسيط مدعوما من هذا الكائن فترجع صفرًا.
عملية هذا.هات_هويتي (): سند[هـوية_صنف]؛
handler this.getMyInterfaceInfo (): ref[TypeInfo];تعطيك سندًا لهوية هذا الوسيط.
عملية هذا.هات_الكائن (): سند[كـائن_بهوية]؛
handler this.getTiObject (): ref[TiObject];تُرجع الكائن الذي يملك هذا الوسيط.
وسيط~عطل_التتبع = هات_الوسيط[كائن، صـنف_الوسيط]
interface~no_deref = getInterface[obj, InterfaceType];
إذا أمشتق_من[كائن، صـنف_الكائن] { ... }
if isDerivedFrom[obj, ObjType] { ... }
دالة اختبار (كائن_جذري: سند[صـنف_الجذر]) { عرف_سندا_بتمثيل_آمن[كائن_فرعي، كائن_جذري، صـنف_الفرع]؛ إذا كائن_فرعي~مؤشر != 0 كائن_فرعي.عملية(...)؛ }
func test (parentObj: ref[ParentType]) { defDynCastedRef[childObj, parentObj, ChildType]; if childObj~ptr != 0 childObj.someFunc(...); }
دالة أنشئ (ق: الـصنف_الأساسي): سـندنا[صـنف_المعلومة]
func create (v: BasicType): SrdRef[ObjType]تنشئ كائنًا من هذا الصنف بالقيمة المعطاة وترجع سندًا مشتركًا للكائن.
دالة هات_هوية_الصنف (): سند[هـوية_صنف]؛
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); }فيما يلي قائمة الأصناف الأساسية بهوية:
عملية هذا.حدد_عضوا (اسم_العضو: مؤشر[مصفوفة[مـحرف]]، قيمة: سند[كـائن_بهوية])؛ عملية هذا.حدد_عضوا (تسلسل_العضو: صـحيح، قيمة: سند[كـائن_بهوية])؛
handler this.setMember (memberName: ptr[array[Char]], value: ref[TiObject]); handler this.setMember (memberIndex: Int, value: ref[TiObject]);تحدد قيمة عضو من أعضاء الكائن. الصيغة الأولى لتحديد العضو اعتمادا على اسمه بينما الثانية تعتمد على تسلسل العضو بين أعضاء الكائن.
عملية هذا.هات_عدد_الأعضاء (): طـبيعي؛
handler this.getMemberCount(): Word;تستعلم عن عدد الأعضاء التي يمتلكها الكائن.
عملية هذا.هات_عضوا (اسم_ألعضو: مؤشر[مصفوفة[مـحرف]]): سند[كـائن_بهوية]؛ عملية هذا.هات_عضوا (تسلسل_العضو: صـحيح): سند[كـائن_بهوية]؛
handler this.getMember (memberName: ptr[array[Char]]): ref[TiObject]; handler this.getMember (memberIndex: Int): ref[TiObject];تجلب قيمة العضو ذي الإسم المعطى في الصيغة الأولى، أو التسلسل المعطى في الصيغة الثانية.
عملية هذا.هات_الصنف_المطلوب_للعضو (اسم_العضو: مؤشر[مصفوفة[مـحرف]]): سند[هـوية_صنف]؛ عملية هذا.هات_الصنف_المطلوب_للعضو (تسلسل_العضو: صـحيح): سند[هـوية_صنف]؛
handler this.getMemberNeededType (memberName: ptr[array[Char]]): ref[[TypeInfo]; handler this.getMemberNeededType (memberIndex: Int): ref[TypeInfo];تجلب هوية الصنف المطلوب للعنصر ذي الإسم المعطى في الصيغة الأولى، أو التسلسل المعطى في الصيغة الثانية.
عملية هذا.هات_اسم_العضو (تسلسل_العضو: صـحيح): نـص؛
handler this.getMemberKey (index: Int): String;تجلب اسم العضو ذي التسلسل المعطى.
عملية هذا.جد_تسلسل_العضو (اسم_العضو: مؤشر[مصفوفة[مـحرف]]): صـحيح؛
handler this.findMemberIndex (name: ptr[array[Char]]): Int;ترجع تسلسل العضو ذي الاسم المعطى، أو -1 إن لم يوجد عضو بهذا الاسم.
عملية هذا.حدد_عنصرا (تسلسل_العنصر: صـحيح، قيمة: سند[كـائن_بهوية])؛
handler this.setElement (index: Int, value: ref[TiObject]);تحديد كائن جديد للعنصر ذي التسلسل المعطى.
عملية هذا.هات_عدد_العناصر (): طـبيعي؛
handler this.getElementCount (): Word;تجلب عدد العناصر التي يحتويها الكائن.
عملية هذا.هات_عنصرا (تسلسل_ألعنصر: صـحيح): سند[كـائن_بهوية]؛
handler this.getElement (index: Int): ref[TiObject];تجلب العنصر الواقع عند التسلسل المعطى.
عملية هذا.هات_الصنف_المطلوب_للعنصر (تسلسل_العنصر: صـحيح): سند[هـوية_صنف]؛
handler this.getElementNeededType (index: Int): ref[TypeInfo];تجلب هوية الصنف المطلوب للعنصر ذي التسلسل المعطى.
عملية هذا.أضف_عنصرا (القيمة: سند[كـائن_بهوية]): صـحيح؛
handler this.addElement (value: ref[TiObject]): Int;تضيف عنصرا جديدا إلى نهاية الحاوية وترجع تسلسل العنصر الجديد.
عملية هذا.احشر_عنصرا (تسلسل: صـحيح، قيمة: سند[كـائن_بهوية])؛
handler this.insertElement (index: Int, value: ref[TiObject]);تضيف عنصرا جديدا إلى الحاوية عند التسلسل المعطى بعد تزحيف كل العناصر التي عند ذلك التسلسل.
عملية هذا.أزل_عنصرا (تسلسل_العنصر: صـحيح)؛
handler this.removeElement (index: Int);تزيل العنصر الذي عند التسلسل المعين ثم تزحف كل العناصر التي تلي ذلك التسلسل.
عملية هذا.هات_الصنف_المطلوب_للعناصر (): سند[هـوية_صنف]؛
handler this.getElementsNeededType (): ref[TypeInfo];تجلب هوية الصنف المطلوب لعناصر هذه الحاوية دون الحاجة لتحديد عنصر معين.
عملية هذا.حدد_عنصرا ( اسم_ألعنصر: مؤشر[مصفوفة[مـحرف]]، قيمة: سند[كـائن_بهوية] ): صـحيح؛
handler this.setElement ( elementName: ptr[array[Char]], value: ref[TiObject] ): Int;تحدد قيمة جديدة للعنصر ذي الاسم المعطى وترجع تسلسل هذا العنصر.
عملية هذا.هات_عنصرا (اسم_العنصر: مؤشر[مصفوفة[مـحرف]]): سند[كـائن_بهوية]؛
handler this.getElement (elementName: ptr[array[Char]]): ref[TiObject];تجلب قيمة العنصر ذي الاسم المعطى.
عملية هذا.هات_الصنف_المطلوب_للعنصر ( اسم_العنصر: مؤشر[مصفوفة[مـحرف]] ): سند[هـوية_صنف]؛
handler this.getElementNeededType ( elementName: ptr[array[Char]] ): ref[TypeInfo];تجلب هوية الصنف المطلوب للعنصر ذي الاسم المعطى.
عملية هذا.هات_اسم_العنصر (تسلسل_العنصر: صـحيح): نـص)
handler this.getElementKey (index: Int): String;تجلب اسم العنصر ذي التسلسل المعطى.
عملية هذا.جد_تسلسل_العنصر (اسم_العنصر: مؤشر[مصفوفة[مـحرف]]): صـحيح؛
handler this.findElementIndex (name: ptr[array[Char]]): Int;ترجع تسلسل العنصر ذي الاسم المعطى، أو -1 إن لم يوجد عنصر بهذا الاسم.
عملية هذا.أضف_عنصرا ( اسم_العنصر: مؤشر[مصفوفة[مـحرف]]، قيمة: سند[كـائن_بهوية] ): صـحيح؛
handler this.addElement ( name: ptr[array[Char]], value: ref[TiObject] ): Int;يضيف عنصرا جديدا باسم الجديد إلى الحاوية ويرجع تسلسل العنصر الجديد.
عملية هذا.احشر_عنصرا ( تسلسل: صـحيح، اسم: مؤشر[مصفوفة[مـحرف]]، قيمة: سند[كـائن_بهوية] )؛
handler this.insertElement ( index: Int, name: ptr[array[Char]], value: ref[TiObject] );يضيف عنصرا جديدا عند التسلسل المحدد بعد تزحيف العناصر التي عند ذلك التسلسل أو تليه.
عملية هذا.أزل_عنصرا (تسلسل_العنصر: صـحيح)؛ عملية هذا.أزل_عنصرا (اسم_ألعنصر: مؤشر[مصفوفة[مـحرف]])؛
handler this.removeElement (index: Int); handler this.removeElement (name: ptr[array[Char]]);تزيل العنصر ذي التسلسل المعطى في الصيغة الأولى أو الاسم المعطى في الصيغة الثانية.
عملية هذا.هات_الصنف_المطلوب_للعناصر (): سند[هـوية_صنف]؛
handler this.getElementsNeededType (): ref[TypeInfo];تجلب هوية الصنف المطلوب لعناصر هذه الحاوية دون الحاجة لتحديد عنصر معين.
دالة هات_هوية_الصنف (): سند[هـوية_صنف]؛
func getTypeInfo (): ref[TypeInfo];هذه الدالة تُرجع سندًا لهوية هذا الصنف، أي لهوية الكائنات المشتقة من هذا الصنف.
دالة هات_هوية_الصنف (): سند[هـوية_صنف]؛
func getTypeInfo (): ref[TypeInfo];هذه الدالة تُرجع سندًا لهوية هذا الصنف، أي لهوية الكائنات المشتقة من هذا الصنف.
دالة أنشئ (قيمة: مؤشر[مصفوفة[مـحرف]]): سـندنا[الـصنف]؛
func create (value: ptr[array[Char]]): SrdRef[TheType];تنشئ كائنًا من هذا الصنف بالقيمة المعطاة وترجع سندًا مشتركًا له.
الوحدة `نـبم` (نمط البرمجة المعياري) تحتوي على دالات للتعامل مباشرة مع مكتبة spp، وهي المكتبة المسؤولة عن دعم نمط البرمجة المعياري. عناصر هذه الوحدة تمكن المستخدم من التعامل مباشرة مع المترجم من خلال برنامجه.
عملية هذا.أدرج_تو_لعنصر (عنصر: سند[كـائن_بهوية])؛
handler this.dumpLlvmIrForElement (element: ref[TiObject]);دالة `أدرج_تو_لعنصر` تقوم بطبع الترميز الوسطي لعنصر معين من الشفرة المصدرية. الترميز الوسطي المطبوع هو ترميز LLVM IR. تستقبل الدالة معطى واحد وهو مؤشر على شبكة البنية المجردة لذلك العنصر (Abstract Syntax Tree). يمكنك الحصول على هذا المؤشر باستخدام الأمر `~شبم` كما في المثال التالي:
نـبم.مدير_البناء.أدرج_تو_لعنصر(دالتي~شبم)؛
Spp.buildMgr.dumpLlvmIrForElement(myFunc~ast);
عملية هذا.أنشء_ملفا_رقميا_لعنصر ( عنصر: سند[كـائن_بهوية]، اسم_الملف: مؤشر[مصفوفة[محرف]]، وصف_المعمارية: مؤشر[مصفوفة[محرف]] ): ثنائي
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 لمزيد من المعلومات حول هذه القيمة.
نـبم.مدير_البناء.أنشء_ملفا_رقميا_لعنصر(وحـدتي~شبم، "اسم_الملف_الناتج"، 0)؛
Spp.buildMgr.buildObjectFileForElement(MyModule~ast, "output_filename", 0);
دالة ارفع_إشعار_بناء ( رمز: مؤشر[مصفوفة[مـحرف]]، حدة: صـحيح، عنصر_شبم: سند[الـقلب.أسـاسيات.كـائن_بهوية] )؛
func raiseBuildNotice ( code: ptr[array[Char]], severity: Int, astNode: ref[TiObject] );تمكن هذه الدالة المبرمج من رفع إشعار بناء بشكل برمجي أثناء المعالجة التمهيدية. تأخذ هذه الدالة ثلاث معطيات:
عرف رمز_خطأ: "SPPH1006"؛ نـبم.مدير_البناء.ارفع_إشعار_بناء(رمز_خطأ، 1، عنصر_معطى_الدالة)؛ // السطر أعلاه سيظهر إشعار خطأ: اسم معطى الدالّة غير صالح.
def errorCode: "SPPH1006"; Spp.buildMgr.raiseBuildNotice(errorCode, 1, funcArgNode); // The above line will show an build error: Invalid function argument name.
عرف كـائن_بهوية: لقب الـقلب.أسـاسيات.كـائن_بهوية؛ عملية هذا.أضف_أمرا_مخصصا ( معرف: مؤشر[مصفوفة[مـحرف]]، شجرة_القاعدة: سند[كـائن_بهوية] معالج: مؤشر[دالة (سـندنا[كـائن_بهوية]): سـندنا[كـائن_بهوية]] )؛
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) يجب أن يظهر مرة واحدة تحديدًا.
عرف كـائن_بهوية: لقب الـقلب.أسـاسيات.كـائن_بهوية؛ عملية هذا.أضف_قاعدة_مخصصة ( معرف: مؤشر[مصفوفة[مـحرف]]، معرف_الأصل: مؤشر[مصفوفة[مـحرف]]، شجرة_القاعدة: سند[كـائن_بهوية] )؛
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> }; ... }شجرة القاعدة تحتوي مجموعة من المدخلات، كل مدخلة تتكون من المسار للقيمة المراد تعديلها ثم القيمة الجديدة. المسار يكون نسبة لجذر القاعدة.
Spp.grammarMgr.addCustomGrammar( "ClosureSigExp", "FuncSigExpression", ast { BitwiseExp.vars: { enable: 1 } } );
عملية هذا.جد_عناصر ( معيار_البحث: سند[الـقلب.أسـاسيات.كـائن_بهوية]، موقع_البحث: سند[الـقلب.أسـاسيات.كـائن_بهوية]، خيارات: طـبيعي ): مـصفوفة[سند[الـقلب.أسـاسيات.كـائن_بهوية]]؛ عملية هذا.جد_عناصر ( معيار_البحث: سند[الـقلب.أسـاسيات.كـائن_بهوية]، موقع_البحث: سند[الـقلب.أسـاسيات.كـائن_بهوية]، خيارات: طـبيعي، معرف_مبدل: مـؤشر_محارف، ترجمات_معرفات: سند[تـطبيق[نـص، نـص]] ): مـصفوفة[سند[الـقلب.أسـاسيات.كـائن_بهوية]]؛
handler this.findElements ( comparison: ref[Core.Basic.TiObject], target: ref[Core.Basic.TiObject], flags: Word ): Array[ref[Core.Basic.TiObject]]; handler this.findElements( comparison: ref[TiObject], target: ref[TiObject], flags: Word, modifierKwd: CharsPtr, kwdTranslations: ref[Map[String, String]] ): Array[ref[TiObject]];تبحث ضمن الشفرة المصدرية عن عناصر تطابق معيار البحث المعطى. المعطيان الأول والثاني سندان على شجرتي بنية مجردة، الأولى لتركيب يمثل معيار البحث بينما الثانية هي الشجرة التي سيتم البحث فيها.
العناصر = نـبم.مدير_شبم.جد_عناصر( شبم { نوع_العنصر == "دالة" }، صـنفي~شبم، نـبم.خـيارات_الساعي._تخطى_المالكين_ | نـبم.خـيارات_الساعي._تخطى_الاستخدامات_ | نـبم.خـيارات_الساعي._تخطى_الأبناء_ )؛
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
عملية هذا.هات_اسم_تعريف ( عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية] ): نـص؛
handler this.getDefinitionName ( element: ref[Core.Basic.TiObject] ): String;ترجع اسم العنصر المعطى، أي اسم التعريف الذي يملك هذا العنصر.
عملية هذا.هات_المبدلات ( عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية] ): سند[الـقلب.أسـاسيات.احـتواء]؛
handler this.getModifiers ( element: ref[Core.Basic.TiObject] ): ref[Core.Basic.Containing];تجلب قائمة المبدلات المطبقة على العنصر المُعطى.
عملية هذا.جد_مبدلا ( مبدلات: سند[الـقلب.أسـاسيات.احـتواء]، كلمة_مفتاحية: مؤشر[مصفوفة[مـحرف]] ): سند[الـقلب.أسـاسيات.كـائن_بهوية]
handler this.findModifier( modifiers: ref[Core.Basic.Containing], kwd: ptr[array[Char]] ): ref[Core.Basic.TiObject];إيجاد مبدل ضمن قائمة مبدلات. يتم البحث باستخدام الكلمة المفتاحية للمبدل. مثلا، للبحث عن مبدل `@تصدير[...]` نحتاج لتمرير الكلمة المفتاحية `تصدير`.
عملية هذا.جد_مبدلا_لعنصر ( عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]، كلمة_مفتاحية: مؤشر[مصفوفة[مـحرف]] ): سند[الـقلب.أسـاسيات.كـائن_بهوية] عملية هذا.جد_مبدلا_لعنصر ( عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]، كلمة_مفتاحية: مؤشر[مصفوفة[مـحرف]]، ترجمات_الكلمة_المفتاحية: سند[تـطبيق[نـص، نـص]] ): سند[الـقلب.أسـاسيات.كـائن_بهوية]
handler this.findModifierForElement( element: ref[Core.Basic.TiObject], kwd: ptr[array[Char]] ): ref[Core.Basic.TiObject]; handler this.findModifierForElement( element: ref[Core.Basic.TiObject], kwd: ptr[array[Char]], kwdTranslations: ref[Map[String, String]] ): ref[Core.Basic.TiObject];إيجاد المبدل بالكلمة المعيارية المعطاة على العنصر المعطى. النسخة الثانية من هذه الدالة تستلم أيضًا قائمة ترجمات لاستخدامها أثناء البحث عبر ترجمة كل كلمة قبل مطابقتها مع الكلمة المطلوبة.
عملية هذا.هات_كلمة_المبدل_المفتاحية ( مبدل: سند[الـقلب.أسـاسيات.كـائن_بهوية] ): نـص
handler this.getModifierKeyword( modifier: ref[Core.Basic.TiObject] ): Srl.String;تُرجع الكلمة المفتاحية للمبدل المعطى.
عملية هذا.هات_معطيات_مبدل ( مبدل: سند[الـقلب.أسـاسيات.كـائن_بهوية]، الناتج: سند[مـصفوفة[سند[الـقلب.أسـاسيات.كـائن_بهوية]]] ): ثـنائي
handler this.getModifierParams( modifier: ref[Core.Basic.TiObject], result: ref[Array[ref[Core.Basic.TiObject]]] ) => Bool;تُرجع قائمة بكل المعطيات الممررة للمبدل. تُرجع الدالة قيمة ثنائية تكون 1 عند نجاح العملية و0 عند فشلها.
عملية هذا.هات_المعطيات_النصية_لمبدل ( مبدل: سند[الـقلب.أسـاسيات.كـائن_بهوية]، الناتج: سند[مـصفوفة[نـص]] ): ثـنائي
handler this.getModifierStringParams( modifier: ref[Core.Basic.TiObject], result: ref[Array[String]] ) => Bool;تُرجع قائمة بكل المعطيات النصية الممررة للمبدل. مثلاً لو كان عندنا مبدل `@اعتماديات["مكتبة1"، "مكتبة2"]` واستخدمنا هذه الدالة فإننا سنحصل منها على مصفوفة من عنصرين، الأول قيمته "مكتبة1" والثاني "مكتبة2". تُرجع الدالة قيمة ثنائية تكون 1 عند نجاح العملية و0 عند فشلها.
عملية هذا.هات_متغيرات_صنف (عنصر: سند[كـائن_بهوية]): مـصفوفة[سند[كـائن_بهوية]]؛ عملية هذا.هات_متغيرات_صنف ( عنصر: سند[كـائن_بهوية]، كلمة_مفتاحية: مؤشر[مصفوفة[مـحرف]]، ترجمات_الكلمة_المفتاحية: سند[تـطبيق[نـص، نـص]] ): مـصفوفة[سند[كـائن_بهوية]]؛
handler this.getClassVars (parent: ref[TiObject]): Array[ref[TiObject]]; handler this.getClassVars ( parent: ref[TiObject], kwd: ptr[array[Char]], kwdTranslations: ref[Map[String, String]] ): Array[ref[TiObject]];تجلب قائمة المتغيرات التابعة لصنف محدد. النسخة الثانية من هذه الدالة تحضر المتغيرات التي تحمل المبدل المحدد فقط.
عملية هذا.هات_أسماء_متغيرات_صنف (عنصر: سند[كـائن_بهوية]): مـصفوفة[نـص]؛ عملية هذا.هات_أسماء_متغيرات_صنف ( عنصر: سند[كـائن_بهوية]، كلمة_مفتاحية: مؤشر[مصفوفة[مـحرف]]، ترجمات_الكلمة_المفتاحية: سند[تـطبيق[نـص، نـص]] ): مـصفوفة[نـص]؛
handler this.getClassVarNames (parent: ref[TiObject]): Array[String]; handler this.getClassVarNames ( parent: ref[TiObject], kwd: ptr[array[Char]], kwdTranslations: ref[Map[String, String]] ): Array[String];تجلب قائمة أسماء المتغيرات التابعة لصنف محدد. النسخة الثانية من هذه الدالة تحضر أسماء المتغيرات التي تحمل المبدل المحدد فقط.
عملية هذا.هات_دالات_صنف (عنصر: سند[كـائن_بهوية]): مـصفوفة[سند[كـائن_بهوية]]؛ عملية هذا.هات_دالات_صنف ( عنصر: سند[كـائن_بهوية]، كلمة_مفتاحية: مؤشر[مصفوفة[مـحرف]]، ترجمات_الكلمة_المفتاحية: سند[تـطبيق[نـص، نـص]] ): مـصفوفة[سند[كـائن_بهوية]]؛
handler this.getClassFuncs (parent: ref[TiObject]): Array[ref[TiObject]]; handler this.getClassFuncs ( parent: ref[TiObject], kwd: ptr[array[Char]], kwdTranslations: ref[Map[String, String]] ): Array[ref[TiObject]];تجلب قائمة الدالات التابعة لصنف محدد. النسخة الثانية من هذه الدالة تحضر الدالات التي تحمل المبدل المحدد فقط.
عملية هذا.هات_أسماء_دالات_صنف (عنصر: سند[كـائن_بهوية]): مـصفوفة[نـص]؛ عملية هذا.هات_أسماء_دالات_صنف ( عنصر: سند[كـائن_بهوية]، كلمة_مفتاحية: مؤشر[مصفوفة[مـحرف]]، ترجمات_الكلمة_المفتاحية: سند[تـطبيق[نـص، نـص]] ): مـصفوفة[نـص]؛
handler this.getClassFuncNames (parent: ref[TiObject]): Array[String]; handler this.getClassFuncNames ( parent: ref[TiObject], kwd: ptr[array[Char]], kwdTranslations: ref[Map[String, String]] ): Array[String];تجلب قائمة أسماء الدالات التابعة لصنف محدد. النسخة الثانية من هذه الدالة تحضر أسماء الدالات التي تحمل المبدل المحدد فقط.
عملية هذا.هات_أصناف_معطيات_دالة (عنصر: سند[كـائن_بهوية]): سند[كـائن_بهوية]؛
handler this.getFuncArgTypes (element: ref[TiObject]): ref[TiObject]تجلب قائمة تعريفات المعطيات للدالة المعطاة.
عملية هذا.هات_صنف_معطى_دالة (عنصر: سند[كـائن_بهوية]، تسلسل: صـحيح): سند[كـائن_بهوية]؛
handler this.getFuncArgType (element: ref[TiObject], index: Int): ref[TiObject]تجلب تعريف معطى الدالة المعطاة ذي التسلسل المحدد.
عملية هذا.هات_المسار_الكامل_لشفرة_عنصر ( عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية] ): نـص
handler this.getSourceFullPathForElement( element: ref[Core.Basic.TiObject] ) => String;ترجع اسم الملف الكامل مع المسار لملف الشفرة المصدرية الذي يحتوي العنصر المعطى.
عملية هذا.هات_مجلد_شفرة_عنصر ( عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية] ): نـص
handler this.getSourceDirectoryForElement( element: ref[Core.Basic.TiObject] ) => String;ترجع المسار الكامل للمجلد الذي يحتوي ملف الشفرة المصدرية الذي يحتوي العنصر المعطى.
عملية هذا.احشر_شبم ( عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]، استعاضات: سند[تـطبيق[نـص، سند[الـقلب.أسـاسيات.كـائن_بهوية]]] ): ثـنائي عملية هذا.احشر_شبم ( عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]، استعاضات: سند[تـطبيق[نـص، سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]]] ): ثـنائي
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، ع < 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) ); }
عملية هذا.أنشئ_شبم ( عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]، استعاضات: سند[تـطبيق[نـص، سند[الـقلب.أسـاسيات.كـائن_بهوية]]]، النتيجة: سند[سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]] ): ثـنائي عملية هذا.أنشئ_شبم ( عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]، استعاضات: سند[تـطبيق[نـص، سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]]]، النتيجة: سند[سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]] ): ثـنائي عملية هذا.أنشئ_شبم ( عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]، استعاضات: سند[تـطبيق[نـص، سند[الـقلب.أسـاسيات.كـائن_بهوية]]] ): سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]؛
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) ); }
عملية هذا.احشر_عمليات_النسخ (عنصر: سند[كـائن_بهوية])؛ @عضو ماكرو احشر_عمليات_النسخ [هذا]؛
handler this.insertCopyHandlers(obj: ref[TiObject]); @member macro insertCopyHandlers [this];تحشر عمليتي النسخ (`عملية هذا=سند[هذا_الصنف]`) والتهيئة الناسخة (`عملية~هيئ(سند[هذا_الصنف])`) ضمن الصنف الحالي وتتولى عملية نسخ كل المتغيرات العضو لهذا الصنف. يجب استخدام هذا الماكرو ضمن متن صنف لتوليد العمليتين لذلك الصنف.
عملية هذا.احشر_مكون (عنصر: سند[كـائن_بهوية])؛ @عضو ماكرو احشر_مكون [هذا، مستهدف]؛
handler this.insertMixin(obj: ref[TiObject]); @member macro insertMixin [this, target];تحشر المكون (mixin) المُشار إليه إلى كائن. الدالة تحشر المكون في الموضع الحالي، لذا يجب استخدامها ضمن عملية `تمهيد` (`preprocess`). الماكرو مجرد مساعد لتسهيل استخدام الدالة وكل ما يقوم به هو استدعاء الدالة ضمن عملية تمهيد مع إعطائها مؤشر ش.ب.م للعنصر المعطى. راجع خاصية الخلط (mixins) لمزيد من المعلومات.
عملية هذا.هات_مالك_عبارة_التمهيد_الحالية (): سند[الـقلب.أسـاسيات.كـائن_بهوية]
handler this.getCurrentPreprocessOwner(): ref[Core.Basic.TiObject];ترجع هذه الدالة سندًا لعنصر شبم الذي يملك عبارة التمهيد قيد التنفيذ.
عملية هذا.هات_محشر_عبارة_التمهيد_الحالية (): صـحيح
handler this.getCurrentPreprocessInsertionPosition(): Int;ترجع هذه الدالة التسلسل (ضمن مالك عبارة التمهيد الحالية) الذي ستُحشر عنده عناصر شبم عند استدعاء دالة `احشر_شبم`.
عملية هذا.هات_نطاق_المتغير ( عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية] ): صـحيح
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. }
عملية هذا.تتبع_الصنف (عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]): سند[نـبم.شـبم.صـنف]
handler this.traceType(element: ref[Core.Basic.TiObject]) => ref[Spp.Ast.Type];تتبع هذه الدالة الصنف المشار إليه بعنصر ش.ب.م المعطى وترجع ذلك الصنف.
عملية هذا.طابق_طبعة_قالب ( القالب: سند[نـبم.شـبم.قـالب]، مدخل_القالب: سند[الـقلب.أسـاسيات.كـائن_بهوية]، الناتج: سند[سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]] ) => ثـنائي؛
handler this.matchTemplateInstance( template: ref[Spp.Ast.Template], templateInput: ref[Core.Basic.TiObject], result: ref[SrdRef[Core.Basic.TiObject]] ) => Bool;ترجع طبعة القالب التي تطابق المدخل المعطى وإن لم توجد فتنشئها وترجعها.
عملية هذا.أهو_قابل_للتمثيل ( الصنف_الأصلي: سند[الـقلب.أسـاسيات.كـائن_بهوية]، الصنف_المطلوب: سند[الـقلب.أسـاسيات.كـائن_بهوية]، تمثيل_تلقائي: ثـنائي ) => ثـنائي؛
handler this.isCastableTo( srcTypeRef: ref[Core.Basic.TiObject], targetTypeRef: ref[Core.Basic.TiObject], implicit: Bool ) => Bool;تستبين إمكانية الصنف المعطى (الأصلي) تمثيل الصنف المطلوب. معطيات الأصناف يمكن أن تكون الأصناف نفسها أو معرفات تشير إليها (اسم الصنف في الشفرة المصدرية). المعطى الثالث يحدد ما إن كان المطلوب استبيانه تمثيلا تلقائيا (implicit) أم لا (explicit).
عملية هذا.استنبط_صنف_الناتج ( عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]، ناتج: سند[سند[الـقلب.أسـاسيات.كـائن_بهوية]]، الناتج_قيمة: سند[ثـنائي] ): سند[ثـنائي]
handler this.computeResultType( element: ref[Core.Basic.TiObject], result: ref[ref[Core.Basic.TiObject]], resultIsValue: ref[Bool] ) => Bool;تستنبط هذه الدالة الناتج من التركيب المعطى وترجعه. الناتج قد يكون صنفًا وقد يكون أي تعريف آخر مثل وحدة أو صنف. المعطى الأخير يخبرك إن كان الناتج قيمة (مثلاً متغير من الصنف المعطى) أم الصنف نفسه (أي يخبرك فيما لو كان التركيب معرفا لصنف أم معرفًا لمتغير من ذلك الصنف).
عملية هذا.كرر_شبم ( عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية] ): مـتم.سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]؛ عملية هذا.كرر_شبم ( عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية]، عنصر_موقع_الشفرة_المصدرية: سند[الـقلب.أسـاسيات.كـائن_بهوية] ): مـتم.سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]؛
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];تنسخ هذه الدالة شجرة الكائنات المعطاة. النسخة الثانية من هذه الدالة تتيح لك إضافة موقع في الشفرة المصدرية إلى مكدس مواقع الشفرة المصدرية المرتبطة بالشجرة المولدة. المعطى الثاني في النسخة الثانية ليس موقع الشفرة المصدرية المراد إضافته إلى المكدس وإنما عنصر ش.ب.م المراد أخذ الموقع منه.
عملية هذا.أدرج_بيانات (عنصر: سند[الـقلب.أسـاسيات.كـائن_بهوية])؛
handler this.dumpData(obj: ref[Core.Basic.TiObject]);تطبع شجرة البيانات المعطاة في الطرفية بصيغة نصية.
عملية هذا.هات_صنف_السند_ل ( صنف_شبم: سند[الـقلب.أسـاسيات.كـائن_بهوية] ): سند[نـبم.شـبم.صـنف_سند]؛
handler this.getReferenceTypeFor( astType: ref[Core.Basic.TiObject] ): ref[Spp.Ast.ReferenceType];ترجع صنف السند للصنف المعطى.
عملية هذا.حاول_جلب_صنف_المحتوى_العميق ( صنف_شبم: سند[نـبم.شـبم.صـنف] ): سند[نـبم.شـبم.صـنف]؛
handler this.tryGetDeepReferenceContentType( astType: ref[Spp.Ast.Type] ): ref[Spp.Ast.Type];ترجع صنف المحتوى للصنف المعطى. إن كان الصنف المعطى سندا فإن الدالة ترجع المحتوى الذي يشير إليه ذلك السند، وإلا فإنها ترجع الصنف نفسه. إن كان الصنف المعطى سندا لسند فإن الدالة تستمر بالبحث عن المحتوى بشكل تعاودي (recursive) حتى تصل إلى صنف غير سند فترجعه.
اشمل "مـتم/طـرفية"؛ اشمل "مـتم/سندات"؛ اشمل "مـتم/نـظام"؛ اشمل "الـقلب/بـيانات"؛ اشمل "مـتم/نـص"؛ اشمل "مـتم/تـطبيق"؛ اشمل "نـبم"؛ استخدم مـتم؛ استخدم الـقلب.أسـاسيات؛ استخدم الـقلب.بـيانات؛ استخدم الـقلب.بـيانات.شـبم؛ عرف سـندنا_لكائن_بهوية: لقب سـندنا[الـقلب.أسـاسيات.كـائن_بهوية]؛ دالة أنشئ_حيثما (كائن: سند[كـائن_بهوية]): سـندنا_لكائن_بهوية { عرف نتيجة: سـندنا_لكائن_بهوية؛ إذا كائن~مؤشر == 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();