اكتب بالعربية. شغّل هنا.

جارٍ تحميل المحرر…

يجمع هذا البرنامج الأعداد من 1 إلى 10. عند نجاحه يطبع 55 ويعيد الحالة 0. عدّل المصدر ثم اضغط «شغّل».

تجري الترجمة والتنفيذ داخل متصفحك. لا يُرسل المصدر إلى خادم.

تابع إلى تعلّم اللغة

تعلّم من برنامج واحد

أول خرج وقراءة التشخيص

ما ستتعلمه

ستغير تحية، وتتوقع خرجها الحرفي، وتستخدم موضعا مذكورا في رسالة تشخيص لإصلاح خطأ في المصدر. وستميز النص المطبوع عن حالة البرنامج.

قبل أن تبدأ

لا تحتاج إلى خبرة برمجية أو تثبيت. يشرح أول برنامج في المتصفح أدوات ساحة التجربة. المصدر هو نص برنامجك. يفحص التحقق ما إذا كان المصدر يتبع قواعد اللغة. يفحص زر التشغيل المصدر ثم ينفذ تعليماته إذا نجح التحقق.

يفتح كل مثال كامل أدناه مسودة جديدة في الصفحة الرئيسية بمصدره الأصلي. تبقى مسوداتك السابقة وتعديلاتك متاحة. يجري الفتح تحققا من المصدر لكنه لا يشغله. اضغط التشغيل بنفسك. لغة الشرح مستقلة عن مفردات المصدر. يتيح محدد المثال كلمات عربية وإنجليزية موردة، ولا يترجم التحية بين علامتي الاقتباس أو مسودتك.

اقرأ برنامجا كاملا

تحتاج ASPL إلى دالة دخول محجوزة اسمها ابدأ_الرئيسية، أو مرادفها الإنجليزي المطابق start_main. يبدأ التنفيذ منها. تعلن دالة / fn عن دالة. تعني () الفارغة أن دالة الدخول لا تأخذ معاملات. وتعني -> ص64 / -> i64 أنها تعيد عددا صحيحا يمثل حالة الانتهاء. أبق هذا التوقيع كما ورد وأنت تتعلم التعليمات داخله.

يحدد القوسان المعقوفان بداية جسم الدالة ونهايته. تنفذ التعليمات داخله بالترتيب. تكتب اطبع / print سلسلة نصية، وهي نص بين علامتي اقتباس مزدوجتين. تمرر الأقواس تلك السلسلة إلى اطبع. لا تضيف اطبع نهاية سطر. يطلب المحرفان \n داخل السلسلة نهاية سطر واحدة، فيبدأ الخرج التالي في سطر جديد. تنتهي التعليمات الإنجليزية بـ ;، ويمكن أن تنتهي التعليمات العربية بـ .. لا تظهر علامة إنهاء التعليمة في الخرج.

تنهي أرجع 0 / return 0 دالة الدخول بصورة طبيعية بحالة عملية 0. لا تطبع الرقم صفر. سنستخدم هذه النهاية في كل درس مستقل. سنتعلم تعريف دوال أخرى لاحقا.

بعد التشغيل، تحتوي منطقة الخرج على Hello ثم نهاية سطر واحدة، أي Hello\n عند تمثيل نهاية السطر بتسلسل الهروب. تعني Hello التحية بالإنجليزية، وتبقى كما كتبها المصدر حتى مع الكلمات العربية. تعرض منطقة الحالة انتهاء طبيعيا مع start_main 0. يتضمن المصدر علامات اقتباس وعلامة إنهاء تعليمة، ولا يتضمن الخرج أيا منها.

توقع قبل التشغيل

ما النص الحرفي الذي سيظهر؟ وهل ينتهي بنهاية سطر؟ هل سيظهر 0 في الخرج؟ اكتب توقعك ثم شغل المثال وقارن. ستجد سطرا واحدا هو Hello مع نهاية سطر بعده، دون طباعة صفر.

غير التحية

غير Hello فقط إلى Welcome داخل علامتي الاقتباس. أبق \n. السلوك المتوقع هو Welcome\n حرفيا، مع حالة طبيعية 0. اكتب توقعك قبل الضغط على التشغيل.

غير التحية إلى Welcome، وقارن السطر ونهاية السطر حرفيا.

تلميح: عدل النص بين علامتي الاقتباس. أبق تسلسل نهاية السطر وتوقيع الدخول وتعليمة الإرجاع كما هي.

اعرض الإجابة المشروحة

تتغير السلسلة فقط. تطبع الدالة Welcome ونهاية سطر واحدة، وتبقى أرجع 0 نهاية طبيعية دون طباعة صفر. يفتح الحل الكامل أدناه مسودة أخرى لتقارنه بتعديلك.

اتبع موضع خطأ المصدر

هذه نسخة برنامج كامل مكسورة عمدا. ينقصها القوس المعقوف الختامي. افتحها لتفحص نتيجة التحقق قبل محاولة تشغيلها.

يبلغ التحقق عن خطأ مصدر سببه expected-token: توقع right-brace ووجد end-of-file. الموضع هو السطر 4 والعمود 1، بعد آخر تعليمة مباشرة. اختر الموضع المذكور في ساحة التجربة. قد تظهر العلامة عند نهاية المصدر لأن المحرف الناقص لا يملك نصا موجودا يمكن تظليله.

أضف القوس المعقوف الختامي في ذلك الموضع. يعرض المقطع المسمى أدناه المحرف المطلوب فقط، وليس برنامجا مستقلا.

مقطع توضيحي

}

البرنامج المصحح هو مثال التحية الأصلي. ينجح التحقق الآن، ثم تختار التشغيل للحصول على Hello\n وحالة 0. لا ينفذ المصدر المكسور أي تعليمة ولا ينتج تحية، رغم ظهور تعليمة الطباعة قبل القوس الناقص. يصف تشخيص المصدر مصدرا مرفوضا. يأتي الخرج من تعليمات منفذة. وتصف الحالة الطبيعية كيفية انتهاء التنفيذ. اقرأ المزيد عن التشخيص والنتائج.

تحقق من فهمك

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

lesson-first-output-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    اطبع("Hello\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Hello\n"
native: check 0; success / status 0; stdout "Hello\n"
نزّل المصدر افتح في المحرر
aspl check lesson-first-output-ar.aspl
aspl run lesson-first-output-ar.aspl
lesson-first-output-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    print("Hello\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Hello\n"
native: check 0; success / status 0; stdout "Hello\n"
نزّل المصدر افتح في المحرر
aspl check lesson-first-output-en.aspl
aspl run lesson-first-output-en.aspl
lesson-first-output-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    اطبع("Welcome\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Welcome\n"
native: check 0; success / status 0; stdout "Welcome\n"
نزّل المصدر افتح في المحرر
aspl check lesson-first-output-solution-ar.aspl
aspl run lesson-first-output-solution-ar.aspl
lesson-first-output-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    print("Welcome\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Welcome\n"
native: check 0; success / status 0; stdout "Welcome\n"
نزّل المصدر افتح في المحرر
aspl check lesson-first-output-solution-en.aspl
aspl run lesson-first-output-solution-en.aspl
lesson-first-output-broken-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    اطبع("Hello\n").
    أرجع 0.

النتائج المتوقعة والخرج الحرفي

browser: check source-error; source-error / expected-token; stdout ""
native: check 1; source-error / status 1 / expected-token; stdout ""
نزّل المصدر افتح في المحرر
aspl check lesson-first-output-broken-ar.aspl
lesson-first-output-broken-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    print("Hello\n");
    return 0;

النتائج المتوقعة والخرج الحرفي

browser: check source-error; source-error / expected-token; stdout ""
native: check 1; source-error / status 1 / expected-token; stdout ""
نزّل المصدر افتح في المحرر
aspl check lesson-first-output-broken-en.aspl
الحدود المعيارية للإصدار

الارتباطات والحساب

ما ستتعلمه

ستسمي قيما، وتحسب بأعداد صحيحة صغيرة، وتطبع نتيجة عددية، وتقرر متى يجوز إسناد قيمة جديدة إلى اسم.

قبل أن تبدأ

اقرأ أول خرج لفهم دالة الدخول المحجوزة والطباعة ونهاية السطر الصريحة والحالة 0. يقدم هذا الدرس برنامجا كاملا مستقلا. يفتحه في مسودة جديدة ويحفظ تعديلاتك السابقة. يبقى التشغيل باختيارك.

سم القيم واحسب

يربط الارتباط اسما بقيمة مهيأة. تعلن دع / let ارتباطا ثابتا: لا يمكنك إسناد قيمة جديدة إلى الاسم لاحقا. تعلن متغير / var ارتباطا قابلا للتغيير يسمح بالإسناد لاحقا. يحتاج كلاهما إلى قيمة أولية. تقدم = هذه القيمة في التصريح. القيمتان 3 و7 عددان صحيحان صغيران، وتستنتج ASPL نوعهما ص64 / i64، فلا يلزم كتابة النوع هنا.

تجمع + عددين، وتضربهما *. يحسب تعبير مثل left + right قيمة باستخدام القيمتين المسميتين. هذه أسماء يختارها المبرمج وليست كلمات محجوزة. يبقي المصدر العربي المقدم الأسماء نفسها left وright وtotal. لا يغير تبديل لغة الشرح أسماءك.

تأخذ اطبع نصا، لذا نستخدم أولا نسق_ص64 / format_i64 لتحويل عدد من نوع ص64 إلى نصه العشري. تقرأ نسق_ص64(total) قيمة total وتعيد ذلك النص. تكتبه اطبع الخارجية. وتكتب تعليمة طباعة ثانية "\n" لإنهاء السطر. التنسيق والطباعة عمليتان منفصلتان، ولا تغير أي منهما total.

تهيئ دالة الدخول left بالقيمة 3 وright بالقيمة 7. ثم تهيئ total بمجموعهما، وهو 10، وتطبع 10\n. أخيرا تنهي أرجع 0 التنفيذ بصورة طبيعية. القيمة المحسوبة خرج وليست حالة العملية.

توقع قبل التشغيل

ما القيمة التي يحملها total؟ وما النص الحرفي المطبوع؟ إذا استبدلت + بـ *، فتوقع النتيجة الجديدة قبل التشغيل. يعطي الجمع 10 ويعطي الضرب 21. يطبع كل منهما مع نهاية سطر واحدة، وتبقى الحالة 0.

اضرب بدلا من الجمع

غير العامل فقط في تصريح total لحساب 3 * 7. الخرج المتوقع هو 21\n حرفيا، والحالة الطبيعية 0.

اجعل البرنامج يضرب 3 في 7 ويطبع 21 ثم نهاية سطر واحدة.

تلميح: غير left + right إلى left * right. أبق التنسيق العددي وتعليمة طباعة نهاية السطر المنفصلة.

اعرض الإجابة المشروحة

يضرب التعبير الجديد القيمتين المهيأتين، فتكون قيمة total هي 21. تعيد نسق_ص64 النص 21، وتضيف تعليمة الطباعة التالية نهاية السطر. يمكن أن تبقى الارتباطات الثلاثة ثابتة لأن أيا منها لا يحتاج إلى إسناد جديد.

افهم خطأ الإسناد إلى ارتباط ثابت

تحسب هذه النسخة الفاشلة عمدا 21، ثم تحاول إسناد total + 1 مجددا إلى الاسم الثابت total.

يبلغ التحقق عن immutable-assignment عند total في السطر 5 والعمود 5. اختر التشخيص للعثور على الاسم الذي تحاول التعليمة إسناد قيمة إليه. لا تنفذ أي طباعة، فلا ينتج الفشل خرجا من البرنامج. المشكلة هي السماح بتغيير الارتباط، وليست الحساب أو التنسيق.

للتغيير المقصود، غير تصريح total من دع إلى متغير، أو من let إلى var في المصدر الإنجليزي المقدم. أبق الارتباطين الآخرين ثابتين. تصبح = اللاحقة إسنادا مسموحا، وتستبدل القيمة المخزنة بـ 22.

ينجح التحقق من التصحيح ويطبع 22\n مع حالة طبيعية 0. يظل الارتباط المعلن بـ متغير محتاجا إلى قيمة أولية. لا تحتاج إلى قابلية التغيير لمجرد حساب نتيجة جديدة مرة واحدة. راجع مرجع الارتباطات والتحكم للقواعد الأوسع.

تحقق من فهمك

اشرح لماذا يحتاج شكلا التصريح إلى قيم أولية، ولماذا يطبع الضرب 21، ولماذا يحتاج مثال التغيير وحده إلى متغير. أصلح الإسناد الفاشل وقارن 22\n بتوقعك. لا تحفظ درجة أو تقدما، ويبقى التنقل مفتوحا. تابع الشروط حين تختار.

lesson-bindings-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع left = 3.
    دع right = 7.
    دع total = left + right.
    اطبع(نسق_ص64(total)).
    اطبع("\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "10\n"
native: check 0; success / status 0; stdout "10\n"
نزّل المصدر افتح في المحرر
aspl check lesson-bindings-ar.aspl
aspl run lesson-bindings-ar.aspl
lesson-bindings-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let left = 3;
    let right = 7;
    let total = left + right;
    print(format_i64(total));
    print("\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "10\n"
native: check 0; success / status 0; stdout "10\n"
نزّل المصدر افتح في المحرر
aspl check lesson-bindings-en.aspl
aspl run lesson-bindings-en.aspl
lesson-bindings-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع left = 3.
    دع right = 7.
    دع total = left * right.
    اطبع(نسق_ص64(total)).
    اطبع("\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "21\n"
native: check 0; success / status 0; stdout "21\n"
نزّل المصدر افتح في المحرر
aspl check lesson-bindings-solution-ar.aspl
aspl run lesson-bindings-solution-ar.aspl
lesson-bindings-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let left = 3;
    let right = 7;
    let total = left * right;
    print(format_i64(total));
    print("\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "21\n"
native: check 0; success / status 0; stdout "21\n"
نزّل المصدر افتح في المحرر
aspl check lesson-bindings-solution-en.aspl
aspl run lesson-bindings-solution-en.aspl
lesson-immutable-assignment-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع left = 3.
    دع right = 7.
    دع total = left * right.
    total = total + 1.
    اطبع(نسق_ص64(total)).
    اطبع("\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check source-error; source-error / immutable-assignment; stdout ""
native: check 1; source-error / status 1 / immutable-assignment; stdout ""
نزّل المصدر افتح في المحرر
aspl check lesson-immutable-assignment-ar.aspl
lesson-immutable-assignment-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let left = 3;
    let right = 7;
    let total = left * right;
    total = total + 1;
    print(format_i64(total));
    print("\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check source-error; source-error / immutable-assignment; stdout ""
native: check 1; source-error / status 1 / immutable-assignment; stdout ""
نزّل المصدر افتح في المحرر
aspl check lesson-immutable-assignment-en.aspl
lesson-mutation-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع left = 3.
    دع right = 7.
    متغير total = left * right.
    total = total + 1.
    اطبع(نسق_ص64(total)).
    اطبع("\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "22\n"
native: check 0; success / status 0; stdout "22\n"
نزّل المصدر افتح في المحرر
aspl check lesson-mutation-ar.aspl
aspl run lesson-mutation-ar.aspl
lesson-mutation-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let left = 3;
    let right = 7;
    var total = left * right;
    total = total + 1;
    print(format_i64(total));
    print("\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "22\n"
native: check 0; success / status 0; stdout "22\n"
نزّل المصدر افتح في المحرر
aspl check lesson-mutation-en.aspl
aspl run lesson-mutation-en.aspl
الحدود المعيارية للإصدار

الدوال

ما ستتعلمه

ستعرف دالة مساعدة في المستوى الأعلى بأنواع صريحة، وتمرر وسيطا، وتتتبع القيمة المرجعة، وتشرح اختلافها عن حالة عملية البرنامج.

قبل أن تبدأ

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

عرف دالة مساعدة واستدعها

تصرح دالة / fn بدالة. تقع الدالة المساعدة double في المستوى الأعلى، خارج دالة الدخول وكل جسم دالة أخرى. يسمي المعامل value: ص64 / value: i64 عددا صحيحا واردا. يعد السهم ونوع النتيجة -> ص64 / -> i64 بإرجاع عدد صحيح. تحتوي الأقواس المعقوفة تعليمات الدالة المساعدة، وترسل أرجع / return قيمة إلى المستدعي وتنهي هذا الاستدعاء.

double(6) استدعاء. يقدم الوسيط 6 قيمة المعامل لهذا الاستدعاء. تمرر الوسائط بالقيمة. داخل الدالة المساعدة تحسب value * 2 العدد 12، ثم ترسله تعليمة الإرجاع إلى موضع الاستدعاء. يخزنه المستدعي في الارتباط الثابت result. يجب أن يقدم الاستدعاء عدد الوسائط وأنواعها كما يحددها التصريح.

يبدأ التنفيذ عند دالة الدخول المحجوزة ابدأ_الرئيسية() -> ص64 / start_main() -> i64، لا عند أول تصريح بدالة مساعدة. لا ينفذ تعريف double وحده جسمها. يدخلها الاستدعاء مؤقتا ثم يستأنف التنفيذ في دالة الدخول. تحول نسق_ص64 / format_i64 قيمة result إلى نص، وتكتبها اطبع / print متبوعة بنهاية السطر الصريحة \n.

ترجع الدالة المساعدة 12 إلى مستدعيها. تطبع دالة الدخول 12\n حرفيا، ثم تعطي أرجع 0 / return 0 الخاصة بها حالة عملية طبيعية 0. لا تطبع قيمة الدالة المساعدة تلقائيا ولا تحدد حالة العملية. إرجاع double(6) مباشرة من دالة الدخول يعطي بدلا من ذلك الحالة 12، ولا ينتج خرجا دون الطباعة.

تتبع القيمة المرجعة

توقع نتيجة الدالة المساعدة والخرج المرئي وحالة العملية كل منها على حدة.

الاستدعاء في دالة الدخول المعامل value نتيجة الدالة المساعدة الخرج المطبوع الحرفي حالة الدخول
double(6) 6 12 12\n 0
double(9) 9 18 18\n 0

يغير الوسيط الجديد الحساب والبيانات المطبوعة. لا يغير تعليمة الإرجاع الأخيرة في دالة الدخول.

غير الوسيط

غير double(6) فقط إلى double(9). الخرج المتوقع هو 18\n حرفيا، والحالة الطبيعية 0.

استدع double بالوسيط 9. اشرح نتيجة الدالة المساعدة والخرج المطبوع وحالة العملية.

تلميح: غير الوسيط في موضع الاستدعاء. أبق الضرب في 2 وتعليمة أرجع 0 الأخيرة في دالة الدخول.

اعرض الإجابة المشروحة

يتلقى المعامل 9. ترجع الدالة المساعدة 9 * 2، وهو 18، وتخزن دالة الدخول هذه القيمة في result. ينتج التنسيق والطباعة 18 ثم نهاية سطر واحدة. ما زالت دالة الدخول ترجع 0، فتبقى حالة العملية 0.

أرجع قيمة في كل مسار مطلوب

يجب أن ترجع الدالة ذات النتيجة غير الوحدة قيمة من ذلك النوع في كل مسار مطلوب. تحتوي دالتنا المساعدة تعليمة إرجاع واحدة غير مشروطة. إذا استخدمت إذا ووإلا، يجب أن يرجع كل بديل قابل للوصول قيمة أو يصل إلى تعليمة إرجاع لاحقة. لا يقدم قوس الإغلاق قيمة عدد صحيح ضمنية.

ترجع هذه الدالة المساعدة المعطوبة عمدا قيمة للأعداد الموجبة فقط. رغم أن دالة الدخول تستدعيها بالوسيط 6، يمكن أن يصل مسارا الصفر والأعداد السالبة إلى نهاية الجسم دون إرجاع. يبلغ الفحص عن missing-return قبل أي تنفيذ للبرنامج. يبلغ التشغيل عن خطأ المصدر نفسه، دون خرج أو حالة عملية.

أعد تعليمة أرجع value * 2 غير المشروطة كما في نسخة البداية لتشمل كل المدخلات. تطبع نسخة البداية الكاملة المصححة 12\n وترجع الحالة 0. اقرأ مرجع الدوال للقواعد الكاملة.

الاستدعاء الذاتي اختياري

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

تحقق من فهمك

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

lesson-functions-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة double(value: ص64) -> ص64 {
    أرجع value * 2.
}

دالة ابدأ_الرئيسية() -> ص64 {
    دع result = double(6).
    اطبع(نسق_ص64(result) + "\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "12\n"
native: check 0; success / status 0; stdout "12\n"
نزّل المصدر افتح في المحرر
aspl check lesson-functions-ar.aspl
aspl run lesson-functions-ar.aspl
lesson-functions-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn double(value: i64) -> i64 {
    return value * 2;
}

fn start_main() -> i64 {
    let result = double(6);
    print(format_i64(result) + "\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "12\n"
native: check 0; success / status 0; stdout "12\n"
نزّل المصدر افتح في المحرر
aspl check lesson-functions-en.aspl
aspl run lesson-functions-en.aspl
lesson-functions-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة double(value: ص64) -> ص64 {
    أرجع value * 2.
}

دالة ابدأ_الرئيسية() -> ص64 {
    دع result = double(9).
    اطبع(نسق_ص64(result) + "\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "18\n"
native: check 0; success / status 0; stdout "18\n"
نزّل المصدر افتح في المحرر
aspl check lesson-functions-solution-ar.aspl
aspl run lesson-functions-solution-ar.aspl
lesson-functions-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn double(value: i64) -> i64 {
    return value * 2;
}

fn start_main() -> i64 {
    let result = double(9);
    print(format_i64(result) + "\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "18\n"
native: check 0; success / status 0; stdout "18\n"
نزّل المصدر افتح في المحرر
aspl check lesson-functions-solution-en.aspl
aspl run lesson-functions-solution-en.aspl
lesson-functions-missing-return-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة double(value: ص64) -> ص64 {
    إذا value > 0 {
        أرجع value * 2.
    }
}

دالة ابدأ_الرئيسية() -> ص64 {
    دع result = double(6).
    اطبع(نسق_ص64(result) + "\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check source-error; source-error / missing-return; stdout ""
native: check 1; source-error / status 1 / missing-return; stdout ""
نزّل المصدر افتح في المحرر
aspl check lesson-functions-missing-return-ar.aspl
lesson-functions-missing-return-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn double(value: i64) -> i64 {
    if value > 0 {
        return value * 2;
    }
}

fn start_main() -> i64 {
    let result = double(6);
    print(format_i64(result) + "\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check source-error; source-error / missing-return; stdout ""
native: check 1; source-error / status 1 / missing-return; stdout ""
نزّل المصدر افتح في المحرر
aspl check lesson-functions-missing-return-en.aspl
الحدود المعيارية للإصدار

استدعاء مكتبات C أصليا

تجهيز المضيف الأصلي

المضيف الأصلي فقط، إصدار ASPL 0.7.0 المنشور. اتبع مسار التثبيت الأصلي ومتطلبات النظام أولا. تستخدم الأمثلة Linux x86-64 وSystem V ABI وglibc. توفر libc.so.6 الدوال puts وabs وstrlen وmemset؛ وتوفر libm.so.6 الدالة sqrt. لا تحتاج أسطر إدخال أو وحدات مصدر أو ملفات بيانات. يظل ملف ELF المبني محتاجا إلى مكتباته المشتركة المسماة.

نزّل نسخة مصدر موردة من مجموعة C. احتفظ باسم الملف وأسماء المستخدم الأصلية. قد يحتوي المصدر ذو الكلمات الإنجليزية أسماء مستخدم ونصوصا عربية. لا يوفر أي مثال C إجراء لفتحه في المتصفح.

الطباعة عبر ملف تعريف محوّل خارجي

يصرّح مثال puts بملف التعريف الدقيق c_int__const_char_ptr الذي يحول توقيع ASPL من نص إلى ص64 إلى توقيع C int(const char *). يحتاج التصريح والاستدعاء إلى غير_آمن / unsafe. يتلقى C نسخة مؤقتة لا تخزين نص ASPL. تضيف puts فاصلة LF بعد مرحبا. يفحص البرنامج نتيجة C السالبة ويعيد 0 عند النجاح؛ لا تصلح النتيجة الموجبة غير المحددة كحالة للعملية.

aspl check puts.ar.aspl
aspl run puts.ar.aspl
aspl build -o puts-program puts.ar.aspl
./puts-program

استخدم puts.en.aspl للنسخة الإنجليزية. يطبع النجاح مرحبا\n ويخرج بالحالة 0. يستخدم مثال double المحوّل c_double__double مع libm.so.6 وsqrt؛ يفحص أن sqrt(4.0) تساوي 2.0 ولا يطبع شيئا ويخرج بالحالة 0.

التصريح بتوقيع ثابت دقيق

يشتق الوسم السياقي سي / c توقيع C ثابتا من أنواع المصدر. في المثال العادي، تستخدم abs توقيعا من ص32 إلى ص32، وتستخدم strlen توقيعا من نص إلى ط64 مع نص_سي(text) / cstring(text). يتكون نصه العربي من عشرة بايتات UTF-8؛ لذلك تعيد strlen القيمة 10 لا خمسة محارف. يفحص البرنامج النتيجتين ولا يطبع شيئا ويعيد 0.

aspl check ordinary.aspl
aspl run ordinary.aspl
aspl build -o ordinary-program ordinary.aspl
./ordinary-program

تستخدم النسختان الاسم ordinary.aspl؛ احفظ واحدة في كل مرة أو ضعهما في مجلدين منفصلين. طابق توقيع C الحقيقي تماما. اقرأ جدول التواقيع قبل تعديل التصريح. لا يستورد ASPL الترويسات ولا يستنتج توقيع الدالة من اسم الرمز.

نسخ البايتات إلى مخزن

يستورد مثال المخزن أساسي::سي، وينسخ 00 FF 41 من قائمة بايتات، ويغيّر القائمة الأصلية، ثم يستدعي memset بمدى إخراج صريح. تحتفظ القائمة المستخرجة الأولى ببايتاتها المنسوخة؛ ويتغير المخزن الأصلي المشترك إلى 20 20 20. يعالج الاستخراج الأكبر من السعة بالرمز foreign.invalid_argument ويغلق نسخة ويفحص foreign.closed عبر نسخة أخرى ثم يكرر الإغلاق بنجاح.

aspl check buffer.لبات
aspl run buffer.لبات
aspl build -o buffer-program buffer.لبات
./buffer-program

تستخدم النسختان buffer.لبات؛ احتفظ بهما في مجلدين منفصلين. لا خرج عند النجاح والحالة 0. تتشارك نسخ مخزن / Buffer مالكا أصليا واحدا. ينسخ الإنشاء والاستخراج البايتات؛ ولا ينسخ الإسناد التخزين الأصلي القابل للتغيير. راجع عمليات المخزن والمديات.

تمييز الإخفاقات والحدود

يفحص check وbuild التصريحات دون فتح المكتبات. يحل run والبرنامج المولد كل التصريحات الخارجية قبل دالة البداية، بما فيها غير المستخدمة. يعطي غياب مكتبة أو رمز الحالة 4 ويمنع آثار المصدر. يعطي غياب وسم عدم الأمان أو التوقيع غير المدعوم خطأ مصدر بالحالة 1.

يسبب NUL داخل إعارة نص C فخا قبل دخول C بالحالة 5. يعطي ملف تعريف النص الأصلي السبب foreign-string-contains-nul؛ ويعطي cstring العام السبب invalid-foreign-argument. تسبب أعداد البايتات غير الصالحة والمخازن المغلقة والنسخ المتداخلة القابلة للكتابة فخا قبل الدخول أيضا. تعيد أدوات المخزن بدلا من ذلك نتيجة فاشلة للرفض الموثق. افحص ok قبل الوصول إلى value أو error؛ تعيد أغلق / close نتيجة وحدة دون قيمة قابلة للقراءة.

تعمل الاستدعاءات العادية غير الآمنة تزامنيا وقد تحجب التنفيذ أو تنهار. لا تمنح امتيازات الإلغاء أو الاستدعاءات الراجعة المدارة. توفر الأداة العامة روابط HTTP وRaylib مدارة ومراجعة، دون واجهة عامة لتثبيت روابط مدارة اعتباطية. تستبعد هذه المجموعة تجهيزات اختبار الاستدعاءات الراجعة الخاصة بالمساهمين. راجع مرجع الواجهات الخارجية أو مجموعة HTTP أو مجموعة Raylib للعقد المناسب.

puts-ar · ASPL 0.7.0

المضيف الأصلي فقط

خاص بالمضيف الأصلي. نتيجة المتصفح المتوقعة: policy-rejection / foreign-imports-not-supported.

غير_آمن خارجي اطبع_سطر(رسالة: نص) -> ص64
    = سي_صحيح__مؤشر_محرف_ثابت("libc.so.6", "puts").

دالة ابدأ_الرئيسية() -> ص64 {
    دع النتيجة = غير_آمن اطبع_سطر("مرحبا").
    إذا النتيجة < 0 { أرجع 1. }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check policy-rejection; policy-rejection / foreign-imports-not-supported; stdout ""
native: check 0; success / status 0; stdout "مرحبا\n"
نزّل المصدر افحص رفض المتصفح
aspl check puts-ar.aspl
aspl run puts-ar.aspl
puts-en · ASPL 0.7.0

المضيف الأصلي فقط

خاص بالمضيف الأصلي. نتيجة المتصفح المتوقعة: policy-rejection / foreign-imports-not-supported.

unsafe foreign اطبع_سطر(رسالة: string) -> i64
    = c_int__const_char_ptr("libc.so.6", "puts");

fn start_main() -> i64 {
    let النتيجة = unsafe اطبع_سطر("مرحبا");
    if النتيجة < 0 { return 1; }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check policy-rejection; policy-rejection / foreign-imports-not-supported; stdout ""
native: check 0; success / status 0; stdout "مرحبا\n"
نزّل المصدر افحص رفض المتصفح
aspl check puts-en.aspl
aspl run puts-en.aspl
c-ordinary-ar · ASPL 0.7.0

المضيف الأصلي فقط

غير_آمن خارجي absolute(قيمة: ص32) -> ص32 = سي("libc.so.6", "abs").
غير_آمن خارجي byte_length(text: نص) -> ط64 = سي("libc.so.6", "strlen", نص_سي(text)).
دالة ابدأ_الرئيسية() -> ص64 {
    إذا غير_آمن absolute(ص32(-7)) ليس يطابق ص32(7) { أرجع 1. }
    إذا غير_آمن byte_length("مرحبا") ليس يطابق ط64(10) { أرجع 2. }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout ""
نزّل المصدر
aspl check c-ordinary-ar.aspl
aspl run c-ordinary-ar.aspl
c-ordinary-en · ASPL 0.7.0

المضيف الأصلي فقط

unsafe foreign absolute(value: i32) -> i32 = c("libc.so.6", "abs");
unsafe foreign byte_length(text: string) -> u64 = c("libc.so.6", "strlen", cstring(text));
fn start_main() -> i64 {
    if unsafe absolute(i32(-7)) not matches i32(7) { return 1; }
    if unsafe byte_length("مرحبا") not matches u64(10) { return 2; }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout ""
نزّل المصدر
aspl check c-ordinary-en.aspl
aspl run c-ordinary-en.aspl
c-buffer-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد أساسي::سي.
غير_آمن خارجي fill(target: سي::مخزن, byte: ص32, count: ط64) -> مؤشر_سي
    = سي("libc.so.6", "memset", إخراج(target, count)).
دالة ابدأ_الرئيسية() -> ص64 {
    متغير source: قائمة<ط8> = [0, 255, 65].
    دع created = سي::أنشئ_مخزن(source).
    إذا ليس created::نجاح { اطبع(created::الخطأ::الرمز). أرجع 1. }
    دع owned = created::قيمة.
    دع alias = owned.
    source[0] = 7.
    دع copied = سي::انسخ_بايتات(owned, ط64(3)).
    إذا ليس copied::نجاح { أرجع 2. }
    غير_آمن fill(owned, ص32(32), ط64(3)).
    دع changed = سي::انسخ_بايتات(alias, ط64(3))::قيمة.
    إذا copied::قيمة[0] ليس يطابق 0 أو copied::قيمة[1] ليس يطابق 255 أو copied::قيمة[2] ليس يطابق 65 { أرجع 3. }
    إذا changed[0] ليس يطابق 32 أو changed[1] ليس يطابق 32 أو changed[2] ليس يطابق 32 { أرجع 4. }
    دع oversized = سي::انسخ_بايتات(owned, ط64(4)).
    إذا oversized::نجاح أو oversized::الخطأ::الرمز ليس يطابق "foreign.invalid_argument" { أرجع 5. }
    إذا ليس سي::أغلق(owned)::نجاح { أرجع 6. }
    دع closed = سي::سعة(alias).
    إذا closed::نجاح أو closed::الخطأ::الرمز ليس يطابق "foreign.closed" { أرجع 7. }
    إذا ليس سي::أغلق(alias)::نجاح { أرجع 8. }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout ""
نزّل المصدر
aspl check c-buffer-ar.aspl
aspl run c-buffer-ar.aspl
c-buffer-en · ASPL 0.7.0

المضيف الأصلي فقط

import core::c;
unsafe foreign fill(target: c::Buffer, byte: i32, count: u64) -> c_ptr
    = c("libc.so.6", "memset", output(target, count));
fn start_main() -> i64 {
    var source: list<u8> = [0, 255, 65];
    let created = c::buffer(source);
    if not created::ok { print(created::error::code); return 1; }
    let owned = created::value;
    let alias = owned;
    source[0] = 7;
    let copied = c::bytes(owned, u64(3));
    if not copied::ok { return 2; }
    unsafe fill(owned, i32(32), u64(3));
    let changed = c::bytes(alias, u64(3))::value;
    if copied::value[0] not matches 0 or copied::value[1] not matches 255 or copied::value[2] not matches 65 { return 3; }
    if changed[0] not matches 32 or changed[1] not matches 32 or changed[2] not matches 32 { return 4; }
    let oversized = c::bytes(owned, u64(4));
    if oversized::ok or oversized::error::code not matches "foreign.invalid_argument" { return 5; }
    if not c::close(owned)::ok { return 6; }
    let closed = c::capacity(alias);
    if closed::ok or closed::error::code not matches "foreign.closed" { return 7; }
    if not c::close(alias)::ok { return 8; }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout ""
نزّل المصدر
aspl check c-buffer-en.aspl
aspl run c-buffer-en.aspl
الحدود المعيارية للإصدار

بناء عملاء HTTP وخوادمه أصليا

تجهيز HTTP الأصلي

المضيف الأصلي فقط، ASPL 0.7.0 المنشور. ثبّت الأداة الأصلية على Linux x86-64 مع glibc 2.34 أو أحدث. يجب أن يطبع aspl --version النص aspl 0.7.0. يرفض المتصفح والتضمين الخاص HTTP قبل التنفيذ. تحفظ التنزيلات المصدر المورّد ولا تفتح مسودة متصفح أو تشغّل برنامجا.

نزّل الجذر ووحداته المطلوبة من مجموعة HTTP. احفظ النسختين العربية والإنجليزية في مجلدين منفصلين بأسماء الملفات الأصلية. تبقى أسماء الوحدات ومعرّفات المستخدم نفسها لكن تختلف بايتات مصدر الوحدات. يستورد كل ملف ما يستخدمه؛ يفعّل استورد أساسي::ويب. البادئة ويب وimport core::http; البادئة http. تتاح البادئة المكتوبة فقط ولأعضاء المكتبة تسميات مكافئة دقيقة. تصلح .aspl و.لبات للجذور والوحدات المستوردة.

يسرد مرجع الواجهة الأنواع والتواقيع والقيم الافتراضية والحدود ورموز الأخطاء. اتبع دليل النشر لتجهيز الشهادات وثقة النظام والنشر. يحتفظ الدليل الخام السابق (يفتح في نافذة جديدة) ومصدر النشر الخام (يفتح في نافذة جديدة) بنطاق إصدارهما السابق.

خدمة النص وJSON والبايتات

نزّل عائلة الخدمة مع settings.aspl وhandlers.لبات من نسخة المصدر المختارة وضعها معا. من مجلد المصدر شغّل:

aspl check service.لبات
aspl run service.لبات

استخدم service.aspl للمصدر الإنجليزي. تبقى الخدمة في المقدمة على 127.0.0.1:8080؛ وفّر المنفذ أولا. لا تحتاج أسطر إدخال أو أصول بيانات لتمرين العميل العادي. يحتاج مسار /upstream أيضا server.pem الموثوق في مجلد عمل العملية ونظيرا موثقا على https://localhost:9443/hello.

الدالة handlers::handle مسماة على المستوى الأعلى ولا تلتقط متغيرات محلية. يطابق طلبها وسياق<app::Config,app::State> هويات أنواع الموجه. يرفض المدقق مسارات المعالج غير الآمنة والحاجبة، بما فيها استدعاءات C العادية وإدخال السطر والملف عبر دوال مساعدة. تتقدم المعالجات المقبولة الأخرى أثناء انتظار طلب HTTP تابع، مع بقاء تنفيذ ASPL متسلسلا.

يعيد GET /hello النص مرحبا من ASPL. يفحص POST /submit صلاحية UTF-8 ويعيد نص JSON الصريح مع application/json; charset=utf-8 دون تحليل بنيته أو التحقق منها. يعيد POST /bytes البايتات، ويعيد GET /download البايتات 00 FF 41 تماما. يعرض /count الحالة قبل زيادتها. تعيد اقرأ_حالة نسخة قيمة وتنشر استبدل_حالة استبدالا كاملا. القراءة والانتظار والاستبدال ليست ذرية؛ أعد القراءة بعد الانتظار أو استخدم لقطات الإصدار.

يجري GET /upstream طلبا تابعا موثقا بإعدادات app::Config. يتحول فشل الابن إلى 502 يحوي رمزه المستقر ما دام الأب حيا. ينهي إلغاء الأب العمل التابع ويلغي الخرج والنشر المتأخرين ولا يستأنف المعالج الملغى بنتيجة فاشلة. مرّر بايتات المتن عن قصد؛ قد تكون بيانات طول الضغط وترميزه لدى الطرف المقابل غير مناسبة للاستجابة الجديدة.

فحص نتائج العميل

ضع جذر العميل بجوار requests.لبات المطابق. شغّل الخدمة ثم افتح نافذة أخرى في مجلد المصدر:

aspl check client.aspl
aspl run client.aspl

يفحص العميل النص وإعادة JSON والبايتات الدقيقة واستجابة 404 مكتملة. يطبع checked text, JSON, 00 FF 41, and 404 بلا سطر جديد أخير ويعيد 0. تعيد ويب::اطلب نتيجة ناجحة للاستجابة المكتملة 404 أو 500؛ افحص حالة منفصلة. يعيد فك UTF-8 غير الصالح http.invalid_utf8 وتبقى بايتات المتن متاحة. لا محلل أو مولد JSON ضمني.

يفترض مثال الرفض عدم وجود مستمع على 127.0.0.1:9 ويطبع http.connect_failed ويعيد 0 بعد فحص الفشل. يغيّر وجود نظير الافتراض. اتخذ القرار وفق الخطأ::الرمز لا نص التشخيص البشري. تختلف النتائج القابلة للاسترداد عن أخطاء المصدر والفخاخ النهائية وإلغاء التنفيذ.

توثيق HTTPS ومراعاة الحدود

تستخدم خدمة TLS المباشر الوحدات نفسها على 127.0.0.1:8443. وفّر server.pem وserver.key المطابق غير المشفر في مجلد العمل. يستخدم عميل HTTPS العنوان https://localhost:8443 ويثق صراحة في server.pem، مع localhost في DNS SAN للشهادة. يحل CA الخاص محل ثقة النظام ويبقي فحص السلسلة والتواريخ والهوية إلزاميا. يعيد غياب مواد الخادم أو فسادها http.tls_config_failed قبل الاستماع.

aspl check direct-tls.لبات
aspl run direct-tls.لبات

في نافذة العميل المنفصلة:

aspl check client-tls.لبات
aspl run client-tls.لبات

يطلب عميل ثقة النظام العنوان https://localhost:9443/hello. يشترط النجاح شهادة نظير موثوقة عند المضيف. تنتج الشهادة المحلية غير الموثوقة http.tls_verify_failed وخرج الرمز وحالة 1. تعيد الثقة المفقودة أو التالفة http.ca_load_failed. راجع تجهيز الشهادة واختيار الثقة.

اتبع تمرين نشر الطرف العلوي الكامل للنظير المطابق ومجلد العمل والطلبات الموثقة ونتائج الإخفاق.

اتباع التحويلات وفك gzip معطّلان افتراضيا. تبقى التحويلات المفعّلة ضمن origin واحد وتشترك في المهلة الكلية الأصلية. يفحص gzip حدي المتن المرمز والمفكوك. لا إعادة محاولة نقل تلقائية. يثبت مثال الحدود أن خفض سعة الصادر إلى أقل من 16 اتصالا خاملا افتراضيا يستلزم خفض سعة الخامل أيضا. لا تحجز الإعدادات العددية موارد. راجع حدود التنفيذ والرسائل والمهل.

تقدم الجلسة ونشر الحالة المنسوخة

استخدم اخدم حين تدير الخدمة تدفق التطبيق. استخدم ابدأ للحصول على جلسة<C,S> واستدعِ تقدم صراحة من التطبيق. يعني نجاح البدء جاهزية المستمعين؛ لا تعمل المعالجات العادية إلا عبر التقدم. لا تعمل دوال الجلسة الخاصة بالتطبيق داخل المعالج. تنتهي صلاحية سياق المعالج مع استدعائه.

يحتاج مثال الجلسة المنفذ الحر 127.0.0.1:8081 دون نظير أو ملفات TLS. ينسخ الحالة دون نشر التعديل المحلي وينشر 11 وفق لقطة حالية ويفحص نجاحا بقيمة خطأ للنشر القديم. ثم يطلب التصريف ويتقدم حتى جلسة_مغلقة ويكرر إغلاق النسخ ويفحص http.closed_session. تبقى اللقطة المحفوظة بقيمة 10. لا خرج للنجاح وحالته 0.

aspl check session.aspl
aspl run session.aspl

تشترك نسخ الجلسة في مالك مدار واحد. يبطل إغلاق نسخة كل النسخ ويحرر فقدان آخر نسخة قابلة للوصول المورد. تحوي لقطة_حالة<S> قيمة منسوخة للقراءة فقط وهوية جلسة وإصدار خفيين. يفشل نشر لقطة جلسة أخرى بـhttp.invalid_argument. تحتفظ المقابض المدارة في اللقطات بالمالك الأصلي نفسه ولا تنسخ حالته الأصلية المتغيرة. راجع أعمار الخدمة والنشر.

الإغلاق وبناء ELF

أرسل POST /stop للخدمة العادية من نافذة أخرى:

curl --http1.1 --request POST http://127.0.0.1:8080/stop

للخدمة المشفرة استخدم CA الموثوق ومنفذها:

curl --http1.1 --cacert server.pem --request POST https://localhost:8443/stop

تطلب أوقف(ctx) من المعالج التصريف ويقبل تكرارها. يمكن للاستجابة الحالية الاكتمال. لا تعود اخدم عاديا قبل تحرير العمل المملوك. تحتاج أوقف_الجلسة إلى تقدم لاحق حتى الإغلاق. تنهي أغلق_الجلسة العمل وتحرر المالك. تصرّف أول Ctrl+C أو SIGTERM ثم تنهي التنفيذ بحالة 7، وتتجاوز الإشارة الثانية بقية التصريف. يبقى الفخ نهائيا بحالة 5 ولا يتحول تلقائيا إلى 500. قد يلغي انتهاء الأب أو قطع الاتصال أو انتهاء التصريف اكتمال المعالج ونشر الحالة.

aspl build -o service-program service.لبات
aspl build -o client-program client.aspl
./service-program --aspl-diagnostic-language=ar --aspl-color=never

شغّل ./client-program في نافذة أخرى ثم أرسل POST /stop. استخدم اسم الجذر الإنجليزي عند بناء تلك النسخة. يتضمن ELF الوحدات المفحوصة والآلة الافتراضية ويعمل دون ASPL أو ملفات المصدر أو مترجم C. تبقى ملفات TLS ومكتبات C المشتركة المصرح بها مدخلات خارجية. يقبل البرنامج المولد خيارات التشخيص واللون المحجوزة؛ لا أوامر ASPL أو معاملات تطبيق عامة. راجع البناء وحالة العملية.

http-service-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد أساسي::ويب.
استورد settings.aspl بسم app.
استورد handlers.لبات بسم handlers.
دالة ابدأ_الرئيسية() -> ص64 {
    دع result = ويب::اخدم(app::server(خطأ), handlers::routes(),
        app::Config { upstream: "https://localhost:9443/hello", ca: "server.pem" },
        app::State { count: 0 }).
    إذا ليس result::نجاح { اطبع(result::الخطأ::الرمز). أرجع 1. }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout ""
نزّل المصدر
aspl check http-service-ar.aspl
aspl run http-service-ar.aspl
http-service-en · ASPL 0.7.0

المضيف الأصلي فقط

import core::http;
import settings.aspl as app;
import handlers.لبات as handlers;
fn start_main() -> i64 {
    let result = http::serve(app::server(false), handlers::routes(),
        app::Config { upstream: "https://localhost:9443/hello", ca: "server.pem" },
        app::State { count: 0 });
    if not result::ok { print(result::error::code); return 1; }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout ""
نزّل المصدر
aspl check http-service-en.aspl
aspl run http-service-en.aspl
http-client-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد requests.لبات بسم requests.
دالة ابدأ_الرئيسية() -> ص64 { أرجع requests::exercise("http://127.0.0.1:8080", خطأ). }

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "checked text, JSON, 00 FF 41, and 404"
نزّل المصدر
aspl check http-client-ar.aspl
aspl run http-client-ar.aspl
http-client-en · ASPL 0.7.0

المضيف الأصلي فقط

import requests.لبات as requests;
fn start_main() -> i64 { return requests::exercise("http://127.0.0.1:8080", false); }

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "checked text, JSON, 00 FF 41, and 404"
نزّل المصدر
aspl check http-client-en.aspl
aspl run http-client-en.aspl
http-session-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد أساسي::ويب.
سجل State { count: ص64 }
دالة handle(req: ويب::طلب_وارد, ctx: ويب::سياق<منطقي,State>) -> ويب::استجابة_خادم {
    دع saved = ويب::التقط_الحالة(ctx).
    دع published = ويب::استبدل_الحالة_إن_كانت_حالية(ctx, saved, State { count: saved::قيمة::count + 1 }).
    إذا ليس published::نجاح أو ليس published::قيمة { أرجع ويب::أنشئ_استجابة(409, [])::قيمة. }
    أرجع ويب::أنشئ_استجابة(200, [])::قيمة.
}
دالة ابدأ_الرئيسية() -> ص64 {
    دع routes = ويب::أنشئ_موجه([ويب::أنشئ_وجهة("GET", "/", handle)::قيمة])::قيمة.
    متغير server = ويب::إعدادات_خدمة().
    server::مستمعون = [ويب::أنشئ_مستمع("127.0.0.1", 8081)::قيمة].
    دع started = ويب::ابدأ(server, routes, خطأ, State { count: 10 }).
    إذا ليس started::نجاح { اطبع(started::الخطأ::الرمز). أرجع 1. }
    دع owner = started::قيمة.
    دع alias = owner.
    دع saved = ويب::التقط_حالة_الجلسة(owner)::قيمة.
    متغير copied = ويب::حالة_الجلسة(owner)::قيمة.
    copied::count = 99.
    إذا ويب::حالة_الجلسة(owner)::قيمة::count لا يطابق 10 { أرجع 2. }
    دع published = ويب::استبدل_حالة_الجلسة_إن_كانت_حالية(owner, saved, State { count: 11 }).
    إذا ليس published::نجاح أو ليس published::قيمة { أرجع 3. }
    دع stale = ويب::استبدل_حالة_الجلسة_إن_كانت_حالية(alias, saved, State { count: 12 }).
    إذا ليس stale::نجاح أو stale::قيمة { أرجع 4. }
    إذا ويب::حالة_الجلسة(owner)::قيمة::count لا يطابق 11 { أرجع 5. }
    إذا ليس ويب::أوقف_الجلسة(owner)::نجاح { أرجع 6. }
    متغير budget = ويب::ميزانية_التقدم().
    budget::زمن_الانتظار_مللي = 1.
    متغير closed = خطأ.
    طالما ليس closed {
        دع advanced = ويب::تقدم(owner, budget).
        إذا ليس advanced::نجاح { اطبع(advanced::الخطأ::الرمز). أرجع 7. }
        closed = advanced::قيمة يطابق ويب::جلسة_مغلقة.
    }
    إذا ليس ويب::أغلق_الجلسة(alias)::نجاح أو ليس ويب::أغلق_الجلسة(owner)::نجاح { أرجع 8. }
    إذا ويب::حالة_الجلسة(alias)::الخطأ::الرمز لا يطابق "http.closed_session" { أرجع 9. }
    إذا saved::قيمة::count لا يطابق 10 { أرجع 10. }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout ""
نزّل المصدر
aspl check http-session-ar.aspl
aspl run http-session-ar.aspl
http-session-en · ASPL 0.7.0

المضيف الأصلي فقط

import core::http;
record State { count: i64 }
fn handle(req: http::IncomingRequest, ctx: http::Context<bool,State>) -> http::ServerResponse {
    let saved = http::snapshot_state(ctx);
    let published = http::replace_state_if_current(ctx, saved, State { count: saved::value::count + 1 });
    if not published::ok or not published::value { return http::response(409, [])::value; }
    return http::response(200, [])::value;
}
fn start_main() -> i64 {
    let routes = http::router([http::route("GET", "/", handle)::value])::value;
    var server = http::server_config();
    server::listeners = [http::listener("127.0.0.1", 8081)::value];
    let started = http::start(server, routes, false, State { count: 10 });
    if not started::ok { print(started::error::code); return 1; }
    let owner = started::value;
    let alias = owner;
    let saved = http::snapshot_session_state(owner)::value;
    var copied = http::session_state(owner)::value;
    copied::count = 99;
    if http::session_state(owner)::value::count not matches 10 { return 2; }
    let published = http::replace_session_state_if_current(owner, saved, State { count: 11 });
    if not published::ok or not published::value { return 3; }
    let stale = http::replace_session_state_if_current(alias, saved, State { count: 12 });
    if not stale::ok or stale::value { return 4; }
    if http::session_state(owner)::value::count not matches 11 { return 5; }
    if not http::stop_session(owner)::ok { return 6; }
    var budget = http::progress_budget();
    budget::wait_ms = 1;
    var closed = false;
    while not closed {
        let advanced = http::progress(owner, budget);
        if not advanced::ok { print(advanced::error::code); return 7; }
        closed = advanced::value matches http::SESSION_CLOSED;
    }
    if not http::close_session(alias)::ok or not http::close_session(owner)::ok { return 8; }
    if http::session_state(alias)::error::code not matches "http.closed_session" { return 9; }
    if saved::value::count not matches 10 { return 10; }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout ""
نزّل المصدر
aspl check http-session-en.aspl
aspl run http-session-en.aspl
الحدود المعيارية للإصدار

الرسم وتشكيل النص وتشغيل الصوت وخدمة HTTP باستخدام Raylib

تجهيز المضيف الأصلي

المضيف الأصلي فقط، ASPL 0.7.0 المنشور. ثبّت الأدوات الأصلية. استورد core::raylib أو أساسي::رايليب في كل وحدة مصدر تستخدم المكتبة. تقبل كل بادئة مستوردة أسماء الأعضاء العربية والإنجليزية المتطابقة. استورد الصيغتين لاستخدام البادئتين القصيرتين. تحتفظ أسماء المستخدم والنصوص والمسارات ببايتاتها.

لا يحتاج الفحص والبناء إلى شاشة أو مترجم C. يحتاج تشغيل نافذة إلى Linux بمعمارية x86_64 وglibc 2.34 أو أحدث وشاشة Wayland/EGL أو X11/GLX متاحة وOpenGL 3.3 core. يستخدم XWayland مسار X11. تضمّن الأداة خلفية Raylib 6.0 المثبتة، فلا تحتاج إلى Raylib نظامي. راجع متطلبات النظام.

عند وجود النقطتين تختار القيمة الدقيقة XDG_SESSION_TYPE=wayland مسار Wayland أولا، وتختار القيم الأخرى X11 أولا. عند وجود قيمة غير فارغة واحدة من WAYLAND_DISPLAY أو DISPLAY يحاول التنفيذ ذلك المسار وحده. يمكن أن ينتقل إلى النقطة الأخرى بعد تحرير آمن لفشل الأولى. عند غياب النقطتين يعيد InitWindow الرمز raylib.host_unavailable. لا يوجد نجاح لنافذة بلا شاشة. تبقى الخلفية الناجحة ثابتة حتى الإغلاق.

نزّل البرامج من مجموعة Raylib. تسرد كل عائلة الصيغ الموردة والملفات المرخصة قبل المصدر. احتفظ بأسماء المصادر ومسارات الأصول الأصلية. تحتاج عائلة الصور إلى PNG وإشعاره تحت docs/examples/assets نسبة إلى مجلد عمل العملية. لا تحتاج هذه العائلات إلى وحدات مصدر. يرفض المتصفح المكتبة حتى إن لم يستخدم الاستيراد.

فحص كل نتيجة

تعيد العمليات العادية result<T>، وتعيد فحوص الجاهزية والصلاحية bool مباشرة. افحص ok / نجاح قبل قراءة value / قيمة أو error / الخطأ. تؤدي قراءة الفرع الخطأ إلى مصيدة. قارن رمز ASCII الثابت error::code، ورسائل Raylib تضم اللغتين. استخدم --diagnostic-language=en لتشخيصات CLI أو --aspl-diagnostic-language=en للبرنامج الناتج.

مقطع توضيحي

استورد أساسي::رايليب.
دالة ابدأ_الرئيسية() -> ص64 {
    دع فتح = رايليب::هيئ_نافذة(640, 360, "سلام ASPL").
    إذا لا فتح::نجاح { اطبع(فتح::error::الرمز). أرجع 1. }
    دع إغلاق = رايليب::أغلق_النافذة().
    إذا لا إغلاق::نجاح { اطبع(إغلاق::error::الرسالة). أرجع 2. }
    أرجع 0.
}

يوضح المقطع فحص استدعاءات دورة الحياة. تحتفظ البرامج الكاملة القابلة للتنزيل أدناه بنتائج الفهرس. راجع مرجع الواجهة للأحجام الدقيقة والسياقات والإخفاقات.

امتلاك جيل نافذة

استدع SetConfigFlags قبل فتح النافذة. يستبدل أعلام النافذة التالية المحفوظة. يقبل SetTargetFPS معدلا غير سالب، والصفر يزيل سقف التوقيت. افتح بأبعاد i32 موجبة وعنوان دون NUL. تنسخ الأداة العناوين وتحتفظ بها حتى الاستبدال أو انتهاء الاستخدام الأصلي. يحتاج SetWindowTitle إلى نافذة حية وإطار مغلق.

يمتلك تنفيذ واحد حجز أجهزة العملية. تجري عمليات الجهاز على الخيط الرئيسي للعملية. IsWindowReady فحص كلي، وWindowShouldClose ملاحظة مفحوصة. لا يغلق طلب الإغلاق النافذة بذاته. يقرر التطبيق متى ينتهي أو يغلقها. ينجح CloseWindow عندما تكون مغلقة بالفعل.

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

إقران إطارات الرسم

استدع BeginDrawing ثم ClearBackground وعمليات الرسم ثم EndDrawing. تحتاج عمليات الرسم والمسح إلى إطار مفتوح. تعيد البداية المكررة أو النهاية غير المقترنة raylib.invalid_order وتحفظ الحالة الحالية. أغلق وضع الكاميرا قبل إنهاء الإطار.

يحتاج التحميل ودورة حياة النافذة وتغييرات العنوان ومفتاح الخروج وFPS ومرشح النسيج والتفافه إلى إطار مغلق. تستطيع ملاحظات الإدخال والتوقيت قراءة العينة الحالية داخل الإطار. يعرض EndDrawing العمل المقبول ويستطلع أحداث المضيف ويطبق التوقيت المستهدف. يعيد GetTime النوع f64 وGetFrameTime النوع f32 وGetFPS النوع i32. تعرض النافذة الجديدة زمن إطار وFPS صفريين قبل أول إطار مكتمل.

تعرض عائلة الإطارات تكرارين قصيرين وتفحص إعادة ضبط التوقيت بعد الفتح. FPS هدف ولا يضمن أداء المضيف المشغول.

قراءة عينات لوحة المفاتيح والفأرة والحجم

تحتاج ملاحظات النافذة والإدخال إلى نافذة حية للتنفيذ المستدعي والخيط الرئيسي. تقرأ حالة مأخوذة ولا تثبت استدعاءات راجعة للمصدر. استخدم ثوابت Key وMouseButton الدقيقة، ولا يجوز بناؤها من أعداد صحيحة. تصف Down وUp حالة الاستمرار، وتصف Pressed وReleased الانتقالات، ويشمل IsKeyPressedRepeat ملاحظات التكرار.

يستهلك GetKeyPressed مفتاحا واحدا من الطابور ويعيد KEY_NULL عند فراغه. يستهلك GetCharPressed قيمة محرف Unicode واحدة ويعيد صفرا عند الفراغ. كرر الاستدعاء لتفريغ الطوابير عند الحاجة. حدث المفتاح والنص المكتوب ملاحظتان منفصلتان. يعطل SetExitKey(KEY_NULL) مفتاح الخروج، ويعيد فتح نافذة جديدة مفتاح الهروب.

تستخدم مواضع الفأرة وفروقها والعجلة قيما f32 مفحوصة. قد يختلف GetScreenWidth وGetScreenHeight المنطقيان عن GetRenderWidth وGetRenderHeight الفيزيائيين. يعرض IsWindowResized عينة تغيير الحجم الحالية.

مشاركة الأنسجة وإغلاقها

يقبل LoadTexture ملفات PNG ويحتاج إلى نافذة حية خارج الإطار. تحل المسارات نسبة إلى مجلد عمل العملية. افحص النتيجة قبل أخذ Texture المعتم. يعيد GetTextureWidth وGetTextureHeight بيانات مفحوصة. اختر المرشح POINT أو BILINEAR والالتفاف REPEAT أو CLAMP خارج الإطارات.

تشارك نسخ النسيج مالكا مدارا واحدا قابلا للإغلاق. يغلق UnloadTexture عبر أي نسخة كل النسخ، وينجح تكراره. يعيد IsTextureValid بعدها خطأ. تعيد بقية عمليات الوصول raylib.closed_resource حتى إن اختفت النافذة السابقة أيضا. يحتفظ الرسم المقبول بالذاكرة الخلفية حتى انتهاء استخدامها الأصلي، فلا يبطل التحرير المنطقي في الإطار الأخير العمل المقبول قبله. لا تعيد إعادة فتح النافذة إحياء الأنسجة القديمة.

ارسم باستخدام DrawTexture أو DrawTextureV أو DrawTextureEx أو DrawTextureRec أو DrawTexturePro. تحافظ أبعاد مستطيل المصدر الموقعة على الانعكاس. يحتفظ المقياس الصفري أو السالب ومستطيلات الوجهة الموقعة بسلوك Raylib المقبول، مع فحص الحسابات الناتجة قبل الدخول الأصلي.

تحويل إحداثيات كاميرا2

أنشئ كل حقول Camera2D، الإزاحة والهدف والدوران والتكبير الموجب. تقاس الزوايا بالدرجات. يحتاج BeginMode2D(camera) إلى إطار رسم مفتوح دون وضع كاميرا نشط. أقرنه بـEndMode2D قبل EndDrawing. تعيد الأوضاع المتداخلة أو غير المقترنة raylib.invalid_order دون تغيير الزوج الحالي.

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

ترسم عائلة أشكال الكاميرا مستطيلا ودائرة وخطا سميكا ومثلثا عبر الكاميرا، ثم نقطة وحدودا بإحداثيات الشاشة.

اختبار التصادم في فضاء إحداثيات واحد

مساعدات التصادم عمليات نقية مفحوصة. لا تحتاج إلى شاشة أو إطار أو مالك مورد ويسمح بها في معالجات HTTP والاستدعاءات الراجعة المدارة. الرسم وعمليات الجهاز للتطبيق فقط، ولا يستطيع مساعد أو قيمة دالة مخزنة تجاوز قيود آثارها.

استخدم CheckCollisionRecs وGetCollisionRec للمستطيلات أو اختبارات الدائرة والمستطيل والنقطة والمثلث في المرجع. قدم المعاملين في فضاء الإحداثيات نفسه. يجب أن يكون نصف القطر غير سالب. تتبع الأشكال الموقعة أو المنحلة المقبولة سلوك الخلفية المثبتة. قد تعيد الحسابات الناتجة المفحوصة raylib.numeric_overflow حتى عندما تكون كل المدخلات منتهية.

تتحقق عائلة الصور من تداخل المستطيلين عند 24,24 و30,28، ثم ترسم التقاطع المعاد بالأحمر داخل وضع الكاميرا. يفحص ذلك هندسة التصادم وموضع الرسم.

اختيار الخطوط المضمنة أو المخصصة

يعيد GetFontDefault الخط العربي واللاتيني المضمن بحجم أساسي 32. لا يحتاج النص على المعالج إلى شاشة أو جهاز صوت. تستخدم حزمة HarfBuzz وICU وFreeType المثبتة Unicode 17 وخطي Noto Sans Arabic Regular 2.013 وNoto Sans Regular 2.015 المضمنين. لا تستبدل خطوط المضيف أو لغته أو ICU_DATA هذه القاعدة. يتضمن ملف الإشعارات المرافق تراخيص الخطوط ونسبة FreeType وإخلاء مسؤوليتها.

للخط المخصص، قدم ملف حدود TrueType مرخصا ذا وجه واحد نسبة إلى مجلد العمل. يستخدم LoadFont الحجم الأساسي 32. يقبل LoadFontEx حجما أساسيا 1..4096 وتلميحات تجهيز منسوخة من نوع list<i32> لقيم المحارف. تعني القائمة الفارغة عدم التجهيز المسبق ولا تحد التغطية. لا تدعم مجموعات الخطوط أو CFF/PostScript أو WOFF/WOFF2 أو خطوط الصور النقطية والألوان. تعيد الجداول المطلوبة المعطوبة raylib.invalid_font، والملفات غير المدعومة raylib.unsupported_font، وفشل قراءة الملف raylib.load_failed.

يجرب الاختيار الخط المخصص ثم الخط المضمن الاحتياطي المفضل للنظام الكتابي. يحافظ على عناقيد المحارف وتسلسلات الوصل العربية معا. يتطلب اختيار خط عربي مخصص ميزات الوصل والعلامات المقبولة. لا يقبل مربعات بديلة نهائية، ويعيد النص غير المغطى raylib.missing_glyph.

تشارك نسخ الخط الإغلاق. يملك الخط المخصص نسخة من بايتات الملف، فلا يغير استبدال الملف بعد التحميل النص الموجود. يغلق UnloadFont نسخ الخط المخصص، وتحتفظ التخطيطات الموجودة ببيانات الخط المستقلة. ينجح تحرير الخط الافتراضي دون إبطاله. يقرأ GetFontBaseSize البيانات ولا يضبط حجم التصيير. يتطلب تحميل الخط سياق التطبيق والخيط الرئيسي خارج الإطارات، ولا يحتاج إلى نافذة حية. يسمح بالوصول الافتراضي والقياس وإنشاء التخطيط والتحرير على المعالج في معالجات HTTP والاستدعاءات الراجعة المدارة.

حفظ ترتيب النص المنطقي وقياس تخطيطه

قدم النص بترتيبه المنطقي. لا يعيد الوصل العربي والربط والعلامات وترتيب الاتجاهين العربي واللاتيني كتابة النص أو تسوية المعرفات أو تغيير بايتات المسار. يستخدم MeasureText وDrawText الاتجاه Auto والمحاذاة Start دون التفاف أو تباعد إضافي للأسطر. يشترط MeasureTextEx وDrawTextEx وDrawTextPro تباعد محارف صفريا.

يأخذ CreateTextLayout حقول TextOptions الستة كلها. font_size منته في 0.5..4096. direction هو Auto أو LTR أو RTL. يستخدم Auto أول محرف قوي، ويختار LTR للفقرات المحايدة فقط. يفعل has_width قيمة width منتهية موجبة، وإلا يكون العرض غير نشط. alignment هو Start أو End أو Center أو Left أو Right. يتبع Start وEnd اتجاه الفقرة الأساسي، أما Left وRight فجانبان فيزيائيان. line_spacing منته وغير سالب.

يستخدم الالتفاف فواصل أسطر ICU الجذرية ثم فواصل طارئة بين عناقيد المحارف. قد يتجاوز عنقود كبير العرض المقدم. تفصل LF وCR وCRLF وU+2029 الفقرات، وتكسر U+2028 السطر. تتبع الأسطر الفارغة والنهائية وتحكم الاتجاهين وZWJ/ZWNJ والواصلات اللينة قواعد التخطيط. للنص الفارغ صفر من الأسطر والارتفاع. تعيد NUL وعلامة الجدولة وDEL ومحارف Cc الأخرى غير المدعومة raylib.invalid_text.

يعيد MeasureTextLayout النوع TextMetrics. size صندوق منطقي يستخدم العرض المقدم عندما يكون نشطا. ink حدود المحارف المحلية بما فيها العلامات والتجاوزات. يقرب الحجم الفعلي إلى 1/64 مع كسر التعادل نحو العدد الزوجي. يقبل MeasureText أحجاما صحيحة 1..4096 ويقرب عرض النص المشكل لأعلى إلى i32 مفحوص. يعيد MeasureTextEx الحجم المنطقي من نوع Vector2. تعمل هذه العمليات على المعالج قبل إنشاء نافذة.

التخطيطات ملاك مشتركون ثابتون. يغلق تحرير نسخة كل النسخ وينجح تكراره. يحتفظ التخطيط بخطوطه بعد تحرير Font المخصص ويبقى بعد إغلاق النافذة وإعادة فتحها. يعيد الوصول إلى تخطيط مغلق raylib.closed_resource، ويعيد فحص الصلاحية خطأ.

رسم المواضع المقاسة

يرسم DrawTextLayout عند الركن العلوي الأيسر المنطقي. يضيف DrawTextLayoutPro الأصل والدوران. يشكل DrawTextEx وDrawTextPro النص المنطقي نفسه بتباعد محارف صفري. يحول الأصل والدوران وCamera2D الموضع دون تغيير المقاييس المحلية. يحافظ إخلاء مخبأ المحارف على هذه المقاييس.

يتطلب رسم النص خيط التطبيق الرئيسي ونافذة حية وإطار رسم مفتوحا. لا يرسل فشل التحقق أو المحرف أو الحساب أو التجهيز المعروف أي جزء من طلب النص. يبقى الرسم المقبول سابقا صالحا. قد يحتفظ العمل المقبول ببيانات المحارف بعد التحرير المنطقي حتى العرض أو انتهاء الاستخدام الأصلي.

تجهز عائلة النص المشكل والصوت تخطيطها وتقيسه قبل فتح النافذة. توضح الحدود الرمادية الصندوق المنطقي والحمراء الحبر. يلزم ملف النغمة OGG الأصلي وإشعار CC0 خارجيا، والخطوط الافتراضية مضمنة.

تهيئة الصوت وتحديث الموسيقى

يجرب InitAudioDevice خدمة PulseAudio عبر libpulse.so.0 ثم ALSA مباشرة عبر libasound.so.2، بما فيه فشل بدء التشغيل. يعمل PipeWire عبر خدمته المتوافقة مع PulseAudio. يتطلب كل انتقال تحريرا كاملا آمنا. يبقى المسار الناجح ثابتا حتى الإغلاق، ولا يوجد نجاح بجهاز وهمي. يشترك الصوت والنافذة في حجز جهاز العملية للتنفيذ مع نطاقي إغلاق وتراجع منفصلين.

حمل Sound أو Music بعد تهيئة الصوت وخارج إطارات الرسم. يفك LoadSound بايتات WAV/OGG/MP3 منسوخة. يحتفظ LoadMusicStream ببايتات منسوخة ومفكك ومخازن بث محدودة مستقلة عن الملف الأصلي. التشغيل والإيقاف المؤقت والاستئناف والإيقاف ومستوى الصوت والتوازن والحدة والبحث والتكرار وUpdateMusicStream عمليات للتطبيق وخيطه الرئيسي مسموحة داخل إطار. مستوى الصوت منته في 0..1 والتوازن في -1..1 والحدة منتهية موجبة. يجب أن يلائم معدل إعادة التعيين الناتج النطاق الأصلي المقبول. يحفظ الرفض الحدة السابقة، ويعيد فشل المحول قيمتها أو يغلق ذلك المالك.

لا يفك تشغيل الموسيقى وحده العينات ولا يملأ مخازنها. استدع UpdateMusicStream صراحة، عادة مرة في كل إطار. يعرض GetMusicTimeLength وGetMusicTimePlayed ثواني f32 مفحوصة. يقبل SeekMusicStream المجال 0..الطول المبلغ عنه شاملا الطرفين. الطرف الأخير نهاية منطقية للملف. يعيد التحديث التالي تشغيل الموسيقى الجارية المتكررة أو يوقف الموسيقى غير المتكررة والفارغة. يبقى تحديث الموسيقى الموقوفة أو المتوقفة مؤقتا غير نشط. يغلق رفض البحث من المفكك نسخ Music ويعيد raylib.load_failed.

تشارك نسخ Sound وMusic مالكا قابلا للإغلاق في جيل الصوت الحالي. يوقف التحرير التشغيل ويلغي تتبعه، ويبطل إغلاق الجهاز كل التوابع قبل التدمير الأصلي. لا يحيي الفتح الجديد النسخ القديمة. تبقى البيانات والتكاليف حتى انتهاء استخدام المازج والمفكك بغض النظر عن اكتمال التشغيل. IsAudioDeviceReady وIsSoundValid وIsMusicValid فحوص كلية. يقرأ GetMusicLooping بيانات المالك المحفوظة. يسمح بهذه العمليات في المعالجات والاستدعاءات الراجعة. تبقى ملاحظات التشغيل وSetMusicLooping مشروطة بسياق التطبيق. لا يستدعي المازج دالة مصدر ASPL.

إعطاء HTTP والرسم أدوارا صريحة

استورد core::http مع Raylib. يملك دليل HTTP وواجهته تصريحات الخدمة الكاملة. يعيد start النوع Session<C,S> بعد جاهزية المستمعين ولا يشغل معالجا. استدع progress خارج إطارات الرسم. ميزانيته الافتراضية 4096 تعليمة و2 ms نشطة وصفر ms انتظار. الأدوار محدودة ومتسلسلة، وقد يتجاوز عمل النظام أو المكتبة الأصلية active_ms. يستطيع المعالج المشغول التنازل عند ميزانية التعليمات مع استمرار التطبيق في الرسم.

قد يحافظ EndDrawing والإدخال المنتظر على النقل والمواعيد خارج الرسم دون تشغيل معالج مصدر. لا يحرك الإدخال داخل الإطار HTTP أو المعالجات. قد تنتهي مهلة طلب عميل HTTP حاجب في التطبيق نحو خادمه الصريح نفسه. رتب تقدما صريحا بالتواتر الذي يحتاجه التطبيق.

تستطيع مساعدات حالة الجلسة وإعداداتها في التطبيق العمل داخل إطار. تبقى مساعدات Context خاصة بالمعالج الحي. تنسخ القراءة الحالة، وتحفظ اللقطات هوية الجلسة والإصدار داخليا وتبقى قيمتها للقراءة فقط بعد الإغلاق. يستبدل النشر المشروط الحالة كلها ويزيد الإصدار. تعيد لقطة قديمة من الجلسة نفسها نجاحا بقيمة خطأ، وتعيد لقطة جلسة أخرى http.invalid_argument. لا يمنح مالك أو لقطة أو قيمة دالة محفوظة سلطة جهاز أو Context. تمنع عمليات الجهاز في المعالجات عبر كل الاستدعاءات. يسمح بالحساب النقي والنص على المعالج والفحوص الكلية وبيانات المالك للقراءة فقط.

يبدأ stop_session التصريف. واصل التقدم حتى SESSION_CLOSED. يسحب close_session الخدمة فوريا دون تشغيل معالجات التصريف. ينجح تكرار الإيقاف والإغلاق الطبيعيين. تعيد مساعدات الحالة المغلقة http.closed_session، والإطار أو السياق الخاطئ http.invalid_order أو http.invalid_context. تبقى إخفاقات المضيف المسجلة بعد التحرير الآمن.

تقدم عائلة HTTP والإطارات المتزامنة البرامج العربية والإنجليزية والمختلطة الأصلية. جهز الطرف العلوي والعملاء المحليين الموصوفين هناك. يتحرك المربع مع تقاسم /busy و/wait و/fast الأدوار. يتيح تأخير الطرف العلوي تقادم اللقطة. راجع نشر HTTP لمتطلبات TLS والثقة.

حفظ الأسماء المكافئة وهوية المستخدم والنصوص

تسمي الأسماء المكافئة الموردة الأنواع والعمليات نفسها. تعد الصيغتان لحقل سجل مورد واحد تكرارا. تحتفظ سجلات المستخدم وحقولها بأسمائها المكتوبة. يختار تبديل اللغة التوثيق ولا يترجم المصدر. تحتفظ النصوص بالمحارف المفككة وبايتات NUL. النص الذي يشبه مسارا ليس قراءة ملف. تفرض عمليات النص والمسار والعنوان كل منها قواعد مدخلاتها.

تعمل عائلة الهوية والنصوص دون رسوم أو صوت أو طرف علوي. تستخدم القياس المشكل المضمن والأسماء المكافئة للسجلات والتعدادات والأعلام وميزانية تقدم HTTP النقية. يحتفظ استدعاء abs غير الآمن العادي من libc.so.6 بعقد توافق C. تطبع رسالة ثنائية اللغة لجدولة غير صالحة ومسار PNG نصيا ومحتوى مفككا وNUL. لا يلزم تنزيل PNG.

تتضمن رسائل أخطاء النص scalar_index=N المنطقي من الصفر وscalar=U+XXXX. يستخدم UTF-8 الأصلي المعطوب byte_offset=N. هذه تفاصيل رسائل وليست حقول نتيجة إضافية أو واجهة تحليل رسائل. تهرب الرسالة محارف التحكم غير المدعومة، ويحتفظ الإخراج العادي بالبايتات النصية.

الإنهاء وتحرير الموارد

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

الحدان الافتراضيان 256 MiB للآلة الافتراضية وحساب خلفية مشترك واحد قدره 128 MiB لـRaylib وHTTP. يحفظ الرفض قبل الدخول الأصلي الحالة، ويضمن الفشل بعد الآثار الأصلية تنظيف الموارد المملوكة دون تراجع عام. راجع الحدود والأخطاء.

عند توزيع برنامج ELF احتفظ بملفه المرافق .THIRD-PARTY-NOTICES والأصول والإشعارات المطلوبة. يعمل البرنامج الناتج دون المصدر أو مترجم ASPL لكنه يحتاج إلى متطلبات رسوم Linux الموثقة. يبقى مصدر الدليل الأصلي (يفتح في نافذة جديدة) تنزيلا مطابقا للمنشور.

توقف أول إشارة SIGINT/SIGTERM كود التطبيق نهائيا وتلغي الإدخال وطلبات التطبيق المنتظرة، وتصرف فقط معالجات HTTP المقبولة سابقا خارج الرسم. تسحب الإشارة الثانية التصريف المتبقي. لا تشغل المصائد والحدود والإلغاء الآخر معالجات تصريف. يستخدم تنظيف الموارد المتبقية موعدا واحدا t + max(R,H) تقيده نطاقات التنفيذ والعملية والجلسة السابقة، ولا تجدده المحاولات. R مهلة تنظيف Raylib. H مهلة الجلسة المتبقية، وإلا أقصى 1000 ms ومهل تنظيف العملاء المقبولين عندما يبقى عمل HTTP. لا تضيف الاستيرادات غير المستخدمة أو الترويسات المغلقة مهلة. تبقى حالات الانتهاء 5 للمصيدة و6 للحد و7 للإلغاء و8 لفشل المضيف، مع نسبة تنظيف منفصلة للنتيجة الأساسية السابقة.

النشر بمتطلبات المضيف الفعلية

تستهدف الأدوات والبرامج الناتجة Linux بمعمارية x86_64 وglibc 2.34 أو أحدث. هي ELF64 PIE بمفسر /lib64/ld-linux-x86-64.so.2 واعتمادين مباشرين libc.so.6 وlibm.so.6، مع RELRO وربط فوري ومكدس غير قابل للتنفيذ ودون RPATH/RUNPATH. تجلب مكتبات الرسوم والصوت المحملة ديناميكيا اعتمادياتها وصلاحياتها وبرامج تشغيلها. يحتاج النص على المعالج والمساعدون النقيون إلى قاعدة المعالج وglibc فقط، ولا يحصل الاستيراد وحده على شاشة أو جهاز صوت.

المسار مكتبات المضيف ومتطلباته
X11 أو XWayland libX11.so.6 وlibXxf86vm.so.1 وlibXi.so.6 وlibXrandr.so.2 وlibXcursor.so.1 وlibXinerama.so.1 وlibXrender.so.1 وlibXext.so.6. يجرب GLX أولا libGLX.so.0 ثم libGL.so.1. يلزم DISPLAY مصرح وOpenGL 3.3 core.
Wayland libwayland-client.so.0 وlibwayland-cursor.so.0 وlibwayland-egl.so.1 وlibxkbcommon.so.0 وlibEGL.so.1. يلزم compositor/subcompositor وxdg-shell وذاكرة مشتركة ولوحة مفاتيح ومؤشر ومخرجات قابلة للاستخدام وسمة مؤشر. يستخدم OpenGL 3.3 core لسطح المكتب دون libdecor. عند غياب إجراءات EGL GL يجرب libOpenGL.so.0 ثم libGL.so.1.
PulseAudio أو خدمة PipeWire المتوافقة libpulse.so.0 وخدمة تشغيل متاحة ونقطة صوت قابلة للاستخدام.
ALSA المباشر libasound.so.2 وجهاز تشغيل قابل للاستخدام ومصرح.

يستخدم تحميل المضيف بحث المحمل المعتاد بنطاق فوري ومحلي وفحص الرموز المطلوبة. لا تلزم روابط مكتبات التطوير. يتبع اختيار الشاشة تجهيز المضيف، ويجرب الصوت PulseAudio ثم ALSA. يوقف رفض المدخلات أو الموارد أو الإلغاء أو تعذر إثبات التنظيف المحاولات. يعرض فشل كل المرشحين بعد التحرير الآمن فئة المرشح الأخير والخلفيات المجربة. لا يستبدل مسار الرسوم أو الصوت النجاح بتشغيل دون جهاز.

تضمن الأدوات Raylib 6.0 وHarfBuzz 14.4.0 وICU 78.3 ببيانات Unicode 17.0.0 الكاملة وFreeType 2.14.3 والخطوط الافتراضية. لا يستدعي فحص التطبيق وبناؤه مترجم C أو مجمعا أو رابطا ولا يحصل على جهاز. لا يحتاج المتلقي إلى مشغل ASPL أو Raylib نظامي أو خطوط مضيف أو مصدر. تبقى ملفات PNG وWAV/OGG/MP3 والخطوط المخصصة خارجية عند استخدامها. احفظ مسارات مجلد العمل وتراخيصها.

بعد تنزيل عائلة النص المشكل وOGG وإشعاره في الشجرة المذكورة:

mkdir -p deploy/docs/examples/assets
aspl build -o deploy/shaped docs/examples/raylib/shaped-text-audio.ar.aspl
cp docs/examples/assets/raylib-tone.ogg docs/examples/assets/raylib-tone.NOTICE deploy/docs/examples/assets/
cd deploy
./shaped --aspl-diagnostic-language=ar

وزع <program>.THIRD-PARTY-NOTICES بجانب الملف التنفيذي مع إشعارات الأصول. لا يقرأ التشغيل الملف المرافق. ينشر البناء المرافق ذريّا أولا ثم الملف التنفيذي. يمنع فشل الإشعار نشر التنفيذي، ويحفظ فشل التنفيذي اللاحق الملف القديم ويبلغ عن الإشعار المنشور. يعيد اصطدام المصدر أو الوحدة output-is-source، وتطابق مساري التنفيذي والمرافق output-path-collision، وفشل الأمان أو الكتابة أو النشر host-operation-failed مع تفاصيل المرحلة والمسار والنتيجة الجزئية. لا ينشئ تشغيل المصدر مرافقا.

تختار شجرة الاستيراد كلها، بما فيها الاستيرادات غير المستخدمة والمتعدية، برنامجا مجهزا أساسيا أو HTTP أو Raylib أو مشتركا. لا تضيف مخرجات الأساسي أو HTTP وحدهما متطلبات Raylib أو الخطوط أو الجهاز. يجب أن تطابق سجلات البايتكود والفهرس والتجهيز الخاصة الأداة المختارة، وليست ABI عامة ثابتة. تحتفظ البرامج المستقلة الموزعة سابقا بهوياتها المضمنة. توفر خطوات التثبيت ومتطلبات النظام والتنزيلات ونشر HTTP الإجراءات المرتبطة. يحتفظ مصدر النشر الأصلي (يفتح في نافذة جديدة) ببايتاته المنشورة ونطاق أدلته.

raylib-window-input-ar · ASPL 0.7.0

المضيف الأصلي فقط

// Run with: aspl run docs/examples/raylib/window-input.mixed.aspl
// Type text, click or scroll to change color. Resize to print new dimensions.
// Escape requests close. The demo also stops after 180 frames.
استورد أساسي::رايليب;

دالة ابدأ_الرئيسية() -> ص64 {
    دع flags = رايليب::اضبط_أعلام_الإعداد(رايليب::علم_نافذة_قابلة_للتحجيم);
    دع pacing = رايليب::اضبط_معدل_الإطارات(60);
    إذا لا flags::نجاح أو لا pacing::نجاح { أرجع 1; }
    دع opened = رايليب::هيئ_نافذة(640, 360, "ASPL input / إدخال رايليب");
    إذا لا opened::نجاح { اطبع(opened::error::الرسالة); أرجع 2; }
    دع exit_key = رايليب::اضبط_مفتاح_الخروج(رايليب::مفتاح_هروب);
    إذا لا exit_key::نجاح { اطبع(exit_key::error::الرسالة); أرجع 3; }
    متغير frame: ص64 = 0;
    متغير color = رايليب::أزرق_سماوي;
    طالما frame < 180 {
        دع closing = رايليب::هل_يجب_إغلاق_النافذة();
        إذا لا closing::نجاح { اطبع(closing::error::الرسالة); أرجع 4; }
        إذا closing::قيمة { أرجع 0; }
        دع clicked = رايليب::هل_ضغط_زر_الفأرة(رايليب::زر_فأرة_أيسر);
        دع pressed = رايليب::هل_ضغط_المفتاح(رايليب::مفتاح_مسافة);
        دع wheel = رايليب::حركة_عجلة_الفأرة();
        إذا لا clicked::نجاح أو لا pressed::نجاح أو لا wheel::نجاح { أرجع 5; }
        إذا clicked::قيمة أو pressed::قيمة أو wheel::قيمة لا يطابق 0.0 { color = رايليب::عنابي; }
        دع typed = رايليب::المحرف_المدخل();
        دع key = رايليب::المفتاح_المضغوط();
        إذا لا typed::نجاح أو لا key::نجاح { أرجع 6; }
        إذا typed::قيمة لا يطابق 0 {
            color = رايليب::أخضر_داكن;
            اطبع("Unicode / محرف: "); اطبع(نسق_ص64(ص64(typed::قيمة))); اطبع("\n");
        }
        دع resized = رايليب::هل_تغير_حجم_النافذة();
        إذا لا resized::نجاح { أرجع 7; }
        إذا resized::قيمة أو frame يطابق 0 {
            دع width = رايليب::عرض_الشاشة(); دع height = رايليب::ارتفاع_الشاشة();
            دع render_width = رايليب::عرض_التصيير(); دع render_height = رايليب::ارتفاع_التصيير();
            إذا لا width::نجاح أو لا height::نجاح أو لا render_width::نجاح أو لا render_height::نجاح { أرجع 8; }
            اطبع("Screen / شاشة: "); اطبع(نسق_ص64(ص64(width::قيمة))); اطبع("x"); اطبع(نسق_ص64(ص64(height::قيمة)));
            اطبع(" render="); اطبع(نسق_ص64(ص64(render_width::قيمة))); اطبع("x"); اطبع(نسق_ص64(ص64(render_height::قيمة))); اطبع("\n");
        }
        دع begun = رايليب::ابدأ_الرسم();
        إذا لا begun::نجاح { اطبع(begun::error::الرسالة); أرجع 9; }
        // Sampled observations also work in an open drawing frame.
        دع position = رايليب::موضع_الفأرة(); دع delta = رايليب::تغير_موضع_الفأرة();
        إذا لا position::نجاح أو لا delta::نجاح { أرجع 10; }
        دع cleared = رايليب::امسح_الخلفية(color);
        إذا لا cleared::نجاح { اطبع(cleared::error::الرسالة); أرجع 11; }
        دع ended = رايليب::أنه_الرسم();
        إذا لا ended::نجاح { اطبع(ended::error::الرسالة); أرجع 12; }
        frame = frame + 1;
    }
    دع closed = رايليب::أغلق_النافذة();
    إذا لا closed::نجاح { اطبع(closed::error::الرسالة); أرجع 13; }
    أرجع 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout undefined
نزّل المصدر
aspl check raylib-window-input-ar.aspl
aspl run raylib-window-input-ar.aspl
raylib-window-input-en · ASPL 0.7.0

المضيف الأصلي فقط

// Run with: aspl run docs/examples/raylib/window-input.mixed.aspl
// Type text, click or scroll to change color. Resize to print new dimensions.
// Escape requests close. The demo also stops after 180 frames.
import core::raylib;

fn start_main() -> i64 {
    let flags = raylib::SetConfigFlags(raylib::FLAG_WINDOW_RESIZABLE);
    let pacing = raylib::SetTargetFPS(60);
    if not flags::ok or not pacing::ok { return 1; }
    let opened = raylib::InitWindow(640, 360, "ASPL input / إدخال رايليب");
    if not opened::ok { print(opened::error::message); return 2; }
    let exit_key = raylib::SetExitKey(raylib::KEY_ESCAPE);
    if not exit_key::ok { print(exit_key::error::message); return 3; }
    var frame: i64 = 0;
    var color = raylib::SKYBLUE;
    while frame < 180 {
        let closing = raylib::WindowShouldClose();
        if not closing::ok { print(closing::error::message); return 4; }
        if closing::value { return 0; }
        let clicked = raylib::IsMouseButtonPressed(raylib::MOUSE_BUTTON_LEFT);
        let pressed = raylib::IsKeyPressed(raylib::KEY_SPACE);
        let wheel = raylib::GetMouseWheelMove();
        if not clicked::ok or not pressed::ok or not wheel::ok { return 5; }
        if clicked::value or pressed::value or wheel::value not matches 0.0 { color = raylib::MAROON; }
        let typed = raylib::GetCharPressed();
        let key = raylib::GetKeyPressed();
        if not typed::ok or not key::ok { return 6; }
        if typed::value not matches 0 {
            color = raylib::DARKGREEN;
            print("Unicode / محرف: "); print(format_i64(i64(typed::value))); print("\n");
        }
        let resized = raylib::IsWindowResized();
        if not resized::ok { return 7; }
        if resized::value or frame matches 0 {
            let width = raylib::GetScreenWidth(); let height = raylib::GetScreenHeight();
            let render_width = raylib::GetRenderWidth(); let render_height = raylib::GetRenderHeight();
            if not width::ok or not height::ok or not render_width::ok or not render_height::ok { return 8; }
            print("Screen / شاشة: "); print(format_i64(i64(width::value))); print("x"); print(format_i64(i64(height::value)));
            print(" render="); print(format_i64(i64(render_width::value))); print("x"); print(format_i64(i64(render_height::value))); print("\n");
        }
        let begun = raylib::BeginDrawing();
        if not begun::ok { print(begun::error::message); return 9; }
        // Sampled observations also work in an open drawing frame.
        let position = raylib::GetMousePosition(); let delta = raylib::GetMouseDelta();
        if not position::ok or not delta::ok { return 10; }
        let cleared = raylib::ClearBackground(color);
        if not cleared::ok { print(cleared::error::message); return 11; }
        let ended = raylib::EndDrawing();
        if not ended::ok { print(ended::error::message); return 12; }
        frame = frame + 1;
    }
    let closed = raylib::CloseWindow();
    if not closed::ok { print(closed::error::message); return 13; }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout undefined
نزّل المصدر
aspl check raylib-window-input-en.aspl
aspl run raylib-window-input-en.aspl
raylib-window-input-mixed · ASPL 0.7.0

المضيف الأصلي فقط

// Run with: aspl run docs/examples/raylib/window-input.mixed.aspl
// Type text, click or scroll to change color. Resize to print new dimensions.
// Escape requests close. The demo also stops after 180 frames.
import core::raylib;
استورد أساسي::رايليب.

fn start_main() -> i64 {
    let flags = raylib::SetConfigFlags(رايليب::FLAG_WINDOW_RESIZABLE);
    let pacing = رايليب::اضبط_معدل_الإطارات(60);
    if not flags::ok or not pacing::ok { return 1; }
    let opened = رايليب::هيئ_نافذة(640, 360, "ASPL input / إدخال رايليب");
    if not opened::ok { print(opened::error::message); return 2; }
    let exit_key = raylib::اضبط_مفتاح_الخروج(رايليب::KEY_ESCAPE);
    if not exit_key::ok { print(exit_key::error::message); return 3; }
    var frame: i64 = 0;
    var color = raylib::SKYBLUE;
    while frame < 180 {
        let closing = raylib::هل_يجب_إغلاق_النافذة();
        if not closing::ok { print(closing::error::message); return 4; }
        if closing::value { return 0; }
        let clicked = رايليب::IsMouseButtonPressed(raylib::MOUSE_BUTTON_LEFT);
        let pressed = raylib::هل_ضغط_المفتاح(رايليب::KEY_SPACE);
        let wheel = raylib::حركة_عجلة_الفأرة();
        if not clicked::ok or not pressed::ok or not wheel::ok { return 5; }
        if clicked::value or pressed::value or wheel::value not matches 0.0 { color = raylib::MAROON; }
        let typed = رايليب::المحرف_المدخل();
        let key = raylib::GetKeyPressed();
        if not typed::ok or not key::ok { return 6; }
        if typed::value not matches 0 {
            color = رايليب::DARKGREEN;
            print("Unicode / محرف: "); print(format_i64(i64(typed::value))); print("\n");
        }
        let resized = raylib::هل_تغير_حجم_النافذة();
        if not resized::ok { return 7; }
        if resized::value or frame matches 0 {
            let width = رايليب::عرض_الشاشة(); let height = raylib::GetScreenHeight();
            let render_width = raylib::عرض_التصيير(); let render_height = رايليب::GetRenderHeight();
            if not width::ok or not height::ok or not render_width::ok or not render_height::ok { return 8; }
            print("Screen / شاشة: "); print(format_i64(i64(width::value))); print("x"); print(format_i64(i64(height::value)));
            print(" render="); print(format_i64(i64(render_width::value))); print("x"); print(format_i64(i64(render_height::value))); print("\n");
        }
        let begun = raylib::ابدأ_الرسم();
        if not begun::ok { print(begun::error::message); return 9; }
        // Sampled observations also work in an open drawing frame.
        let position = رايليب::موضع_الفأرة(); let delta = raylib::GetMouseDelta();
        if not position::ok or not delta::ok { return 10; }
        let cleared = raylib::امسح_الخلفية(color);
        if not cleared::ok { print(cleared::error::message); return 11; }
        let ended = رايليب::EndDrawing();
        if not ended::ok { print(ended::error::message); return 12; }
        frame = frame + 1;
    }
    let closed = raylib::أغلق_النافذة();
    if not closed::ok { print(closed::error::message); return 13; }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout undefined
نزّل المصدر
aspl check raylib-window-input-mixed.aspl
aspl run raylib-window-input-mixed.aspl
raylib-sprite-camera-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد أساسي::رايليب;

دالة ابدأ_الرئيسية() -> ص64 {
    دع opened = رايليب::هيئ_نافذة(480, 300, "PNG sprites / صور متحركة");
    إذا لا opened::نجاح { اطبع(opened::error::الرسالة); أرجع 1; }
    دع loaded = رايليب::حمل_نسيجا("docs/examples/assets/raylib-sprites.png");
    إذا لا loaded::نجاح { اطبع(loaded::error::الرسالة); أرجع 2; }
    دع texture = loaded::قيمة;
    دع alias = texture;
    إذا رايليب::عرض_النسيج(texture)::قيمة لا يطابق 32 أو رايليب::ارتفاع_النسيج(texture)::قيمة لا يطابق 16 { أرجع 3; }
    دع filter = رايليب::اضبط_مرشح_النسيج(texture, رايليب::مرشح_نسيج_نقطي);
    دع wrap = رايليب::اضبط_التفاف_النسيج(texture, رايليب::التفاف_نسيج_تثبيت);
    دع pacing = رايليب::اضبط_معدل_الإطارات(60);
    إذا لا filter::نجاح أو لا wrap::نجاح أو لا pacing::نجاح { أرجع 4; }
    دع camera = رايليب::كاميرا2 {
        إزاحة: رايليب::متجه2 { س: 15.0, ص: 10.0 }, هدف: رايليب::متجه2 { س: 0.0, ص: 0.0 },
        دوران: 0.0, تكبير: 1.0
    };
    دع first = رايليب::مستطيل { س: 24.0, ص: 24.0, عرض: 32.0, ارتفاع: 16.0 };
    دع second = رايليب::مستطيل { س: 30.0, ص: 28.0, عرض: 32.0, ارتفاع: 16.0 };
    دع collision = رايليب::هل_يتداخل_مستطيلان(first, second);
    دع overlap = رايليب::مستطيل_التداخل(first, second);
    إذا لا collision::نجاح أو لا overlap::نجاح { أرجع 16; }
    إذا لا collision::قيمة { أرجع 17; }
    متغير frame: ص32 = 0;
    طالما frame < 20 {
        إذا لا رايليب::ابدأ_الرسم()::نجاح أو لا رايليب::امسح_الخلفية(رايليب::أبيض_رايليب)::نجاح { أرجع 5; }
        إذا لا رايليب::ابدأ_وضع_ثنائي_الأبعاد(camera)::نجاح { أرجع 6; }
        إذا لا رايليب::ارسم_نسيجا(texture, 24, 24, رايليب::أبيض)::نجاح { أرجع 7; }
        إذا لا رايليب::ارسم_نسيجا_بمتجه(texture, رايليب::متجه2 { س: 100.0, ص: 24.0 }, رايليب::أزرق_سماوي)::نجاح { أرجع 8; }
        إذا لا رايليب::ارسم_نسيجا_موسعا(texture, رايليب::متجه2 { س: 40.0, ص: 110.0 }, -10.0, 4.0, رايليب::أبيض)::نجاح { أرجع 9; }
        إذا لا رايليب::ارسم_جزء_نسيج(texture, رايليب::مستطيل { س: 16.0, ص: 0.0, عرض: -16.0, ارتفاع: 16.0 },
            رايليب::متجه2 { س: 250.0, ص: 24.0 }, رايليب::أبيض)::نجاح { أرجع 10; }
        إذا لا رايليب::ارسم_نسيجا_متقدما(texture, رايليب::مستطيل { س: 16.0, ص: 0.0, عرض: 16.0, ارتفاع: -16.0 },
            رايليب::مستطيل { س: 330.0, ص: 160.0, عرض: -96.0, ارتفاع: 96.0 },
            رايليب::متجه2 { س: 48.0, ص: 48.0 }, 25.0, رايليب::لون { أحمر: 255, أخضر: 255, أزرق: 255, ألفا: 210 })::نجاح { أرجع 11; }
        إذا لا رايليب::ارسم_محيط_مستطيل_موسعا(overlap::قيمة, 1.0, رايليب::أحمر)::نجاح { أرجع 18; }
        إذا لا رايليب::أنه_وضع_ثنائي_الأبعاد()::نجاح { أرجع 12; }
        إذا frame يطابق 19 {
            إذا لا رايليب::حرر_النسيج(alias)::نجاح أو رايليب::هل_النسيج_صالح(texture) { أرجع 13; }
        }
        إذا لا رايليب::أنه_الرسم()::نجاح { أرجع 14; }
        frame = frame + 1;
    }
    إذا لا رايليب::حرر_النسيج(texture)::نجاح أو لا رايليب::أغلق_النافذة()::نجاح { أرجع 15; }
    اطبع("texture sprites complete");
    أرجع 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "texture sprites complete"
نزّل المصدر
aspl check raylib-sprite-camera-ar.aspl
aspl run raylib-sprite-camera-ar.aspl
raylib-sprite-camera-en · ASPL 0.7.0

المضيف الأصلي فقط

import core::raylib;

fn start_main() -> i64 {
    let opened = raylib::InitWindow(480, 300, "PNG sprites / صور متحركة");
    if not opened::ok { print(opened::error::message); return 1; }
    let loaded = raylib::LoadTexture("docs/examples/assets/raylib-sprites.png");
    if not loaded::ok { print(loaded::error::message); return 2; }
    let texture = loaded::value;
    let alias = texture;
    if raylib::GetTextureWidth(texture)::value not matches 32 or raylib::GetTextureHeight(texture)::value not matches 16 { return 3; }
    let filter = raylib::SetTextureFilter(texture, raylib::TEXTURE_FILTER_POINT);
    let wrap = raylib::SetTextureWrap(texture, raylib::TEXTURE_WRAP_CLAMP);
    let pacing = raylib::SetTargetFPS(60);
    if not filter::ok or not wrap::ok or not pacing::ok { return 4; }
    let camera = raylib::Camera2D {
        offset: raylib::Vector2 { x: 15.0, y: 10.0 }, target: raylib::Vector2 { x: 0.0, y: 0.0 },
        rotation: 0.0, zoom: 1.0
    };
    let first = raylib::Rectangle { x: 24.0, y: 24.0, width: 32.0, height: 16.0 };
    let second = raylib::Rectangle { x: 30.0, y: 28.0, width: 32.0, height: 16.0 };
    let collision = raylib::CheckCollisionRecs(first, second);
    let overlap = raylib::GetCollisionRec(first, second);
    if not collision::ok or not overlap::ok { return 16; }
    if not collision::value { return 17; }
    var frame: i32 = 0;
    while frame < 20 {
        if not raylib::BeginDrawing()::ok or not raylib::ClearBackground(raylib::RAYWHITE)::ok { return 5; }
        if not raylib::BeginMode2D(camera)::ok { return 6; }
        if not raylib::DrawTexture(texture, 24, 24, raylib::WHITE)::ok { return 7; }
        if not raylib::DrawTextureV(texture, raylib::Vector2 { x: 100.0, y: 24.0 }, raylib::SKYBLUE)::ok { return 8; }
        if not raylib::DrawTextureEx(texture, raylib::Vector2 { x: 40.0, y: 110.0 }, -10.0, 4.0, raylib::WHITE)::ok { return 9; }
        if not raylib::DrawTextureRec(texture, raylib::Rectangle { x: 16.0, y: 0.0, width: -16.0, height: 16.0 },
            raylib::Vector2 { x: 250.0, y: 24.0 }, raylib::WHITE)::ok { return 10; }
        if not raylib::DrawTexturePro(texture, raylib::Rectangle { x: 16.0, y: 0.0, width: 16.0, height: -16.0 },
            raylib::Rectangle { x: 330.0, y: 160.0, width: -96.0, height: 96.0 },
            raylib::Vector2 { x: 48.0, y: 48.0 }, 25.0, raylib::Color { r: 255, g: 255, b: 255, a: 210 })::ok { return 11; }
        if not raylib::DrawRectangleLinesEx(overlap::value, 1.0, raylib::RED)::ok { return 18; }
        if not raylib::EndMode2D()::ok { return 12; }
        if frame matches 19 {
            if not raylib::UnloadTexture(alias)::ok or raylib::IsTextureValid(texture) { return 13; }
        }
        if not raylib::EndDrawing()::ok { return 14; }
        frame = frame + 1;
    }
    if not raylib::UnloadTexture(texture)::ok or not raylib::CloseWindow()::ok { return 15; }
    print("texture sprites complete");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "texture sprites complete"
نزّل المصدر
aspl check raylib-sprite-camera-en.aspl
aspl run raylib-sprite-camera-en.aspl
raylib-sprite-camera-mixed · ASPL 0.7.0

المضيف الأصلي فقط

import core::raylib;
استورد أساسي::رايليب.

fn start_main() -> i64 {
    let opened = raylib::InitWindow(480, 300, "PNG sprites / صور متحركة");
    if not opened::ok { print(opened::error::message); return 1; }
    let loaded = رايليب::حمل_نسيجا("docs/examples/assets/raylib-sprites.png");
    if not loaded::ok { print(loaded::error::message); return 2; }
    let texture = loaded::value;
    let alias = texture;
    if raylib::GetTextureWidth(texture)::value not matches 32 or رايليب::ارتفاع_النسيج(texture)::value not matches 16 { return 3; }
    let filter = raylib::SetTextureFilter(texture, raylib::TEXTURE_FILTER_POINT);
    let wrap = raylib::SetTextureWrap(texture, raylib::TEXTURE_WRAP_CLAMP);
    let pacing = raylib::SetTargetFPS(60);
    if not filter::ok or not wrap::ok or not pacing::ok { return 4; }
    let camera = raylib::Camera2D {
        offset: raylib::Vector2 { x: 15.0, y: 10.0 }, target: raylib::Vector2 { x: 0.0, y: 0.0 },
        rotation: 0.0, zoom: 1.0
    };
    let first = raylib::Rectangle { x: 24.0, y: 24.0, width: 32.0, height: 16.0 };
    let second = raylib::Rectangle { x: 30.0, y: 28.0, width: 32.0, height: 16.0 };
    let collision = raylib::CheckCollisionRecs(first, second);
    let overlap = رايليب::مستطيل_التداخل(first, second);
    if not collision::ok or not overlap::ok { return 16; }
    if not collision::value { return 17; }
    var frame: i32 = 0;
    while frame < 20 {
        if not raylib::BeginDrawing()::ok or not raylib::ClearBackground(raylib::RAYWHITE)::ok { return 5; }
        if not raylib::BeginMode2D(camera)::ok { return 6; }
        if not raylib::DrawTexture(texture, 24, 24, raylib::WHITE)::ok { return 7; }
        if not raylib::DrawTextureV(texture, raylib::Vector2 { x: 100.0, y: 24.0 }, raylib::SKYBLUE)::ok { return 8; }
        if not raylib::DrawTextureEx(texture, raylib::Vector2 { x: 40.0, y: 110.0 }, -10.0, 4.0, raylib::WHITE)::ok { return 9; }
        if not raylib::DrawTextureRec(texture, raylib::Rectangle { x: 16.0, y: 0.0, width: -16.0, height: 16.0 },
            raylib::Vector2 { x: 250.0, y: 24.0 }, raylib::WHITE)::ok { return 10; }
        if not raylib::DrawTexturePro(texture, raylib::Rectangle { x: 16.0, y: 0.0, width: 16.0, height: -16.0 },
            raylib::Rectangle { x: 330.0, y: 160.0, width: -96.0, height: 96.0 },
            raylib::Vector2 { x: 48.0, y: 48.0 }, 25.0, raylib::Color { r: 255, g: 255, b: 255, a: 210 })::ok { return 11; }
        if not raylib::DrawRectangleLinesEx(overlap::value, 1.0, raylib::RED)::ok { return 18; }
        if not raylib::EndMode2D()::ok { return 12; }
        if frame matches 19 {
            if not raylib::UnloadTexture(alias)::ok or raylib::IsTextureValid(texture) { return 13; }
        }
        if not raylib::EndDrawing()::ok { return 14; }
        frame = frame + 1;
    }
    if not raylib::UnloadTexture(texture)::ok or not raylib::CloseWindow()::ok { return 15; }
    print("texture sprites complete");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "texture sprites complete"
نزّل المصدر
aspl check raylib-sprite-camera-mixed.aspl
aspl run raylib-sprite-camera-mixed.aspl
raylib-shaped-text-audio-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد أساسي::رايليب;

دالة ابدأ_الرئيسية() -> ص64 {
    // Layout and measurement need no display. Text stays in logical order.
    دع loaded_font = رايليب::الخط_الافتراضي();
    إذا لا loaded_font::نجاح { اطبع(loaded_font::error::الرسالة); أرجع 1; }
    دع options = رايليب::خيارات_النص {
        حجم_الخط: 32.0, اتجاه: رايليب::اتجاه_نص_تلقائي,
        له_عرض: صواب, عرض: 430.0, محاذاة: رايليب::محاذاة_نص_بداية,
        تباعد_الأسطر: 4.0
    };
    دع prepared = رايليب::أنشئ_تخطيط_نص(loaded_font::قيمة, "سلام ASPL 123\nبَِّ Hello", options);
    إذا لا prepared::نجاح { اطبع(prepared::error::الرسالة); أرجع 2; }
    دع layout = prepared::قيمة;
    دع measured = رايليب::قس_تخطيط_النص(layout);
    إذا لا measured::نجاح { اطبع(measured::error::الرسالة); أرجع 3; }
    دع audio = رايليب::هيئ_جهاز_الصوت();
    إذا لا audio::نجاح { اطبع(audio::error::الرسالة); أرجع 4; }
    دع loaded_music = رايليب::حمل_تدفق_موسيقى("docs/examples/assets/raylib-tone.ogg");
    إذا لا loaded_music::نجاح { اطبع(loaded_music::error::الرسالة); أرجع 5; }
    دع music = loaded_music::قيمة;
    إذا لا رايليب::اضبط_تكرار_الموسيقى(music, صواب)::نجاح أو لا رايليب::شغل_تدفق_الموسيقى(music)::نجاح { أرجع 6; }
    دع opened = رايليب::هيئ_نافذة(500, 300, "Shaped text / نص مشكل");
    إذا لا opened::نجاح { اطبع(opened::error::الرسالة); أرجع 7; }
    إذا لا رايليب::اضبط_معدل_الإطارات(60)::نجاح { أرجع 8; }
    متغير frame: ص32 = 0;
    طالما frame < 60 {
        دع closing = رايليب::هل_يجب_إغلاق_النافذة();
        إذا لا closing::نجاح { أرجع 9; }
        إذا closing::قيمة { أرجع 0; }
        // Streaming advances only when the application calls UpdateMusicStream.
        إذا لا رايليب::حدث_تدفق_الموسيقى(music)::نجاح { أرجع 10; }
        إذا لا رايليب::ابدأ_الرسم()::نجاح أو لا رايليب::امسح_الخلفية(رايليب::أبيض_رايليب)::نجاح { أرجع 11; }
        دع size = measured::value::حجم;
        دع ink = measured::value::حبر;
        دع box = رايليب::مستطيل { س: 30.0, ص: 30.0, عرض: size::س, ارتفاع: size::ص };
        إذا لا رايليب::ارسم_محيط_مستطيل_موسعا(box, 1.0, رايليب::رمادي)::نجاح { أرجع 12; }
        دع ink_box = رايليب::مستطيل { س: 30.0 + ink::س, ص: 30.0 + ink::ص, عرض: ink::عرض, ارتفاع: ink::ارتفاع };
        إذا لا رايليب::ارسم_محيط_مستطيل_موسعا(ink_box, 1.0, رايليب::أحمر)::نجاح { أرجع 13; }
        إذا لا رايليب::ارسم_تخطيط_النص(layout, رايليب::متجه2 { س: 30.0, ص: 30.0 }, رايليب::أسود)::نجاح { أرجع 14; }
        إذا لا رايليب::أنه_الرسم()::نجاح { أرجع 15; }
        frame = frame + 1;
    }
    إذا لا رايليب::حرر_تدفق_الموسيقى(music)::نجاح أو لا رايليب::أغلق_جهاز_الصوت()::نجاح { أرجع 16; }
    إذا لا رايليب::أغلق_النافذة()::نجاح أو لا رايليب::حرر_تخطيط_النص(layout)::نجاح { أرجع 17; }
    اطبع("shaped text and explicit music updates complete\n");
    أرجع 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout undefined
نزّل المصدر
aspl check raylib-shaped-text-audio-ar.aspl
aspl run raylib-shaped-text-audio-ar.aspl
raylib-shaped-text-audio-en · ASPL 0.7.0

المضيف الأصلي فقط

import core::raylib;

fn start_main() -> i64 {
    // Layout and measurement need no display. Text stays in logical order.
    let loaded_font = raylib::GetFontDefault();
    if not loaded_font::ok { print(loaded_font::error::message); return 1; }
    let options = raylib::TextOptions {
        font_size: 32.0, direction: raylib::TEXT_DIRECTION_AUTO,
        has_width: true, width: 430.0, alignment: raylib::TEXT_ALIGNMENT_START,
        line_spacing: 4.0
    };
    let prepared = raylib::CreateTextLayout(loaded_font::value, "سلام ASPL 123\nبَِّ Hello", options);
    if not prepared::ok { print(prepared::error::message); return 2; }
    let layout = prepared::value;
    let measured = raylib::MeasureTextLayout(layout);
    if not measured::ok { print(measured::error::message); return 3; }
    let audio = raylib::InitAudioDevice();
    if not audio::ok { print(audio::error::message); return 4; }
    let loaded_music = raylib::LoadMusicStream("docs/examples/assets/raylib-tone.ogg");
    if not loaded_music::ok { print(loaded_music::error::message); return 5; }
    let music = loaded_music::value;
    if not raylib::SetMusicLooping(music, true)::ok or not raylib::PlayMusicStream(music)::ok { return 6; }
    let opened = raylib::InitWindow(500, 300, "Shaped text / نص مشكل");
    if not opened::ok { print(opened::error::message); return 7; }
    if not raylib::SetTargetFPS(60)::ok { return 8; }
    var frame: i32 = 0;
    while frame < 60 {
        let closing = raylib::WindowShouldClose();
        if not closing::ok { return 9; }
        if closing::value { return 0; }
        // Streaming advances only when the application calls UpdateMusicStream.
        if not raylib::UpdateMusicStream(music)::ok { return 10; }
        if not raylib::BeginDrawing()::ok or not raylib::ClearBackground(raylib::RAYWHITE)::ok { return 11; }
        let size = measured::value::size;
        let ink = measured::value::ink;
        let box = raylib::Rectangle { x: 30.0, y: 30.0, width: size::x, height: size::y };
        if not raylib::DrawRectangleLinesEx(box, 1.0, raylib::GRAY)::ok { return 12; }
        let ink_box = raylib::Rectangle { x: 30.0 + ink::x, y: 30.0 + ink::y, width: ink::width, height: ink::height };
        if not raylib::DrawRectangleLinesEx(ink_box, 1.0, raylib::RED)::ok { return 13; }
        if not raylib::DrawTextLayout(layout, raylib::Vector2 { x: 30.0, y: 30.0 }, raylib::BLACK)::ok { return 14; }
        if not raylib::EndDrawing()::ok { return 15; }
        frame = frame + 1;
    }
    if not raylib::UnloadMusicStream(music)::ok or not raylib::CloseAudioDevice()::ok { return 16; }
    if not raylib::CloseWindow()::ok or not raylib::UnloadTextLayout(layout)::ok { return 17; }
    print("shaped text and explicit music updates complete\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout undefined
نزّل المصدر
aspl check raylib-shaped-text-audio-en.aspl
aspl run raylib-shaped-text-audio-en.aspl
raylib-shaped-text-audio-mixed · ASPL 0.7.0

المضيف الأصلي فقط

import core::raylib;
استورد أساسي::رايليب.

fn start_main() -> i64 {
    // Layout and measurement need no display. Text stays in logical order.
    let loaded_font = raylib::GetFontDefault();
    if not loaded_font::ok { print(loaded_font::error::message); return 1; }
    let options = raylib::TextOptions {
        font_size: 32.0, direction: raylib::TEXT_DIRECTION_AUTO,
        has_width: true, width: 430.0, alignment: raylib::TEXT_ALIGNMENT_START,
        line_spacing: 4.0
    };
    let prepared = رايليب::أنشئ_تخطيط_نص(loaded_font::value, "سلام ASPL 123\nبَِّ Hello", options);
    if not prepared::ok { print(prepared::error::message); return 2; }
    let layout = prepared::value;
    let measured = raylib::MeasureTextLayout(layout);
    if not measured::ok { print(measured::error::message); return 3; }
    let audio = رايليب::هيئ_جهاز_الصوت();
    if not audio::ok { print(audio::error::message); return 4; }
    let loaded_music = raylib::LoadMusicStream("docs/examples/assets/raylib-tone.ogg");
    if not loaded_music::ok { print(loaded_music::error::message); return 5; }
    let music = loaded_music::value;
    if not raylib::SetMusicLooping(music, true)::ok or not raylib::PlayMusicStream(music)::ok { return 6; }
    let opened = raylib::InitWindow(500, 300, "Shaped text / نص مشكل");
    if not opened::ok { print(opened::error::message); return 7; }
    if not raylib::SetTargetFPS(60)::ok { return 8; }
    var frame: i32 = 0;
    while frame < 60 {
        let closing = raylib::WindowShouldClose();
        if not closing::ok { return 9; }
        if closing::value { return 0; }
        // Streaming advances only when the application calls UpdateMusicStream.
        if not raylib::UpdateMusicStream(music)::ok { return 10; }
        if not raylib::BeginDrawing()::ok or not raylib::ClearBackground(raylib::RAYWHITE)::ok { return 11; }
        let size = measured::value::size;
        let ink = measured::value::ink;
        let box = raylib::Rectangle { x: 30.0, y: 30.0, width: size::x, height: size::y };
        if not raylib::DrawRectangleLinesEx(box, 1.0, raylib::GRAY)::ok { return 12; }
        let ink_box = raylib::Rectangle { x: 30.0 + ink::x, y: 30.0 + ink::y, width: ink::width, height: ink::height };
        if not raylib::DrawRectangleLinesEx(ink_box, 1.0, raylib::RED)::ok { return 13; }
        if not رايليب::ارسم_تخطيط_النص(layout, raylib::Vector2 { x: 30.0, y: 30.0 }, raylib::BLACK)::ok { return 14; }
        if not raylib::EndDrawing()::ok { return 15; }
        frame = frame + 1;
    }
    if not raylib::UnloadMusicStream(music)::ok or not raylib::CloseAudioDevice()::ok { return 16; }
    if not raylib::CloseWindow()::ok or not raylib::UnloadTextLayout(layout)::ok { return 17; }
    print("shaped text and explicit music updates complete\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout undefined
نزّل المصدر
aspl check raylib-shaped-text-audio-mixed.aspl
aspl run raylib-shaped-text-audio-mixed.aspl
raylib-concurrent-http-ar · ASPL 0.7.0

المضيف الأصلي فقط

// Run an upstream HTTP server on 127.0.0.1:8001, then request /busy, /wait and
// /fast on port 8000. The window keeps drawing while the handlers share turns.
استورد أساسي::رايليب;
استورد أساسي::ويب;

سجل State { frames: ص64, busy: منطقي, fast: منطقي, conflict: منطقي }

دالة outbound(ctx: ويب::سياق<نص,State>, saved: ص64) -> ويب::استجابة_خادم {
    دع snapshot = ويب::التقط_الحالة(ctx);
    دع request = ويب::أنشئ_طلب("GET", ويب::اقرأ_إعدادات(ctx))::قيمة;
    دع reply = ويب::اطلب(request, ويب::خيارات_طلب());
    إذا لا reply::نجاح {
        أرجع ويب::استجابة_نصية(502, reply::error::الرمز, "text/plain")::قيمة;
    }
    إذا saved لا يطابق 7 { أرجع ويب::أنشئ_استجابة(500, [])::قيمة; }
    دع published = ويب::استبدل_الحالة_إن_كانت_حالية(ctx, snapshot, snapshot::قيمة)::قيمة;
    متغير current = ويب::اقرأ_حالة(ctx);
    current::conflict = لا published;
    ويب::استبدل_حالة(ctx, current);
    أرجع ويب::استجابة_نصية(200, "conflict", "text/plain")::قيمة;
}

دالة handler(req: ويب::طلب_وارد, ctx: ويب::سياق<نص,State>) -> ويب::استجابة_خادم {
    إذا req::مسار يطابق "/busy" {
        متغير state = ويب::اقرأ_حالة(ctx);
        state::busy = صواب;
        ويب::استبدل_حالة(ctx, state);
        طالما صواب {}
    }
    إذا req::مسار يطابق "/wait" { أرجع outbound(ctx, 7); }
    متغير current = ويب::اقرأ_حالة(ctx);
    current::fast = رايليب::هل_النافذة_جاهزة();
    ويب::استبدل_حالة(ctx, current);
    أرجع ويب::استجابة_نصية(200, "fast", "text/plain")::قيمة;
}

دالة ابدأ_الرئيسية() -> ص64 {
    دع opened = رايليب::هيئ_نافذة(480, 240, "ASPL HTTP and drawing");
    إذا لا opened::نجاح { اطبع(opened::error::الرمز); أرجع 1; }
    دع pacing = رايليب::اضبط_معدل_الإطارات(60);
    إذا لا pacing::نجاح { أرجع 9; }
    متغير server = ويب::إعدادات_خدمة();
    server::مستمعون = [ويب::أنشئ_مستمع("127.0.0.1", 8000)::قيمة];
    دع routes = ويب::أنشئ_موجه([
        ويب::أنشئ_وجهة("GET", "/busy", handler)::قيمة,
        ويب::أنشئ_وجهة("GET", "/wait", handler)::قيمة,
        ويب::أنشئ_وجهة("GET", "/fast", handler)::قيمة
    ])::قيمة;
    دع started = ويب::ابدأ(server, routes, "http://127.0.0.1:8001/",
        State {frames: 0, busy: خطأ, fast: خطأ, conflict: خطأ});
    إذا لا started::نجاح { اطبع(started::error::الرمز); أرجع 2; }
    دع owner = started::قيمة;
    اطبع("ready\n");
    متغير budget = ويب::ميزانية_التقدم();
    budget::حد_التعليمات = 128;
    متغير frames: ص32 = 0;
    طالما frames < 180 و لا رايليب::هل_يجب_إغلاق_النافذة()::قيمة {
        إذا لا ويب::تقدم(owner, budget)::نجاح { أرجع 3; }
        إذا لا رايليب::ابدأ_الرسم()::نجاح { أرجع 4; }
        إذا لا رايليب::امسح_الخلفية(رايليب::أبيض_رايليب)::نجاح { أرجع 10; }
        متغير state = ويب::التقط_حالة_الجلسة(owner)::value::قيمة;
        state::frames = state::frames + 1;
        إذا لا ويب::استبدل_حالة_الجلسة(owner, state)::نجاح { أرجع 5; }
        إذا لا رايليب::ارسم_مستطيلا(frames, 90, 40, 40, رايليب::أزرق)::نجاح { أرجع 11; }
        إذا لا رايليب::أنه_الرسم()::نجاح { أرجع 6; }
        frames = frames + 1;
    }
    دع final = ويب::حالة_الجلسة(owner)::قيمة;
    إذا لا ويب::أغلق_الجلسة(owner)::نجاح { أرجع 7; }
    إذا لا رايليب::أغلق_النافذة()::نجاح { أرجع 8; }
    إذا final::busy و final::fast و final::conflict {
        اطبع("busy fast conflict\n");
    }
    أرجع 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout undefined
نزّل المصدر
aspl check raylib-concurrent-http-ar.aspl
aspl run raylib-concurrent-http-ar.aspl
raylib-concurrent-http-en · ASPL 0.7.0

المضيف الأصلي فقط

// Run an upstream HTTP server on 127.0.0.1:8001, then request /busy, /wait and
// /fast on port 8000. The window keeps drawing while the handlers share turns.
import core::raylib;
import core::http;

record State { frames: i64, busy: bool, fast: bool, conflict: bool }

fn outbound(ctx: http::Context<string,State>, saved: i64) -> http::ServerResponse {
    let snapshot = http::snapshot_state(ctx);
    let request = http::client_request("GET", http::read_config(ctx))::value;
    let reply = http::request(request, http::client_options());
    if not reply::ok {
        return http::text_response(502, reply::error::code, "text/plain")::value;
    }
    if saved not matches 7 { return http::response(500, [])::value; }
    let published = http::replace_state_if_current(ctx, snapshot, snapshot::value)::value;
    var current = http::read_state(ctx);
    current::conflict = not published;
    http::replace_state(ctx, current);
    return http::text_response(200, "conflict", "text/plain")::value;
}

fn handler(req: http::IncomingRequest, ctx: http::Context<string,State>) -> http::ServerResponse {
    if req::path matches "/busy" {
        var state = http::read_state(ctx);
        state::busy = true;
        http::replace_state(ctx, state);
        while true {}
    }
    if req::path matches "/wait" { return outbound(ctx, 7); }
    var current = http::read_state(ctx);
    current::fast = raylib::IsWindowReady();
    http::replace_state(ctx, current);
    return http::text_response(200, "fast", "text/plain")::value;
}

fn start_main() -> i64 {
    let opened = raylib::InitWindow(480, 240, "ASPL HTTP and drawing");
    if not opened::ok { print(opened::error::code); return 1; }
    let pacing = raylib::SetTargetFPS(60);
    if not pacing::ok { return 9; }
    var server = http::server_config();
    server::listeners = [http::listener("127.0.0.1", 8000)::value];
    let routes = http::router([
        http::route("GET", "/busy", handler)::value,
        http::route("GET", "/wait", handler)::value,
        http::route("GET", "/fast", handler)::value
    ])::value;
    let started = http::start(server, routes, "http://127.0.0.1:8001/",
        State {frames: 0, busy: false, fast: false, conflict: false});
    if not started::ok { print(started::error::code); return 2; }
    let owner = started::value;
    print("ready\n");
    var budget = http::progress_budget();
    budget::max_instructions = 128;
    var frames: i32 = 0;
    while frames < 180 and not raylib::WindowShouldClose()::value {
        if not http::progress(owner, budget)::ok { return 3; }
        if not raylib::BeginDrawing()::ok { return 4; }
        if not raylib::ClearBackground(raylib::RAYWHITE)::ok { return 10; }
        var state = http::snapshot_session_state(owner)::value::value;
        state::frames = state::frames + 1;
        if not http::replace_session_state(owner, state)::ok { return 5; }
        if not raylib::DrawRectangle(frames, 90, 40, 40, raylib::BLUE)::ok { return 11; }
        if not raylib::EndDrawing()::ok { return 6; }
        frames = frames + 1;
    }
    let final = http::session_state(owner)::value;
    if not http::close_session(owner)::ok { return 7; }
    if not raylib::CloseWindow()::ok { return 8; }
    if final::busy and final::fast and final::conflict {
        print("busy fast conflict\n");
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout undefined
نزّل المصدر
aspl check raylib-concurrent-http-en.aspl
aspl run raylib-concurrent-http-en.aspl
raylib-concurrent-http-mixed · ASPL 0.7.0

المضيف الأصلي فقط

// Run an upstream HTTP server on 127.0.0.1:8001, then request /busy, /wait and
// /fast on port 8000. The window keeps drawing while the handlers share turns.
import core::raylib;
استورد أساسي::رايليب.
import core::http;

record State { frames: i64, busy: bool, fast: bool, conflict: bool }

fn outbound(ctx: http::Context<string,State>, saved: i64) -> http::ServerResponse {
    let snapshot = http::snapshot_state(ctx);
    let request = http::client_request("GET", http::read_config(ctx))::value;
    let reply = http::request(request, http::client_options());
    if not reply::ok {
        return http::text_response(502, reply::error::code, "text/plain")::value;
    }
    if saved not matches 7 { return http::response(500, [])::value; }
    let published = http::replace_state_if_current(ctx, snapshot, snapshot::value)::value;
    var current = http::read_state(ctx);
    current::conflict = not published;
    http::replace_state(ctx, current);
    return http::text_response(200, "conflict", "text/plain")::value;
}

fn handler(req: http::IncomingRequest, ctx: http::Context<string,State>) -> http::ServerResponse {
    if req::path matches "/busy" {
        var state = http::read_state(ctx);
        state::busy = true;
        http::replace_state(ctx, state);
        while true {}
    }
    if req::path matches "/wait" { return outbound(ctx, 7); }
    var current = http::read_state(ctx);
    current::fast = raylib::IsWindowReady();
    http::replace_state(ctx, current);
    return http::text_response(200, "fast", "text/plain")::value;
}

fn start_main() -> i64 {
    let opened = raylib::InitWindow(480, 240, "ASPL HTTP and drawing");
    if not opened::ok { print(opened::error::code); return 1; }
    let pacing = raylib::SetTargetFPS(60);
    if not pacing::ok { return 9; }
    var server = http::server_config();
    server::listeners = [http::listener("127.0.0.1", 8000)::value];
    let routes = http::router([
        http::route("GET", "/busy", handler)::value,
        http::route("GET", "/wait", handler)::value,
        http::route("GET", "/fast", handler)::value
    ])::value;
    let started = http::start(server, routes, "http://127.0.0.1:8001/",
        State {frames: 0, busy: false, fast: false, conflict: false});
    if not started::ok { print(started::error::code); return 2; }
    let owner = started::value;
    print("ready\n");
    var budget = http::progress_budget();
    budget::max_instructions = 128;
    var frames: i32 = 0;
    while frames < 180 and not raylib::WindowShouldClose()::value {
        if not http::progress(owner, budget)::ok { return 3; }
        if not raylib::ابدأ_الرسم()::ok { return 4; }
        if not raylib::ClearBackground(raylib::RAYWHITE)::ok { return 10; }
        var state = http::snapshot_session_state(owner)::value::value;
        state::frames = state::frames + 1;
        if not http::replace_session_state(owner, state)::ok { return 5; }
        if not raylib::DrawRectangle(frames, 90, 40, 40, raylib::BLUE)::ok { return 11; }
        if not raylib::أنه_الرسم()::ok { return 6; }
        frames = frames + 1;
    }
    let final = http::session_state(owner)::value;
    if not http::close_session(owner)::ok { return 7; }
    if not raylib::CloseWindow()::ok { return 8; }
    if final::busy and final::fast and final::conflict {
        print("busy fast conflict\n");
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout undefined
نزّل المصدر
aspl check raylib-concurrent-http-mixed.aspl
aspl run raylib-concurrent-http-mixed.aspl
raylib-identity-literals-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد أساسي::رايليب;
استورد أساسي::ويب;

غير_آمن خارجي absolute(number: ص32) -> ص32 = سي("libc.so.6", "abs");

// User identifiers and record fields keep their own names in all three files.
سجل Asset { filename: نص, untouched: نص }

دالة ابدأ_الرئيسية() -> ص64 {
    إذا غير_آمن absolute(-7) لا يطابق 7 { أرجع 11; }
    دع asset = Asset { filename: "docs/examples/assets/raylib-sprites.png", untouched: "مسار/é.png\0A" };
    إذا asset::filename لا يطابق "docs/examples/assets/raylib-sprites.png" { أرجع 1; }
    إذا asset::untouched لا يطابق "مسار/e\u{0301}.png\0A" { أرجع 2; }
    دع a: رايليب::متجه2 = رايليب::متجه2 { س: 1.25, ص: 2.5 };
    دع b: رايليب::متجه2 = رايليب::متجه2 { س: a::س, ص: a::ص };
    إذا b::س لا يطابق 1.25 أو b::ص لا يطابق 2.5 { أرجع 3; }
    دع key: رايليب::مفتاح = رايليب::مفتاح_مسافة;
    إذا key لا يطابق رايليب::مفتاح_مسافة { أرجع 4; }
    دع flags = رايليب::علم_نافذة_قابلة_للتحجيم | رايليب::علم_تلميح_تزامن_رأسي;
    إذا flags لا يطابق رايليب::علم_نافذة_قابلة_للتحجيم | رايليب::علم_تلميح_تزامن_رأسي { أرجع 5; }
    دع budget: ويب::ميزانية_تقدم = ويب::ميزانية_التقدم();
    إذا budget::حد_التعليمات لا يطابق 4096 { أرجع 6; }
    دع font = رايليب::الخط_الافتراضي();
    إذا لا font::نجاح { اطبع(font::error::الرسالة); أرجع 7; }
    دع english = رايليب::قس_النص_موسعا(font::قيمة, "سلام ASPL 123", 32.0, 0.0);
    دع arabic = رايليب::قس_النص_موسعا(font::قيمة, "سلام ASPL 123", 32.0, 0.0);
    إذا لا english::نجاح أو لا arabic::نجاح { أرجع 8; }
    إذا english::value::س لا يطابق arabic::value::س { أرجع 9; }
    دع invalid = رايليب::قس_النص("bad\ttext", 32);
    إذا invalid::نجاح أو invalid::error::الرمز لا يطابق "raylib.invalid_text" { أرجع 10; }
    اطبع(invalid::error::الرسالة); اطبع("\n");
    اطبع(asset::filename); اطبع("\n");
    اطبع(asset::untouched); اطبع("\nidentity and literals complete\n");
    أرجع 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "Text input is invalid. مدخل النص غير صالح. MeasureText: text.input: scalar_index=3 scalar=U+0009.\ndocs/examples/assets/raylib-sprites.png\nمسار/é.png\u0000A\nidentity and literals complete\n"
نزّل المصدر
aspl check raylib-identity-literals-ar.aspl
aspl run raylib-identity-literals-ar.aspl
raylib-identity-literals-en · ASPL 0.7.0

المضيف الأصلي فقط

import core::raylib;
import core::http;

unsafe foreign absolute(number: i32) -> i32 = c("libc.so.6", "abs");

// User identifiers and record fields keep their own names in all three files.
record Asset { filename: string, untouched: string }

fn start_main() -> i64 {
    if unsafe absolute(-7) not matches 7 { return 11; }
    let asset = Asset { filename: "docs/examples/assets/raylib-sprites.png", untouched: "مسار/é.png\0A" };
    if asset::filename not matches "docs/examples/assets/raylib-sprites.png" { return 1; }
    if asset::untouched not matches "مسار/e\u{0301}.png\0A" { return 2; }
    let a: raylib::Vector2 = raylib::Vector2 { x: 1.25, y: 2.5 };
    let b: raylib::Vector2 = raylib::Vector2 { x: a::x, y: a::y };
    if b::x not matches 1.25 or b::y not matches 2.5 { return 3; }
    let key: raylib::Key = raylib::KEY_SPACE;
    if key not matches raylib::KEY_SPACE { return 4; }
    let flags = raylib::FLAG_WINDOW_RESIZABLE | raylib::FLAG_VSYNC_HINT;
    if flags not matches raylib::FLAG_WINDOW_RESIZABLE | raylib::FLAG_VSYNC_HINT { return 5; }
    let budget: http::ProgressBudget = http::progress_budget();
    if budget::max_instructions not matches 4096 { return 6; }
    let font = raylib::GetFontDefault();
    if not font::ok { print(font::error::message); return 7; }
    let english = raylib::MeasureTextEx(font::value, "سلام ASPL 123", 32.0, 0.0);
    let arabic = raylib::MeasureTextEx(font::value, "سلام ASPL 123", 32.0, 0.0);
    if not english::ok or not arabic::ok { return 8; }
    if english::value::x not matches arabic::value::x { return 9; }
    let invalid = raylib::MeasureText("bad\ttext", 32);
    if invalid::ok or invalid::error::code not matches "raylib.invalid_text" { return 10; }
    print(invalid::error::message); print("\n");
    print(asset::filename); print("\n");
    print(asset::untouched); print("\nidentity and literals complete\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "Text input is invalid. مدخل النص غير صالح. MeasureText: text.input: scalar_index=3 scalar=U+0009.\ndocs/examples/assets/raylib-sprites.png\nمسار/é.png\u0000A\nidentity and literals complete\n"
نزّل المصدر
aspl check raylib-identity-literals-en.aspl
aspl run raylib-identity-literals-en.aspl
raylib-identity-literals-mixed · ASPL 0.7.0

المضيف الأصلي فقط

import core::raylib;
استورد أساسي::رايليب.
import core::http;
استورد أساسي::ويب.

unsafe foreign absolute(number: i32) -> i32 = c("libc.so.6", "abs");

// User identifiers and record fields keep their own names in all three files.
record Asset { filename: string, untouched: string }

fn start_main() -> i64 {
    if unsafe absolute(-7) not matches 7 { return 11; }
    let asset = Asset { filename: "docs/examples/assets/raylib-sprites.png", untouched: "مسار/é.png\0A" };
    if asset::filename not matches "docs/examples/assets/raylib-sprites.png" { return 1; }
    if asset::untouched not matches "مسار/e\u{0301}.png\0A" { return 2; }
    let a: raylib::Vector2 = رايليب::متجه2 { س: 1.25, ص: 2.5 };
    let b: رايليب::متجه2 = raylib::Vector2 { x: a::س, y: a::y };
    if b::x not matches 1.25 or b::ص not matches 2.5 { return 3; }
    let key: رايليب::مفتاح = raylib::KEY_SPACE;
    if key not matches رايليب::مفتاح_مسافة { return 4; }
    let flags = رايليب::علم_نافذة_قابلة_للتحجيم | raylib::FLAG_VSYNC_HINT;
    if flags not matches raylib::FLAG_WINDOW_RESIZABLE | رايليب::علم_تلميح_تزامن_رأسي { return 5; }
    let budget: ويب::ميزانية_تقدم = http::progress_budget();
    if budget::حد_التعليمات not matches 4096 { return 6; }
    let font = raylib::GetFontDefault();
    if not font::ok { print(font::error::message); return 7; }
    let english = raylib::MeasureTextEx(font::value, "سلام ASPL 123", 32.0, 0.0);
    let arabic = رايليب::قس_النص_موسعا(font::value, "سلام ASPL 123", 32.0, 0.0);
    if not english::ok or not arabic::ok { return 8; }
    if english::value::x not matches arabic::value::س { return 9; }
    let invalid = raylib::MeasureText("bad\ttext", 32);
    if invalid::ok or invalid::error::code not matches "raylib.invalid_text" { return 10; }
    print(invalid::error::message); print("\n");
    print(asset::filename); print("\n");
    print(asset::untouched); print("\nidentity and literals complete\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "Text input is invalid. مدخل النص غير صالح. MeasureText: text.input: scalar_index=3 scalar=U+0009.\ndocs/examples/assets/raylib-sprites.png\nمسار/é.png\u0000A\nidentity and literals complete\n"
نزّل المصدر
aspl check raylib-identity-literals-mixed.aspl
aspl run raylib-identity-literals-mixed.aspl
الحدود المعيارية للإصدار

ارجع إلى العقد

البرنامج وحالة العملية

دالة البداية

يبدأ برنامج ASPL بالدالة الإلزامية ابدأ_الرئيسية / start_main في الملف الجذر. لا تأخذ معاملات وتعيد i64. تشمل التصريحات العليا الدوال والسجلات والاستيرادات. يمكن للبرامج الأصلية استخدام وحدات مصدر المستخدم والتصريحات الخارجية. توضع العبارات التنفيذية والروابط داخل الدوال.

لا يمكن استدعاء دالة البداية من المصدر. يفشل الفحص عند غيابها بالسبب missing-entry-function أو عند وجود توقيع غير صالح بالسبب invalid-entry-signature. ويفشل استدعاؤها بالسبب entry-call-not-allowed.

حالة العملية

أعد عددا صحيحا من 0 إلى 255 بوصفه حالة العملية. تنهي أي نتيجة أخرى التنفيذ بالنتيجة trap / invalid-process-status، ولا تختزل ASPL القيمة. ينطبق عقد البداية نفسه على مضيف المتصفح والمضيف الأصلي في ASPL 0.7.0.

الحالة والخرج مستقلان. الإرجاع العادي للقيمة 1 تنفيذ ASPL ناجح. أخطاء المصدر والفخاخ والنتائج القابلة للاسترداد والإلغاء وفشل المضيف أو الموارد نتائج مختلفة. استخدم اطبع لإنتاج الخرج، والأوامر الأصلية لاصطلاحات حالة CLI.

مثال كامل

يعيد هذا المثال المفحوص الحالة 0 ولا ينتج خرجا. مفردات المصدر مستقلة عن لغة التوثيق.

حدد نوع نتيجة دالة البداية وحالة العملية المعادة في المثال.
{
  "browser": {
    "check": "success",
    "class": "success",
    "output": "",
    "processStatus": 0
  },
  "native": {
    "check": 0,
    "status": 0,
    "output": ""
  }
}
hello-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout ""
native: check 0; success / status 0; stdout ""
نزّل المصدر افتح في المحرر
aspl check hello.aspl
aspl run hello.aspl
hello-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout ""
native: check 0; success / status 0; stdout ""
نزّل المصدر افتح في المحرر
aspl check hello.aspl
aspl run hello.aspl
الحدود المعيارية للإصدار

أوامر Linux ومراحلها

صياغة أوامر Linux

تصف هذه الأشكال أداة ASPL 0.7.0 الأصلية المنشورة. اتبع صفحة التثبيت للتحقق وإعداد PATH.

aspl [COMMON_OPTIONS] check [--] SOURCE
aspl [COMMON_OPTIONS] run [--] SOURCE
aspl [COMMON_OPTIONS] build [-o OUTPUT | --output=OUTPUT] [--] SOURCE

الخياران المشتركان هما --diagnostic-language=ar|en و--color=auto|always|never. يسبقان الأمر ولا يجوز تكرار أي منهما. القيم حساسة لحالة الأحرف وتستخدم =. تسبق خيارات خرج البناء المصدر. يسمح -- بمسار مصدر يبدأ بشرطة. تنتهي مسارات المصدر بـ.aspl أو .لبات؛ يأخذ الأمر مصدرا جذريا واحدا ويحمل استيراداته الصريحة لوحدات المصدر. لا تقبل الأوامر المصدر من stdin أو جذورا متعددة أو خرج بايت كود عامّا أو معاملات للبرنامج.

استخدم aspl --version أو aspl --help أو aspl build --help للمعلومات. الإصدار سطر مستقل عن اللغة هو aspl 0.7.0. تستخدم المساعدة والتشخيصات العربية افتراضيا بغض النظر عن مفردات المصدر أو لغة العملية. للإنجليزية، استخدم aspl --diagnostic-language=en --help.

مراحل الترجمة والتنفيذ

تقرأ الأوامر الثلاثة المصدر وتحل وحداته الصريحة وتترجم بايت الكود الخاص وتتحقق منه. يتخلص check بعد ذلك من النتيجة. يجهز run الاعتمادات الأصلية وينفذ في العملية نفسها. يغلف build ملف ELF ويتحقق منه ويكتب ملفا مؤقتا في مجلد الوجهة ثم ينشره بإعادة تسمية ذرية. لا يستدعي مترجما خارجيا أو رابطا. لا ينفذ الفحص والبناء البرنامج ولا يحملان مكتباته الخارجية.

دون خيار خرج، يزيل البناء لاحقة المصدر الأخيرة. تستخدم مسارات الخرج الصريحة كما قدمت. لا تنشأ المجلدات الأب المفقودة. يرفض الخرج الذي يطابق المصدر. يحتفظ الفشل قبل النشر بالخرج السابق، ويستبدله النشر الناجح. لا تضمن الرؤية الذرية المتانة عند انقطاع الطاقة.

الحالات وقنوات الخرج

يعيد الفحص أو البناء الناجح صفرا ويكون صامتا ما لم توجد تحذيرات. يعيد run والبرنامج المبني نتيجة دالة البداية الصحيحة العادية من 0 إلى 255. تؤدي النتيجة خارج المجال إلى فخ. قد تتداخل النتائج العادية غير الصفرية مع حالات الفشل؛ افحص stderr للتشخيصات. لا تغير التحذيرات حالة النجاح.

حالة الفشل النتيجة
1 أخطاء المصدر
2 استخدام غير صالح للأوامر
3 رفض سياسة المضيف
4 فشل تحميل
5 فخ ASPL
6 توقف عند حد مضبوط
7 إلغاء تعاوني
8 فشل مضيف
9 فشل داخلي

يستخدم خرج البرنامج stdout وتستخدم التشخيصات والفخاخ stderr. لا يضيف run رسالة نجاح إلى خرج البرنامج. استخدم --color=never لتشخيصات بلا ألوان في السكربتات. ترث الأداة دليل العمل والبيئة والقنوات القياسية. للكود الخارجي صلاحية العملية الأصلية وقد يفشل خارج ضمانات وقت تشغيل ASPL.

خيارات البرنامج المبني

لا يقبل البرنامج المبني إلا --aspl-diagnostic-language=ar|en و--aspl-color=auto|always|never، كل منهما مرة واحدة باستخدام =. دون خيارات، تكون التشخيصات عربية والألوان تلقائية. لا يقبل معاملات عادية أو -- أو --help أو --version. مثلا، يشغل ./hello --aspl-diagnostic-language=en --aspl-color=never البرنامج. انظر الإدخال الأصلي والتنفيذ المستقل.

الحدود المعيارية للإصدار

الإدخال الأصلي والبرامج المبنية

إدخال الأسطر الأصلي

في ASPL 0.7.0، تقرأ اقرأ_سطر / read_line: () -> string سطرا واحدا من stdin الموروث. لا تقبل معاملات أو وسم غير_آمن. لا تطبع الدالة مطالبة أو صدى أو نهاية سطر. اطبع المطالبة أولا؛ تظهر قبل انتظار الإدخال حتى دون سطر جديد. يستخدم إدخال الطرفية والأنابيب والملفات المعاد توجيهها القارئ نفسه في aspl run والبرامج المبنية.

تزال نهايتا LF وCRLF. يعيد السطر الفارغ نصا فارغا. يعاد السطر الأخير غير المنتهي مرة واحدة عند EOF، وتؤدي القراءة اللاحقة إلى فخ input-exhausted. تبقى المسافات وNUL والعلامات العربية ومحارف الاتجاه والأرقام والتطبيع كما قدمت. الإدخال بيانات لا تمر بتحويل أرقام المصدر. يستهلك القارئ السطر الحالي فقط ويترك بايتات stdin اللاحقة للقراءات التالية أو الكود الخارجي.

نهاية الإدخال وحالات فشله

يتحقق وقت التشغيل من كل سطر كامل بوصفه UTF-8 صارما. تسبب البايتات غير الصالحة فخ invalid-input-utf8 مع إزاحة أول بايت غير صالح. الحد الافتراضي للسطر 65536 بايت محتوى دون LF أو CRLF. ينجح الحجم المطابق تماما؛ ويوقف السطر الأكبر التنفيذ بحالة input-line-limit بدلا من إرجاع نص مبتور. نهاية الإدخال دون سطر فخ وليست نصا فارغا. لا يبلغ الإلغاء أو تقاطع إشارة أثناء الانتظار بوصفه EOF.

تجربة الأنبوب وإعادة التوجيه

نزّل مثال الإدخال المقدم باسم input.aspl. يسأل عن الاسم ويطبع الاسم المقدم مع التحية ويعيد صفرا. تحتفظ صيغة المفردات الإنجليزية بنص المطالبة والخرج العربي الأصلي.

printf 'Mina\n' | aspl run input.aspl
printf 'Mina\n' > name.txt
aspl run input.aspl < name.txt
aspl build -o input input.aspl
printf 'Mina\n' | ./input
./input < /dev/null

تطبع أشكال التنفيذ الثلاثة الأولى ما اسمك؟ مرحبا Mina وسطرًا جديدًا. لا يجد الأمر الأخير سطرا: يطبع المطالبة ثم يتوقف بفخ input-exhausted وتشخيص في stderr وحالة 5. لاختيار نص التشخيص الإنجليزي، استخدم ./input --aspl-diagnostic-language=en < /dev/null.

متطلبات البرنامج المستقل

تتضمن القوالب الأصلية المنشورة للإصدار 0.7.0 الآلة الافتراضية وبايت كود خاصا بالإصدار 7. بايت الكود الخاص ليس تنسيق ملفات عاما مستقرا. يعمل ELF المبني بعد إزالة المصدر وASPL من PATH. يظل بحاجة إلى محمل Linux والمكتبات المتوافقة والمكتبات الخارجية أو بيانات التنفيذ التي يستخدمها. لا يتحقق البناء من توافر اعتمادات التنفيذ هذه.

ترث البرامج المبنية stdin وstdout وstderr والبيئة ودليل العمل. خياراتها الوحيدة هي خيارات التشخيص الأصلية. استخدم ./program لتنفيذ ملف محلي؛ لا يدخل الملف التنفيذي في الدليل الحالي تلقائيا ضمن PATH. لا تغير ترقية الأداة الأصلية أو الرجوع عنها ملف ELF موجودا. أعد البناء من المصدر بالأداة المختارة إذا أردت برنامجها المولد.

input-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    اطبع("ما اسمك؟ ").
    دع الاسم = اقرأ_سطر().
    اطبع("مرحبا ").
    اطبع(الاسم).
    اطبع("\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "ما اسمك؟ مرحبا ليلى\n"
native: check 0; success / status 0; stdout "ما اسمك؟ مرحبا ليلى\n"
scripted stdin lines: ["ليلى"]
نزّل المصدر افتح في المحرر
aspl check input-ar.aspl
aspl run input-ar.aspl
input-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    print("ما اسمك؟ ");
    let الاسم = read_line();
    print("مرحبا ");
    print(الاسم);
    print("\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "ما اسمك؟ مرحبا Mina\n"
native: check 0; success / status 0; stdout "ما اسمك؟ مرحبا Mina\n"
scripted stdin lines: ["Mina"]
نزّل المصدر افتح في المحرر
aspl check input-en.aspl
aspl run input-en.aspl
input-mixed · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn مرر(value: string) -> string {
    return value;
}

fn start_main() -> i64 {
    print("first: ");
    var first = اقرأ_سطر();
    let kept = first.
    let returned = مرر(first).
    اطبع("second: ").
    let second = read_line().
    first = second.
    إذا returned matches kept {
        print("equal: ");
        print(returned).
        اطبع(" / ").
        print(kept).
        اطبع("\n").
        return 0.
    }
    أرجع 1.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "first: second: equal: ١٢٣ / ١٢٣\n"
native: check 0; success / status 0; stdout "first: second: equal: ١٢٣ / ١٢٣\n"
scripted stdin lines: ["١٢٣","١٢٣"]
نزّل المصدر افتح في المحرر
aspl check input-mixed.aspl
aspl run input-mixed.aspl
الحدود المعيارية للإصدار

كتابة المصدر

قواعد المصدر

المصدر UTF-8 صارم وفق Unicode 17.0. الأسماء حساسة لحالة الحروف وبتطبيع NFC، وبخط عربي أو لاتيني واحد لكل اسم. المفردات والعوامل الإنجليزية بدائل مطابقة ويمكن مزجها. الأرقام وعلامات الترقيم في الشيفرة من ASCII، وتكتب المساواة والاقتران والفصل بـ matches وand وor أو ببدائلها العربية يطابق وتطابق وو وأو. للأعداد بادئات 0x/0X و0b/0B أو 0س و0ث؛ سداسي عشر العربية يستخدم ا ب ت ث ج ح للقيم 10 إلى 15. تنتهي العبارات بـ . أو ;. يبقى كل رمز عددي LTR في ترتيب المصدر المنطقي، ولا يغير ترتيب العرض بايتات المصدر.

تستخدم المعرّفات ملف Unicode لـXID_Start وXID_Continue مع _، ويحدد تطبيع NFC الهوية. يسمح بعلامة UTF-8 BOM في البداية وتحسب ضمن حجم المصدر. يسمح بـNUL الخام داخل النصوص والتعليقات ويمنع خارجهما. ينشئ \0 داخل النص أيضا NUL وقت التشغيل. تحتفظ النصوص والتعليقات بمحتواها دون تطبيع. يسمح بـLRM وRLM عند حدود الرموز القانونية فقط، وترفض المحارف المحظورة الأخرى. تكشف التشخيصات محارف التحكم برمزها واسمها.

match اسم بديل آخر للمساواة. not / لا / ليس / ليست ينفي الشرط ويمكن أن يسبق المساواة مثل a not match b. != لعدم المساواة، و== و&& و|| غير صالحة.

تحويل أرقام المحرر

مقبول: كلمات عربية وإنجليزية وبادئا عدد في البرنامج نفسه. مرفوض: أرقام غير محولة خارج النصوص والتعليقات، أو اسم يجمع الخطين، أو تهجئة سداسية عشر تخلط الأبجديتين. يحول المحرر أرقام العربية الهندية والفارسية إلى ASCII خارج النصوص والتعليقات ويعرض محارف التحكم غير المرئية بوضوح.

يحوّل الإدخال واللصق في محرر المصدر الأرقام فقط خارج النصوص والتعليقات. استيراد ملف المصدر يحفظ بايتاته ولا يجري هذا التحويل. إدخال البرنامج ونص التحليل العددي لا يمران بالمحرر. العرض RTL أو LTR والنسخ يحفظان ترتيب المصدر المنطقي.

النصوص والتعليقات

النص بين علامتي اقتباس مزدوجتين. المحارف المهربة هي \\ و\" و\0 و\n و\r و\t و\u{...} لقيمة Unicode scalar واحدة من رقم إلى ستة أرقام سداسية عشرية. السطر الخام أو الهروب المجهول خطأ. يبدأ // تعليق سطر، و/* ... */ تعليق كتلة لا يتداخل. راجع مرجع الأعداد للحرفيات والبادئات.

يقبل ASPL 0.7.0 أيضا بدائل عربية لمحارف الهروب. يمكن مزج الصيغتين في النص نفسه، وينتج كل زوج البايتات نفسها. تبقى الشرطة المائلة العكسية بداية الهروب، ويظل / محرفا عاديا داخل النص.

الإنجليزية العربية القيمة
\\ \\ شرطة مائلة عكسية حرفية
\" \" علامة اقتباس مزدوجة حرفية
\0 \ص المحرف الصفري، U+0000
\n \س سطر جديد، U+000A
\r \ر رجوع إلى بداية السطر، U+000D
\t \ت تبويب أفقي، U+0009
\u{...} \ي{...} قيمة يونيكود عددية واحدة

تحتفظ \u{...} بأبجدية ASCII السداسية عشرية. تقبل \ي{...} أرقام ASCII السداسية عشرية إضافة إلى ا ب ت ث ج ح للقيم 10 إلى 15، ويمكن مزج الأبجديتين. تتطلب الصيغتان رقما إلى ستة أرقام، وترفضان القيم البديلة والقيم الأعلى من U+10FFFF، وتقبلان U+0000 داخل النصوص. مثلا تنتج \ي{062ت} و\u{062C} المحرف ج نفسه. لا تقبل أي صيغة أرقام العربية الهندية أو الفواصل. تحتفظ ملفات الإصدار المنشور 0.6.0 بصيغة الهروب الأصلية.

نطاق الإصدار والمراجع

تصف هذه الصفحة ASPL 0.7.0. نص MVP المرتبط سجل تاريخي، ولا يصف كل الإضافات الحالية.

أضاف امتداد الأعداد بادئات الأساس والعمليات البتية. يبقى == و&& و|| غير صالح. المثال جمع الأعداد يبيّن المفردات المختلطة.

sum-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    متغير المجموع: ص64 = 0.
    متغير العدد: ص64 = 1.
    طالما (العدد <= 10) {
        المجموع = المجموع + العدد.
        العدد = العدد + 1.
    }
    إذا (المجموع يطابق 55) {
        اطبع("55\n").
        أرجع 0.
    }
    أرجع 1.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "55\n"
native: check 0; success / status 0; stdout "55\n"
نزّل المصدر افتح في المحرر
aspl check sum-ar.aspl
aspl run sum-ar.aspl
sum-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    var المجموع: i64 = 0;
    var العدد: i64 = 1;
    while (العدد <= 10) {
        المجموع = المجموع + العدد;
        العدد = العدد + 1;
    }
    if (المجموع matches 55) {
        print("55\n");
        return 0;
    }
    return 1;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "55\n"
native: check 0; success / status 0; stdout "55\n"
نزّل المصدر افتح في المحرر
aspl check sum-en.aspl
aspl run sum-en.aspl
sum-mixed · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn ابدأ_الرئيسية() -> ص64 {
    متغير المجموع: ص64 = 0;
    متغير العدد: ص64 = 1;
    طالما (العدد <= 10) {
        المجموع = المجموع + العدد;
        العدد = العدد + 1;
    }
    إذا (المجموع matches 55) {
        print("55\n");
        return 0;
    }
    أرجع 1;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "55\n"
native: check 0; success / status 0; stdout "55\n"
نزّل المصدر افتح في المحرر
aspl check sum-mixed.aspl
aspl run sum-mixed.aspl
الحدود المعيارية للإصدار

الأنواع والتدفق

الأنواع الدقيقة

لا توجد تحويلات ضمنية. كل قيمة عددية مكتوبة لها نوعها الدقيق وعرضها وإشارتها. العمليات تحتاج نوعي معاملين متطابقين، والحدود أو الحاويات لا تحوّل القيمة. التحويل الوحيد هو تطبيق اسم نوع عددي صريح مثل ط8(value) أو u8(value)، وقد يوقف التنفيذ عند عدم تمثيل القيمة. يبقى ص64/i64 لنتيجة البداية والفهارس والأطوال وحدود يونيكود. النص ثابت، وc_ptr معتم وقابل للقيمة الفارغة، ولا يمكن تخزين unit. يتيح الربط المهيأ استنتاج النوع، وتتطلب if, while شرطا منطقيا، وreturn نتيجة من النوع المعلن.

الأسماء الأساسية الأخرى هي منطقي / bool ونص / string ومؤشر_سي / c_ptr ووحدة / unit. الحرفيات المنطقية صواب / true وخطأ / false، والمؤشر الفارغ عدم / null. تحتاج المساواة نوعين متطابقين، وتقارن النصوص بايتات UTF-8 بالضبط والمؤشرات بالهوية. لا يمكن تخزين unit أو تمريرها كقيمة أو مقارنتها.

الروابط

دع / let ثابت ومتغير / var قابل للإسناد. كل رابط يحتاج قيمة أولية. يمكن كتابة النوع بعد : أو استنتاجه. لا يسمح بالتظليل. الأنواع العددية المكتوبة لا تتحول ضمنيا حتى داخل قائمة أو سجل أو نتيجة. تشمل 0.7.0 أيضا list<T> وresult<T> والسجلات والقيم القابلة للاستدعاء، وهي إضافات إلى الأنواع الأساسية في MVP.

التدفق والتقييم

الشروط من نوع bool فقط. و / and وأو / or يقصران التقييم، و! ينفي الشرط. تقيم المعاملات والحجج والقيم الأولية من اليسار إلى اليمين. يحسب الإسناد الطرف الأيمن كاملا قبل تعديل الهدف. تستخدم إذا / if ووإلا / else وطالما / while كتلا مع نطاق معجمي. لا يوجد break أو continue. يجب أن تعيد كل مسارات الدالة غير unit القيمة المعلنة. تثبت if الإرجاع إذا أعاد الفرعان، بينما لا تثبته while. الكود الذي يثبت الفاحص أنه غير قابل للوصول مرفوض.

مثال الجمع يطبع 55\n ويرجع الحالة 0. التشخيص والتصحيح يوضح رفض تعديل رابط ثابت.

نطاق الإصدار والمراجع

تصف هذه الصفحة ASPL 0.7.0. نص MVP المرتبط سجل تاريخي، ولا يصف كل الإضافات الحالية.

الحدود المعيارية للإصدار

عائلة الأعداد الدقيقة

الأنواع والمجالات

العربية English الحد الأدنى الحد الأعلى
ص8 i8 -128 127
ص16 i16 -32768 32767
ص32 i32 -2147483648 2147483647
ص64 i64 -9223372036854775808 9223372036854775807
ط8 u8 0 255
ط16 u16 0 65535
ط32 u32 0 4294967295
ط64 u64 0 18446744073709551615

ع32 / f32 هو IEEE 754 binary32، وع64 / f64 هو binary64. كل زوج اسمي يشير إلى نوع واحد دقيق. لا يجوز إعادة تعريف هذه الأسماء أو أسماء التحليل والتنسيق العددي.

حرفيات المصدر

العدد العشري ذو الأصفار البادئة عشري. يقبل السداسي عشر اللاتيني 0x/0X الأرقام وa..f/A..F، ويقبل 0س الأرقام وا ب ت ث ج ح. يقبل الثنائي 0b/0B أو 0ث. يحتاج كل بادئ رقما واحدا على الأقل. تسمح _ بين رقمين صحيحين فقط، فلا تلامس البادئ أو النقطة أو الأس ولا تبدأ أو تنتهي أو تتكرر. لا توجد لاحقات نوعية أو ثماني أو عائم سداسي عشر أو حرفيات NaN أو infinity. النقطة منهي للعبارة ما لم تبدأ كسرا: 1. عدد صحيح ثم منهي و1.0. عدد عائم ثم منهي.

للعائم العشري كسر بأرقام على جانبي . أو أس e أو E بإشارة اختيارية ورقم واحد على الأقل. يقبل 1e2 و1.0e-2، ولا يقبل .5. إشارة المصدر عامل وحادي وليست جزءا من رمز الحرفية. لا تمزج أبجديتي الأساس في رمز واحد. كل الأرقام ASCII حتى مع البادئات العربية.

السياق والأسبقية

الأسبقية من الأقوى إلى الأضعف هي الاستدعاء والفهرسة والحقل والتجميع، ثم ! - ~، ثم * / %، ثم + -، ثم الإزاحات، ثم & ثم ^ ثم |، ثم المقارنات المرتبة، ثم المساواة، ثم AND المنطقي ثم OR المنطقي. العمليات الثنائية يسارية والوحادية يمينية.

نوع السياق يأتي من التصريح أو الإسناد أو المعامل أو الإرجاع أو الحقل أو القائمة أو النتيجة أو معامل مكتوب. العدد بلا سياق هو i64 أو f64. يقبل السالب المباشر أصغر قيمة موقعة، ويمتد حرفي u64 السياقي إلى 18446744073709551615. لا يختار الفاحص أصغر نوع مناسب ولا يحول قيمة مكتوبة سابقا.

عمليات الصحيح

الجمع والطرح والضرب والقسمة تحتاج نوعا متطابقا وتعيده، و% للصحيح فقط. فائض الجمع والطرح والضرب والسالب الصحيح الموقع يوقف التنفيذ بـinteger-overflow بدلا من الالتفاف. يرفض الفحص السالب الوحادي لعدد صحيح غير موقع مكتوب النوع بالسبب numeric-operator-not-supported. القسمة تقطع نحو الصفر، والباقي بإشارة المقسوم، والصفر أو أصغر موقّع على -1 يوقف التنفيذ. تعمل ~ & ^ | << >> بعرض المعامل بالضبط. عد الإزاحة أي عدد صحيح، ولا يحول إلى نوع الطرف الأيسر. العدد السالب أو الذي يساوي العرض أو يتجاوزه يوقف التنفيذ بـinvalid-shift-count. اليسرى تطرح البتات العالية، واليمنى غير الموقعة تصفر والعلامية تمد الإشارة.

العائم والتحويل الصريح

كل عملية f32 أو f64 تقرب لأقرب زوجي عند عرضها قبل العملية التالية. لا يوجد دمج مضاعفة وجمع. تبقى الأعداد دون العادية، والصفر الموقع، واللانهاية، ونتائج IEEE للقسمة على الصفر. تسوى NaN الناتجة إلى NaN هادئة موجبة، ومقارنتها المرتبة كاذبة.

يطبق التحويل الصريح أي اسم نوع على تعبير عددي فقط. تحويل الصحيح إلى صحيح يفحص المدى، والصحيح إلى العائم يقرب العدد الرياضي مباشرة إلى عرض الهدف لأقرب زوجي، وكل صحيح منته؛ لذلك يتحول أكبر u64 إلى 2^64 في f64. العائم إلى صحيح يقطع أولا ثم يفحص المدى، وتحويلات العرض العائم تقرب ولا توقف التنفيذ. الفشل المعتمد على قيمة التحويل لا يقع إلا إذا وصل التنفيذ إليه؛ تصنيفاته below-range وabove-range وnan وpositive-infinity وnegative-infinity. تكمل التحويلات المتداخلة من الداخل وتحفظ كل نقطة تقريب.

التحليل والتنسيق

لكل نوع محلل ومنسق: حلل_ص8/parse_i8 ونسق_ص8/format_i8؛ حلل_ص16/parse_i16 ونسق_ص16/format_i16؛ حلل_ص32/parse_i32 ونسق_ص32/format_i32؛ حلل_ص64/parse_i64 ونسق_ص64/format_i64؛ حلل_ط8/parse_u8 ونسق_ط8/format_u8؛ حلل_ط16/parse_u16 ونسق_ط16/format_u16؛ حلل_ط32/parse_u32 ونسق_ط32/format_u32؛ حلل_ط64/parse_u64 ونسق_ط64/format_u64؛ حلل_ع32/parse_f32 ونسق_ع32/format_f32؛ حلل_ع64/parse_f64 ونسق_ع64/format_f64.

المحلل يأخذ string ويعيد result<T>، والمنسق يأخذ T بالضبط ويعيد string. نص الصحيح إشارة ASCII اختيارية ثم أرقام ASCII عشرية. نص العائم إشارة ASCII اختيارية وأرقام، وكسر اختياري بأرقام تالية، وأُس اختياري e أو E بإشارة ASCII اختيارية وأرقام، أو واحد من nan, inf, +inf, -inf.

هذه قواعد نص وقت التشغيل وليست قواعد حرفيات المصدر: ترفض المسافات والفواصل والبادئات واللاحقات وNUL والذيل والأرقام غير ASCII، ورفض .5 و1. للعائم. يفحص المحلل البنية كلها قبل المدى. الرسائل الحرفية هي invalid number for T أو number out of range for T (MIN through MAX) أو finite number out of range for T. النتيجة الفاشلة بلا تشخيص أو موضع أو أثر.

التنسيق ASCII حتمي وقابل للذهاب والإياب للقيم العائمة المنتهية، ويطبع -0 وnan وinf و-inf كما هي.

التخزين العددي

تخزن الروابط والمعاملات والنتائج وحقول السجلات والقوائم وحمولات النتائج الأنواع العشرة بدقة. لكل خانة محجوزة في قائمة رقمية عرضها: 1 بايت لـi8/u8، و2 لـi16/u16، و4 لـi32/u32/f32، و8 لـi64/u64/f64.

طول القائمة والسعة والرسوم منفصلة: القائمة الفارغة سعتها صفر، والسعة غير الفارغة بين الطول وmax(4, 2 * length)، ورسوم العناصر capacity * width. النسخ تشترك أولا ثم تنفصل عند التعديل، وتحرر الذاكرة بعد آخر مالك. لا يوجد عرض بايت عام أو وعد بعنوان أو محاذاة أو ترتيب بايتات أو مخطط C. توقف الذاكرة أو الإلغاء أو فشل التخصيص لا ينشر تعديلا جزئيا.

نطاق الإصدار والمراجع

تضيف قواعد الأعداد المؤرشفة لـ0.4.0 العروض العشرة والسداسي والثنائي والبتات والتحليل لكل نوع. تبقى قواعدها العددية في 0.7.0، لكن رقم البايت كود الحالي هو 7 وليس 4. سلك نتيجة المتصفح 3. البايت كود خاص وليس واجهة توافق عامة. لا تغيّر هذه الصفحة نص MVP القديم الذي حدد i64 وf64 فقط.

النجاح والفشل المقصود

حقول التشخيص تشرح الفرق بين رفض الحرفية وفخ التحويل.

اقرأ العائلات الكاملة:

numeric-types-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع الحد: ط64 = 18446744073709551615.
    دع مباشر: ع32 = 1.0000000596046448.
    دع بتات: ط8 = 0سحح.
    دع محول: ط8 = ط8(255).
    إذا (نسق_ط64(الحد) لا يطابق "18446744073709551615") { أرجع 1. }
    إذا (نسق_ع32(مباشر) لا يطابق "1.00000012") { أرجع 2. }
    إذا ((بتات & 0س0ح) لا يطابق 15 أو (بتات >> 4) لا يطابق 15 أو محول لا يطابق 255) { أرجع 3. }
    متغير بايتات: قائمة<ط8> = [0, 255].
    متغير نسخة: قائمة<ط8> = بايتات.
    نسخة[0] = بتات << 0.
    إذا (بايتات[0] لا يطابق 0 أو نسخة[0] لا يطابق 255) { أرجع 4. }
    اطبع("numeric types\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "numeric types\n"
native: check 0; success / status 0; stdout "numeric types\n"
نزّل المصدر افتح في المحرر
aspl check numeric-types-ar.aspl
aspl run numeric-types-ar.aspl
numeric-types-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let الحد: ط64 = 18446744073709551615;
    let مباشر: f32 = 1.0000000596046448;
    let بتات: ط8 = 0سحح;
    let محول: ط8 = ط8(255);
    if (format_u64(الحد) not match "18446744073709551615") { return 1; }
    if (format_f32(مباشر) not match "1.00000012") { return 2; }
    if ((بتات & 0س0ح) not match 15 or (بتات >> 4) not match 15 or محول not match 255) { return 3; }
    var بايتات: list<ط8> = [0, 255];
    var نسخة: list<ط8> = بايتات;
    نسخة[0] = بتات << 0;
    if (بايتات[0] not match 0 or نسخة[0] not match 255) { return 4; }
    print("numeric types\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "numeric types\n"
native: check 0; success / status 0; stdout "numeric types\n"
نزّل المصدر افتح في المحرر
aspl check numeric-types-en.aspl
aspl run numeric-types-en.aspl
numeric-types-mixed · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn ابدأ_الرئيسية() -> i64 {
    دع maximum: u64 = 18446744073709551615.
    let direct: ع32 = 1.0000000596046448;
    let latin: ط8 = 0xff;
    دع عربي: u8 = 0سحح.
    let binary_latin: u8 = 0b0011;
    دع binary_arabic: ط8 = 0ث0011.
    let converted: u8 = ط8(255);
    if (نسق_ط64(maximum) not match "18446744073709551615") { return 1. }
    إذا (format_f32(direct) not match "1.00000012") { أرجع 2; }
    if ((latin & 0x0f) not match 15 or (عربي >> 4) not match 15) { return 3. }
    إذا ((binary_latin | binary_arabic) not match 3 أو converted not match 255) { أرجع 4; }
    var bytes: قائمة<u8> = [0, latin];
    متغير copy: list<ط8> = bytes.
    copy[0] = عربي.
    if (bytes[0] not match 0 or copy[0] not match 255) { return 5. }
    print("numeric types\n");
    return 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "numeric types\n"
native: check 0; success / status 0; stdout "numeric types\n"
نزّل المصدر افتح في المحرر
aspl check numeric-types-mixed.aspl
aspl run numeric-types-mixed.aspl
numeric-range-check-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع بايت: ط8 = 256.
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check source-error; source-error / numeric-literal-out-of-range; stdout ""
native: check 1; source-error / status 1 / numeric-literal-out-of-range; stdout ""
نزّل المصدر افتح في المحرر
aspl check numeric-range-check-ar.aspl
numeric-range-check-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let بايت: ط8 = 256;
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check source-error; source-error / numeric-literal-out-of-range; stdout ""
native: check 1; source-error / status 1 / numeric-literal-out-of-range; stdout ""
نزّل المصدر افتح في المحرر
aspl check numeric-range-check-en.aspl
numeric-conversion-trap-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع بايت: ط8 = ط8(256).
    اطبع(نسق_ط8(بايت)).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; trap / invalid-numeric-conversion; stdout ""
native: check 0; success / status 5 / invalid-numeric-conversion; stdout ""
نزّل المصدر افتح في المحرر
aspl check numeric-conversion-trap-ar.aspl
aspl run numeric-conversion-trap-ar.aspl
numeric-conversion-trap-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let بايت: ط8 = ط8(256);
    print(format_u8(بايت));
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; trap / invalid-numeric-conversion; stdout ""
native: check 0; success / status 5 / invalid-numeric-conversion; stdout ""
نزّل المصدر افتح في المحرر
aspl check numeric-conversion-trap-en.aspl
aspl run numeric-conversion-trap-en.aspl
الحدود المعيارية للإصدار

التشخيص والتصحيح

حقول التشخيص

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

موضع المصدر والتصحيح

اختر التشخيص لتحديد موضعه في نسخة المصدر التي فُحصت. مواضع النقل هي إزاحات بايت UTF-8 نصف مفتوحة، ويعرض المحرر التحديد في المصدر المنطقي. قد يتضمن التشخيص تعديلا مقترحا. في مثال الرابط الثابت يشير الموضع الأولي إلى المعرّف المسند إليه، والمواضع الثانوية فارغة، ولا يوجد تعديل تلقائي مقدم. استبدل يدويا دع / let بـمتغير / var. يمكن أن تتضمن تشخيصات أخرى مواضع ثانوية مرتبة. تطبيق التصحيح ثم إعادة الفحص لا يشغّل البرنامج تلقائيا. المصدر المصحح يرجع 1 بنجاح ولا يطبع شيئا.

للتصحيح التلقائي، ينتج unsafe print("text") التشخيص unsafe-on-safe-call مع تعديل يزيل علامة unsafe. طبق التعديل صراحة ثم أعد الفحص. يشير الموضع الأولي إلى العلامة ونص الاستبدال فارغ.

نتائج مختلفة

مثال let byte: u8 = 256 خطأ فحص لأن الحرفي السياقي خارج المدى. أما u8(256) فمعامله i64 افتراضي صالح ثم يوقف التنفيذ بفخ invalid-numeric-conversion إذا وصل إليه. وparse_u8("256") يعيد نتيجة فاشلة بالرمز number-out-of-range. لا يتحول واحد من هذه المخرجات إلى الآخر.

خطأ المصدر يمنع الترجمة. التحذير يسمح بها. result<T> الفاشلة قيمة يستطيع البرنامج فحصها. الفخ يوقف البرنامج ولا يمكن التقاطه. فشل التحميل يقع قبل التنفيذ. limit-stop وcancelled وhost-failure نتائج مستقلة. success مع الحالة 1 نجاح لغة، حتى لو فسرته أداة shell كحالة غير صفرية.

حقول الأعداد

حقول خطأ الفحص numeric-literal-out-of-range للأعداد الصحيحة هي spelling, type, minimum, maximum، وللعائم spelling, type, classification حيث التصنيف finite-overflow. وحقول numeric-operator-not-supported هي operator, type.

حقول الفخ العددية مرتبة: integer-overflow يحمل type, operation, operand-count, operands؛ وinteger-zero-divisor يحمل type, operation, dividend؛ وinvalid-shift-count يحمل left-type, count-type, count, width؛ وinvalid-numeric-conversion يحمل source-type, target-type, classification ثم source-value أو source-bits. تحمل القيم غير الموقعة حتى u64 كاملة بلا تقريب JavaScript.

نطاق الإصدار والمراجع

تصف هذه الصفحة ASPL 0.7.0. نص MVP المرتبط سجل تاريخي، ولا يصف كل الإضافات الحالية.

diagnostic-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع قيمة = 0.
    قيمة = 1.
    أرجع قيمة.
}

النتائج المتوقعة والخرج الحرفي

browser: check source-error; source-error / immutable-assignment; stdout ""
native: check 1; source-error / status 1 / immutable-assignment; stdout ""
نزّل المصدر افتح في المحرر
aspl check diagnostic-ar.aspl
diagnostic-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let قيمة = 0;
    قيمة = 1;
    return قيمة;
}

النتائج المتوقعة والخرج الحرفي

browser: check source-error; source-error / immutable-assignment; stdout ""
native: check 1; source-error / status 1 / immutable-assignment; stdout ""
نزّل المصدر افتح في المحرر
aspl check diagnostic-en.aspl
corrected-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    متغير قيمة = 0.
    قيمة = 1.
    أرجع قيمة.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 1; stdout ""
native: check 0; success / status 1; stdout ""
نزّل المصدر افتح في المحرر
aspl check corrected-ar.aspl
aspl run corrected-ar.aspl
corrected-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    var قيمة = 0;
    قيمة = 1;
    return قيمة;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 1; stdout ""
native: check 0; success / status 1; stdout ""
نزّل المصدر افتح في المحرر
aspl check corrected-en.aspl
aspl run corrected-en.aspl
الحدود المعيارية للإصدار

الطباعة الآمنة

اطبع النص

توقيع الطباعة المدمجة هو اطبع / print: (string) -> unit. يكتب بايتات النص بالترتيب، بما فيها NUL، بلا سطر جديد أو تفريغ تلقائي. أضف \n صراحة. لا يمكن إعادة تعريف أي من الاسمين. يعرض المتصفح بايتات الخرج بأمان ولا يفسرها كترميز صفحة.

مقبول: نص واحد، بما فيه النص الفارغ. مرفوض: عدد أو معاملات متعددة أو تخزين النتيجة.

الخرج والحالة وفشل المضيف

الكتابة متزامنة، والنص الفارغ لا يلمس المضيف. يعيد المضيف الأصلي محاولة الكتابات المقطوعة ويتابع الكتابات القصيرة. يبقى أي خرج مقبول قبل الفشل ظاهرا. لا توجد معالجة خاصة لإشارة SIGPIPE؛ قد ينهي الأنبوب المغلق العملية بها. إذا تجاهلت البيئة الإشارة أو حجبتها وأعادت الكتابة EPIPE، تكون النتيجة فشل مضيف بالحالة 8.

الخرج مستقل عن حالة العملية. حد المتصفح 256 KiB يرفض الكتابة المتجاوزة كاملة ويحفظ الخرج السابق. يعرض المتصفح النص بأمان حتى لو احتوى على علامات HTML.

نطاق الإصدار والمراجع

تصف هذه الصفحة ASPL 0.7.0. نص MVP المرتبط سجل تاريخي، ولا يصف كل الإضافات الحالية.

output-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    اطبع("مرحبا\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "مرحبا\n"
native: check 0; success / status 0; stdout "مرحبا\n"
نزّل المصدر افتح في المحرر
aspl check output-ar.aspl
aspl run output-ar.aspl
output-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    print("مرحبا\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "مرحبا\n"
native: check 0; success / status 0; stdout "مرحبا\n"
نزّل المصدر افتح في المحرر
aspl check output-en.aspl
aspl run output-en.aspl
الحدود المعيارية للإصدار

إدخال سطر

قراءة السطر وEOF

الدالة المدمجة اقرأ_سطر / read_line: () -> string تقرأ سطرا واحدا. لا تقبل معاملات أو وسم غير_آمن / unsafe، ولا يمكن تعريف اسم من أسمائها. اطبع أي مطالبة قبل الاستدعاء، فالدالة نفسها لا تكتب مطالبة أو صدى أو فاصلة نهاية. ينتهي السطر بـLF أو CRLF وتزال النهاية. السطر الفارغ نص فارغ. يعاد السطر الأخير غير المنتهي مرة واحدة عند EOF، ثم يوقف الاستدعاء التالي بـinput-exhausted.

مقبول: تمرير النص المقروء إلى دالة أو إعادته أو مقارنته أو طباعته أو قياسه أو فهرسته أو اقتطاعه أو جمعه أو تحليله صراحة بدالة عددية. مرفوض: اعتبار نص المصدر أو أرقام العربية الهندية إدخالا عدديا مقبولا، أو تحويل النص ضمنيا إلى عدد.

حفظ الإدخال وUTF-8

يتحقق وقت التشغيل من بايتات السطر كلها بوصفها UTF-8 صارما. تبقى المسافات وNUL وعلامات العربية ومحارف الاتجاه والأرقام العربية الهندية وشكل التطبيع كما أرسله المضيف. لا يمر إدخال البرنامج عبر محرر المصدر أو محلله أو تحويل أرقامه. السطر غير الصالح يوقف التنفيذ بـinvalid-input-utf8 مع موضع أول بايت غير صالح.

حد السطر والإلغاء

الحد في المضيفين هو 65536 بايت حمولة للسطر، من دون LF أو CRLF. يقبل الحد بالضبط، أما تجاوزه فينهي التنفيذ بـinput-line-limit من دون نص مبتور. إلغاء التنفيذ أثناء الانتظار إلغاء وليس EOF.

عمر النص

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

نطاق الإصدار والمراجع

تصف هذه الصفحة ASPL 0.7.0. نص MVP المرتبط سجل تاريخي، ولا يصف كل الإضافات الحالية.

أضيف إدخال الأسطر بعد MVP الذي كان يملك الخرج فقط. راجع إدخال المتصفح أو الإدخال الأصلي.

الحدود المعيارية للإصدار

إدخال الملعب في المتصفح

طلب الإدخال

حين يصل البرنامج إلى read_line يعرض الملعب حالة انتظار وحقل سطر واحد وزري Send وClose input وStop. يرسل Send المسودة الحالية للطلب المعروض فقط، ثم يمسحها بعد إقرار العامل. يرسل Close input EOF ولا يرسل المسودة، وتبقى ظاهرة بوصفها غير مرسلة. يوقف Stop التنفيذ ولا يعني EOF.

مسودة الإدخال

لا يقبل الحقل لصقا متعدد الأسطر أو محرفي CR وLF، ويعرض حد البايتات. تبقى بايتات المسودة والأرقام كما أدخلت ولا تمر عبر محرر المصدر. تسجل أصداء الإدخال كسجلات واجهة منفصلة ولا تدخل في خرج البرنامج أو حد خرجه.

الوقت وحالة المسودة

يقيس حد التنفيذ زمن العمل المتراكم فقط. الوقت الذي يقضيه البرنامج منتظرا الإدخال لا يستهلكه. تحافظ أزرار Auto وLTR وRTL على بايتات الخرج والمسودة ولقطة المصدر وهوية الطلب، وتعيد تنسيق العرض والمحاذاة فقط.

يتوقف الطلب عند مغادرة Home أو تبديل مسودة المصدر. الرجوع يعيد البيانات المحفوظة في المستند ويعيد الفحص، ولا يعيد التشغيل أو إرسال الإدخال. التحديث يبدأ دون خرج أو إدخال سابق. تحفظ Stop الخرج ومسودة الإدخال غير المرسلة. راجع حدود التنفيذ وقراءة السطر.

نطاق الإصدار والمراجع

تصف هذه الصفحة ASPL 0.7.0. نص MVP المرتبط سجل تاريخي، ولا يصف كل الإضافات الحالية.

أضيف الإدخال التفاعلي بعد MVP. تقتصر هذه الصفحة على الإدخال، وملفات التشغيل الافتراضية بيانات مؤقتة منفصلة.

الحدود المعيارية للإصدار

المضيف وحدود التنفيذ

المضيفان

يشغّل المتصفح المترجم والآلة في عامل محلي داخل WebAssembly دون إرسال المصدر إلى خادم. يرفض الاستيراد الخارجي ولو لم يستدع، بالنتيجة policy-rejection / foreign-imports-not-supported. لا يدعم وحدات مصدر المستخدم أو C أو HTTP أو Raylib. المضيف الأصلي يشغّل البرنامج على Linux بصلاحيات العملية وليس صندوقا معزولا.

سقوف الموارد

MiB = 1048576 bytes; KiB = 1024 bytes.

المورد الأصلي المتصفح
بايتات المصدر 16 MiB 1 MiB
الوحدات المعجمية 1048576 131072
عقد الصياغة 1048576 131072
عمق الصياغة 256 128
ذاكرة المترجم العاملة 512 MiB 128 MiB
بايتات البايت كود 64 MiB 8 MiB
الدوال 65536 4096
الاستيرادات الخارجية 4096 0
ثوابت الأعداد الصحيحة 1048576 131072
ثوابت الأعداد العائمة 1048576 131072
مراجع النصوص 1048576 131072
بايتات النصوص 16 MiB 2 MiB
حمولة سطر الإدخال 65536 bytes 65536 bytes
تعليمات البايت كود 4194304 524288
السجلات لكل دالة 65536 8192
التعليمات المنفذة none 10000000
إطارات وقت التشغيل 4096 512
مواضع قيم وقت التشغيل 1048576 131072
ذاكرة التنفيذ المملوكة للآلة 256 MiB 64 MiB
الخرج الملتقط none 256 KiB
زمن الفحص none 2 s
زمن التنفيذ none 3 s
الذاكرة الخطية n/a 256 MiB
وظائف العامل المتزامنة n/a 1

none لا سقف منتج، وn/a لا ينطبق. يوقف العامل أول حد ملحوظ.

حساب الذاكرة

يشمل المصدر كل بايت مقروء بما فيه علامة بداية النص. تشمل ذاكرة المترجم كل تخصيص حي للترجمة. تشمل ذاكرة التنفيذ الإطارات ومواضع القيم وإعارة النص والنصوص الحية المملوكة للتنفيذ، وتستبعد البرنامج الثابت والمكتبات وتخصيصات الشيفرة الخارجية. يتقدم فشل الحد البنيوي على حد الذاكرة عند العملية نفسها. فشل التخصيص دون السقف هو host-failure / allocation-failed.

الوقت والخرج

يبدأ مؤقت الفحص حين يقبل العامل المحمّل المهمة، ومؤقت التنفيذ حين يقبل التشغيل بعد نجاح الفحص. لا يدخل التحميل في المؤقتين، ولا يدخل انتظار إدخال المستخدم في مؤقت التنفيذ. أول حد ملحوظ يحدد النتيجة؛ بلوغ الموعد ينهي العامل بسبب time-limit. يرفض حد الخرج الاستدعاء الذي يتجاوزه بأكمله ويبقي الخرج السابق جزئيا. ليس للتنفيذ الأصلي سقف منتج للتعليمات أو الوقت أو الخرج، مع بقاء الحد التمثيلي لعداد التعليمات.

نطاق الإصدار والمراجع

تصف هذه الصفحة ASPL 0.7.0. نص MVP المرتبط سجل تاريخي، ولا يصف كل الإضافات الحالية.

في 0.7.0 البايت كود الخاص 7 وسلك نتيجة المتصفح 3. يحسب حد الذاكرة أيضا تخزين القوائم والسجلات والنتائج الحية، وتضاف ميزات الملفات والإدخال إلى نطاق MVP التاريخي.

حلقة محدودة في المتصفح

افتح المثال في المتصفح فقط. لا تشغله أصليا، فالمضيف الأصلي بلا سقف تعليمات منتج. أول حد ملحوظ يحدد النتيجة، وقد يصل مؤقت الوقت قبل سقف التعليمات على جهاز بطيء.

limit-ar · ASPL 0.7.0

المتصفح فقط

دالة ابدأ_الرئيسية() -> ص64 {
    طالما صواب {}
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; limit-stop / execution-instruction-limit / ceiling 10000000; stdout ""
نزّل المصدر افتح في المحرر
limit-en · ASPL 0.7.0

المتصفح فقط

fn start_main() -> i64 {
    while true {}
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; limit-stop / execution-instruction-limit / ceiling 10000000; stdout ""
نزّل المصدر افتح في المحرر
الحدود المعيارية للإصدار

الدوال المضمنة

استدعاء الدوال المضمنة

الدوال المضمنة معرفة مسبقا، ولا تحتاج استيرادا أو علامة غير_آمن / unsafe. كلا الاسمين العربي والإنجليزي محجوز للهدف نفسه، فلا يجوز تعريفهما أو تظليلهما. يفحص المترجم عدد الحجج وأنواعها الدقيقة. تعبير التحويل مثل u8(value) عملية لغة مفحوصة، وليس محلل نص يعيد نتيجة قابلة للاسترداد.

المجموعات والأسماء

هذه الأسماء متاحة في 0.7.0 على المضيفين. ملفات المتصفح افتراضية ومؤقتة.

العربية English
اطبع print
اقرأ_سطر read_line
طول length
محرف_عند char_at
رمز_عند codepoint_at
من_رمز from_codepoint
اقتطع slice
نجاح success
إخفاق failure
أضف append
اجمع_نصوص join
حلل_ص64 parse_i64
نسق_ص64 format_i64
حلل_ع64 parse_f64
نسق_ع64 format_f64
حلل_ع32 parse_f32
نسق_ع32 format_f32
حلل_ص8 parse_i8
حلل_ص16 parse_i16
حلل_ص32 parse_i32
حلل_ط8 parse_u8
حلل_ط16 parse_u16
حلل_ط32 parse_u32
حلل_ط64 parse_u64
نسق_ص8 format_i8
نسق_ص16 format_i16
نسق_ص32 format_i32
نسق_ط8 format_u8
نسق_ط16 format_u16
نسق_ط32 format_u32
نسق_ط64 format_u64
اقرأ_ملف_نصي read_text_file
اكتب_ملف_نصي write_text_file

الأنواع والنتائج والمضيف

راجع الخرج وإدخال السطر والتحليل والتنسيق العددي. تستخدم length للنصوص والقوائم، وباقي عمليات النص حدود Unicode scalar من نوع i64. يبني success وfailure نتائج قابلة للفحص. يعدل append هدف قائمة قابلا للتغيير، وjoin يجمع list<string> بفاصل نصي. يعيد read_text_file نتيجة result<string> وwrite_text_file نتيجة result<unit>. عمليات الفشل المتوقعة لا تتحول إلى فخاخ. ليست أسماء المكتبات المؤهلة مثل net_http::get دوال مضمنة مشتركة، بل تحتاج المضيف الأصلي والاستيراد. مجموعات الأمثلة توفر المصادر الحالية للنصوص والنتائج والملفات.

نطاق الإصدار

كان MVP يحدد اطبع / print فقط. تصف هذه الصفحة المجموعة المضمنة في 0.7.0، بما فيها إضافات النصوص والإدخال والنتائج والقوائم والملفات والأعداد.

الحدود المعيارية للإصدار

النصوص ويونيكود

قيم النص الدقيقة

يدعم ASPL 0.7.0 هذه العمليات في المتصفح والمضيف الأصلي. نص/string قيمة UTF-8 صحيحة وثابتة. تحفظ BOM وNUL ونهايات الأسطر وعلامات الاتجاه والمسافات والتطبيع كما هي. تقارن يطابق/matches البايتات الدقيقة. النصان "é" و"e\u{301}" مختلفان حتى إن بدوا متشابهين.

مواضع قيم يونيكود العددية

تبدأ المواضع من الصفر وتعد قيم يونيكود العددية، لا بايتات UTF-8 أو وحدات UTF-16 أو المحارف المرئية المركبة. تعد علامة التشكيل قيمة مستقلة، وقد يتكون تسلسل الرموز التعبيرية من عدة قيم. نتيجة length("aمرحبا😀") هي 7.

العملية التوقيع المعنى
طول/length (string) -> i64 عدد القيم العددية
محرف_عند/char_at (string, i64) -> string قيمة واحدة كنص
رمز_عند/codepoint_at (string, i64) -> i64 العدد الذي يمثل القيمة
من_رمز/from_codepoint (i64) -> string نص من قيمة عددية صالحة
اقتطع/slice (string, i64, i64) -> string البداية مشمولة والنهاية مستبعدة

يجب أن يحقق الفهرس 0 <= index < length(text)، وأن يحقق المقطع 0 <= start <= end <= length(text). تنجح المقاطع الفارغة، ومنها المقطع عند النهاية. يوقف الفهرس غير الصالح التنفيذ بسبب string-index-out-of-bounds، والمقطع غير الصالح بسبب string-slice-out-of-bounds. تقبل from_codepoint الصفر حتى 1114111 باستثناء القيم البديلة من 55296 حتى 57343، وتوقف القيم غير الصالحة التنفيذ بسبب invalid-unicode-scalar.

الدمج وجمع النصوص

تدمج + نصين بأسبقية الجمع المعتادة. نسق العدد صراحة قبل دمجه مع نص. تضع اجمع_نصوص/join: (list<string>, string) -> string الفاصل بين العناصر فقط. تنتج القائمة الفارغة ""، ولا يضاف فاصل إلى العنصر الوحيد. لا تغير العمليتان المدخلات أو تطبيع النص.

النص العددي الصارم

يسرد مرجع الأعداد المحللات والمنسقات لكل عرض دقيق. يعيد التحليل نتيجة قابلة للاسترداد، ولا يوقف التنفيذ لمجرد نص عددي غير صالح. يقبل النص الصحيح إشارة ASCII اختيارية وأرقاما عشرية ASCII، بما فيها الأصفار البادئة. يقبل النص العشري إشارة ASCII اختيارية وأرقاما وجزءا كسريا اختياريا بأرقام بعد النقطة وأسا اختياريا، أو التهجئات الدقيقة nan وinf و+inf و-inf.

تنتج المسافات والأرقام غير ASCII مثل ٢ وNUL وبادئات الأساس والفواصل واللواحق والذيل الرمز invalid-number. تفشل أيضا .5 و1.. ينتج النص الصحيح نحويا خارج مجال النوع number-out-of-range. لا يحول تحويل أرقام المصدر في المحرر النص المرسل عبر إدخال البرنامج أو الملفات المستوردة.

يحتاج مثال تحليل الصحيح سطري إدخال، 256 ثم 41. ويحتاج مثال تحليل العشري 12x ثم 41. يعالج كلاهما النتيجة الفاشلة الأولى ويواصل لطباعة 42 للسطر الثاني.

النطاق والأمثلة الكاملة

توسع هذه العمليات الحالية قواعد النصوص في MVP التاريخي. تبقى المواصفة المؤرشفة سجلا لذلك النطاق السابق. تجد الصيغ الكاملة الموردة في النصوص وجمع النصوص وتحليل الصحيح وتحليل العشري.

strings-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع المتن = "aمرحبا😀".
    إذا (طول(المتن) لا يطابق 7) { أرجع 1. }
    إذا (محرف_عند(المتن, 1) لا يطابق "م") { أرجع 2. }
    إذا (رمز_عند(المتن, 1) لا يطابق 1605) { أرجع 3. }
    إذا (من_رمز(65) لا يطابق "A") { أرجع 4. }
    إذا (اقتطع(المتن, 1, 3) لا يطابق "مر") { أرجع 5. }
    دع الرسالة = المتن + "!".
    اطبع(الرسالة).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "aمرحبا😀!"
native: check 0; success / status 0; stdout "aمرحبا😀!"
نزّل المصدر افتح في المحرر
aspl check strings-ar.aspl
aspl run strings-ar.aspl
strings-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let المتن = "aمرحبا😀";
    if (length(المتن) not match 7) { return 1; }
    if (char_at(المتن, 1) not match "م") { return 2; }
    if (codepoint_at(المتن, 1) not match 1605) { return 3; }
    if (from_codepoint(65) not match "A") { return 4; }
    if (slice(المتن, 1, 3) not match "مر") { return 5; }
    let الرسالة = المتن + "!";
    print(الرسالة);
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "aمرحبا😀!"
native: check 0; success / status 0; stdout "aمرحبا😀!"
نزّل المصدر افتح في المحرر
aspl check strings-en.aspl
aspl run strings-en.aspl
strings-mixed · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn ابدأ_الرئيسية() -> ص64 {
    دع المتن = "aمرحبا😀";
    if (طول(المتن) not match 7) { return 1; }
    إذا (char_at(المتن, 1) not match "م") { أرجع 2. }
    let رمز = رمز_عند(المتن, 1);
    if (رمز not match 1605) { return 3; }
    دع حرف = from_codepoint(65).
    إذا (حرف not match "A") { أرجع 4. }
    let مقطع = اقتطع(المتن, 1, 3);
    if (مقطع not match "مر") { return 5; }
    دع الرسالة = المتن + "!";
    اطبع(الرسالة).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "aمرحبا😀!"
native: check 0; success / status 0; stdout "aمرحبا😀!"
نزّل المصدر افتح في المحرر
aspl check strings-mixed.aspl
aspl run strings-mixed.aspl
join-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع فارغة: قائمة<نص> = [].
    إذا (اجمع_نصوص(فارغة, ",") لا يطابق "") { أرجع 1. }
    دع واحدة: قائمة<نص> = ["مرحبا"].
    إذا (اجمع_نصوص(واحدة, ",") لا يطابق "مرحبا") { أرجع 2. }
    دع أجزاء: قائمة<نص> = ["a", "b", "c"].
    إذا (اجمع_نصوص(أجزاء, ",") لا يطابق "a,b,c") { أرجع 3. }
    إذا (اجمع_نصوص(أجزاء, "") لا يطابق "abc") { أرجع 4. }
    اطبع(اجمع_نصوص(أجزاء, ",")).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "a,b,c"
native: check 0; success / status 0; stdout "a,b,c"
نزّل المصدر افتح في المحرر
aspl check join-ar.aspl
aspl run join-ar.aspl
join-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let فارغة: list<string> = [];
    if (join(فارغة, ",") not match "") { return 1; }
    let واحدة: list<string> = ["مرحبا"];
    if (join(واحدة, ",") not match "مرحبا") { return 2; }
    let أجزاء: list<string> = ["a", "b", "c"];
    if (join(أجزاء, ",") not match "a,b,c") { return 3; }
    if (join(أجزاء, "") not match "abc") { return 4; }
    print(join(أجزاء, ","));
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "a,b,c"
native: check 0; success / status 0; stdout "a,b,c"
نزّل المصدر افتح في المحرر
aspl check join-en.aspl
aspl run join-en.aspl
join-mixed · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn ابدأ_الرئيسية() -> ص64 {
    دع فارغة: قائمة<string> = [].
    if (اجمع_نصوص(فارغة, ",") not match "") { return 1; }
    دع واحدة: list<نص> = ["مرحبا"];
    إذا (join(واحدة, ",") not match "مرحبا") { أرجع 2. }
    let أجزاء: قائمة<string> = ["a", "b", "c"];
    if (طول(أجزاء) not match 3) { return 3; }
    إذا (اجمع_نصوص(أجزاء, ",") not match "a,b,c") { أرجع 4. }
    if (join(أجزاء, "") not match "abc") { return 5; }
    اطبع(join(أجزاء, ",")).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "a,b,c"
native: check 0; success / status 0; stdout "a,b,c"
نزّل المصدر افتح في المحرر
aspl check join-mixed.aspl
aspl run join-mixed.aspl
parse-int-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    اطبع("first: ").
    دع سيئ: نتيجة<ط8> = حلل_ط8(اقرأ_سطر()).
    إذا (سيئ::نجاح) {
        أرجع 1.
    }
    اطبع(سيئ::الخطأ::الرمز).
    اطبع("\nsecond: ").
    دع جيد: نتيجة<ص64> = حلل_ص64(اقرأ_سطر()).
    إذا (جيد::نجاح) {
        إذا (نسق_ص64(-9223372036854775808) لا يطابق "-9223372036854775808") { أرجع 2. }
        اطبع(نسق_ص64(جيد::قيمة + 1)).
        اطبع("\n").
        أرجع 0.
    }
    أرجع 3.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "first: number-out-of-range\nsecond: 42\n"
native: check 0; success / status 0; stdout "first: number-out-of-range\nsecond: 42\n"
scripted stdin lines: ["256","41"]
نزّل المصدر افتح في المحرر
aspl check parse-int-ar.aspl
aspl run parse-int-ar.aspl
parse-int-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    print("first: ");
    let سيئ: result<ط8> = parse_u8(read_line());
    if (سيئ::ok) {
        return 1;
    }
    print(سيئ::error::code);
    print("\nsecond: ");
    let جيد: result<i64> = parse_i64(read_line());
    if (جيد::ok) {
        if (format_i64(-9223372036854775808) not match "-9223372036854775808") { return 2; }
        print(format_i64(جيد::value + 1));
        print("\n");
        return 0;
    }
    return 3;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "first: number-out-of-range\nsecond: 42\n"
native: check 0; success / status 0; stdout "first: number-out-of-range\nsecond: 42\n"
scripted stdin lines: ["256","41"]
نزّل المصدر افتح في المحرر
aspl check parse-int-en.aspl
aspl run parse-int-en.aspl
parse-int-mixed · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn ابدأ_الرئيسية() -> ص64 {
    اطبع("first: ").
    let سيئ: نتيجة<u8> = parse_u8(اقرأ_سطر()).
    إذا (سيئ::ok) { أرجع 1. }
    print(سيئ::الخطأ::code).
    print("\nsecond: ").
    دع جيد: result<ص64> = حلل_ص64(read_line()).
    if (جيد::نجاح) {
        إذا (format_i64(-9223372036854775808) not match "-9223372036854775808") { return 2. }
        اطبع(نسق_ص64(جيد::value + 1)).
        print("\n").
        أرجع 0.
    }
    return 3.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "first: number-out-of-range\nsecond: 42\n"
native: check 0; success / status 0; stdout "first: number-out-of-range\nsecond: 42\n"
scripted stdin lines: ["256","41"]
نزّل المصدر افتح في المحرر
aspl check parse-int-mixed.aspl
aspl run parse-int-mixed.aspl
parse-float-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    اطبع("first: ").
    دع سيئ: نتيجة<ع32> = حلل_ع32(اقرأ_سطر()).
    إذا (سيئ::نجاح) {
        أرجع 1.
    }
    اطبع(سيئ::الخطأ::الرمز).
    اطبع("\nsecond: ").
    دع جيد: نتيجة<ع64> = حلل_ع64(اقرأ_سطر()).
    إذا (جيد::نجاح) {
        إذا (نسق_ع64(0.5) لا يطابق "0.5") { أرجع 2. }
        إذا (نسق_ع32(1.0000000596046448) لا يطابق "1.00000012") { أرجع 3. }
        اطبع(نسق_ع64(جيد::قيمة + 1.0)).
        اطبع("\n").
        أرجع 0.
    }
    أرجع 4.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "first: invalid-number\nsecond: 42\n"
native: check 0; success / status 0; stdout "first: invalid-number\nsecond: 42\n"
scripted stdin lines: ["12x","41"]
نزّل المصدر افتح في المحرر
aspl check parse-float-ar.aspl
aspl run parse-float-ar.aspl
parse-float-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    print("first: ");
    let سيئ: result<f32> = parse_f32(read_line());
    if (سيئ::ok) {
        return 1;
    }
    print(سيئ::error::code);
    print("\nsecond: ");
    let جيد: result<f64> = parse_f64(read_line());
    if (جيد::ok) {
        if (format_f64(0.5) not match "0.5") { return 2; }
        if (format_f32(1.0000000596046448) not match "1.00000012") { return 3; }
        print(format_f64(جيد::value + 1.0));
        print("\n");
        return 0;
    }
    return 4;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "first: invalid-number\nsecond: 42\n"
native: check 0; success / status 0; stdout "first: invalid-number\nsecond: 42\n"
scripted stdin lines: ["12x","41"]
نزّل المصدر افتح في المحرر
aspl check parse-float-en.aspl
aspl run parse-float-en.aspl
parse-float-mixed · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn ابدأ_الرئيسية() -> ص64 {
    اطبع("first: ").
    let سيئ: نتيجة<f32> = parse_f32(اقرأ_سطر()).
    إذا (سيئ::ok) { أرجع 1. }
    print(سيئ::الخطأ::code).
    print("\nsecond: ").
    دع جيد: result<ع64> = حلل_ع64(read_line()).
    if (جيد::نجاح) {
        إذا (format_f64(0.5) not match "0.5") { return 2. }
        if (نسق_ع32(1.0000000596046448) not match "1.00000012") { أرجع 3. }
        اطبع(نسق_ع64(جيد::value + 1.0)).
        print("\n").
        أرجع 0.
    }
    return 4.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "first: invalid-number\nsecond: 42\n"
native: check 0; success / status 0; stdout "first: invalid-number\nsecond: 42\n"
scripted stdin lines: ["12x","41"]
نزّل المصدر افتح في المحرر
aspl check parse-float-mixed.aspl
aspl run parse-float-mixed.aspl
الحدود المعيارية للإصدار

القوائم المحددة النوع

قيم القوائم المحددة النوع

في ASPL 0.7.0، تمثل قائمة<T>/list<T> تسلسلا قابلا للنمو بعناصر من نوع مخزن واحد دقيق، وتعمل في المتصفح والمضيف الأصلي. تستخدم معاملات الأنواع الأقواس الزاوية، وتبني الأقواس المربعة القيم. تقبل القوائم المتداخلة والسجلات والنتائج. يرفض الفحص عناصر unit ومساواة قائمتين كاملتين.

يستنتج الليترال غير الفارغ نوع عناصره دون تحويل عددي. يحتاج الليترال الفارغ نوعا متوقعا من الربط أو الإسناد أو المعامل أو الإرجاع. تقيم العناصر بترتيب كتابتها وتقبل فاصلة أخيرة.

مقطع توضيحي

دع فارغة: قائمة<ص64> = [];
دع قيم: قائمة<ص64> = [3, 4, 5,];

قراءة العناصر

تعيد طول/length: (list<T>) -> i64 عدد العناصر في زمن ثابت. تقرأ values[index] عنصرا بالقيمة. نوع الفهرس i64 ويبدأ من الصفر؛ يوقف الفهرس السالب أو المساوي للطول أو الأكبر منه التنفيذ بسبب list-index-out-of-bounds.

التعديل والنسخ المستقلة

تأخذ أضف/append موضع قائمة قابل للتعديل وقيمة من نوع عنصرها الدقيق، وتضيف القيمة وتعيد unit. يستبدل الإسناد المفهرس عنصرا موجودا ولا ينمي القائمة. تتطلب العمليتان ربطا جذريا من نوع متغير/var. لا يمثل ربط دع/let أو معامل دالة أو قيمة مؤقتة أو إسقاط حمولة نتيجة موضعا قابلا للتعديل.

ينسخ الإسناد والمعامل والإرجاع وحقول القيم المركبة القيم. لا يغير تعديل نسخة، بما فيها قائمة متداخلة، النسخ الأخرى. قد يشارك وقت التشغيل التخزين حتى التعديل، لكنه لا يعرض أسماء تشترك في قيمة قابلة للتعديل. يحل التعديل الفهارس من اليسار إلى اليمين مرة واحدة قبل تقييم القيمة الجديدة. الصيغة append(xs, xs[0]) صالحة.

التخزين والإخفاقات

تحفظ خانات القوائم العددية عروضها الدقيقة كما يوضح التخزين العددي. يختلف الطول عن السعة؛ لا توجد واجهة بايتات عامة أو ضمان لتخطيط C. تحسب القوائم المملوكة لوقت التشغيل وعناصرها المحتفظ بها ضمن ذاكرة التنفيذ. لا تعرض حدود الموارد أو فشل التخصيص تعديلا ملتزما جزئيا.

يرفض الفحص اختلاف أنواع العناصر والليترالات الفارغة بلا نوع وأهداف التعديل غير الصالحة وتعديل الربط الثابت. الوصول خارج النطاق توقف غير قابل للاسترداد، وليس نتيجة قابلة للاسترداد.

النطاق والأمثلة الكاملة

توسع القوائم MVP التاريخي. اقرأ كل صيغة موردة في القوائم المحددة النوع وتعديل القوائم، أو انتقل إلى السجلات ودلالات القيمة.

lists-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة المجموع(القيم: قائمة<ص64>) -> ص64 {
    أرجع القيم[0] + القيم[1] + القيم[2].
}
دالة ابدأ_الرئيسية() -> ص64 {
    دع القيم: قائمة<ص64> = [3, 4, 5].
    إذا (طول(القيم) لا يطابق 3) { أرجع 1. }
    إذا (المجموع(القيم) لا يطابق 12) { أرجع 2. }
    دع بايتات: قائمة<ط8> = [0, 255].
    إذا (طول(بايتات) لا يطابق 2 أو بايتات[0] لا يطابق 0 أو بايتات[1] لا يطابق 255) { أرجع 3. }
    دع كسور: قائمة<ع64> = [0.5].
    إذا (كسور[0] لا يطابق 0.5) { أرجع 4. }
    اطبع("12").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "12"
native: check 0; success / status 0; stdout "12"
نزّل المصدر افتح في المحرر
aspl check lists-ar.aspl
aspl run lists-ar.aspl
lists-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn المجموع(القيم: list<i64>) -> i64 {
    return القيم[0] + القيم[1] + القيم[2];
}
fn start_main() -> i64 {
    let القيم: list<i64> = [3, 4, 5];
    if (length(القيم) not match 3) { return 1; }
    if (المجموع(القيم) not match 12) { return 2; }
    let بايتات: list<ط8> = [0, 255];
    if (length(بايتات) not match 2 or بايتات[0] not match 0 or بايتات[1] not match 255) { return 3; }
    let كسور: list<f64> = [0.5];
    if (كسور[0] not match 0.5) { return 4; }
    print("12");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "12"
native: check 0; success / status 0; stdout "12"
نزّل المصدر افتح في المحرر
aspl check lists-en.aspl
aspl run lists-en.aspl
lists-mixed · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn total(القيم: list<ص64>) -> i64 {
    return القيم[0] + القيم[1] + القيم[2];
}
fn ابدأ_الرئيسية() -> ص64 {
    دع xs: قائمة<i64> = [3, 4, 5].
    if (طول(xs) not match 3) { return 1; }
    إذا (total(xs) not match 12) { أرجع 2. }
    let bytes: قائمة<u8> = [0, 255];
    إذا (length(bytes) not match 2 أو bytes[0] not match 0 أو bytes[1] not match 255) { return 3. }
    let fractions: list<ع64> = [0.5];
    if (fractions[0] not match 0.5) { أرجع 4. }
    print("12");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "12"
native: check 0; success / status 0; stdout "12"
نزّل المصدر افتح في المحرر
aspl check lists-mixed.aspl
aspl run lists-mixed.aspl
list-mutation-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    متغير xs: قائمة<ص64> = [1, 2].
    أضف(xs, 3).
    إذا (طول(xs) لا يطابق 3) { أرجع 1. }
    متغير نسخة: قائمة<ص64> = xs.
    نسخة[0] = 9.
    إذا (xs[0] لا يطابق 1) { أرجع 2. }
    إذا (نسخة[0] لا يطابق 9) { أرجع 3. }
    أضف(xs, xs[0]).
    إذا (طول(xs) لا يطابق 4) { أرجع 4. }
    إذا (xs[3] لا يطابق 1) { أرجع 5. }
    متغير nested: قائمة<قائمة<ص64>> = [[1], [2]].
    دع nested_copy: قائمة<قائمة<ص64>> = nested.
    nested[0][0] = 7.
    إذا (nested_copy[0][0] لا يطابق 1) { أرجع 6. }
    إذا (nested[0][0] لا يطابق 7) { أرجع 7. }
    متغير grown: قائمة<ص64> = [].
    متغير k = 0.
    طالما (k < 32) { أضف(grown, k * 2). k = k + 1. }
    إذا (طول(grown) لا يطابق 32) { أرجع 8. }
    إذا (grown[31] لا يطابق 62) { أرجع 9. }
    grown[0] = grown[31].
    إذا (grown[0] لا يطابق 62) { أرجع 10. }
    متغير بايتات: قائمة<ط8> = [0, 255].
    متغير نسخة_بايتات: قائمة<ط8> = بايتات.
    نسخة_بايتات[0] = 255.
    إذا (بايتات[0] لا يطابق 0 أو نسخة_بايتات[0] لا يطابق 255) { أرجع 11. }
    متغير كسور: قائمة<ع64> = [0.5].
    كسور[0] = 1.5.
    إذا (كسور[0] لا يطابق 1.5) { أرجع 12. }
    اطبع("32").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "32"
native: check 0; success / status 0; stdout "32"
نزّل المصدر افتح في المحرر
aspl check list-mutation-ar.aspl
aspl run list-mutation-ar.aspl
list-mutation-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    var xs: list<i64> = [1, 2];
    append(xs, 3);
    if (length(xs) not match 3) { return 1; }
    var نسخة: list<i64> = xs;
    نسخة[0] = 9;
    if (xs[0] not match 1) { return 2; }
    if (نسخة[0] not match 9) { return 3; }
    append(xs, xs[0]);
    if (length(xs) not match 4) { return 4; }
    if (xs[3] not match 1) { return 5; }
    var nested: list<list<i64>> = [[1], [2]];
    let nested_copy: list<list<i64>> = nested;
    nested[0][0] = 7;
    if (nested_copy[0][0] not match 1) { return 6; }
    if (nested[0][0] not match 7) { return 7; }
    var grown: list<i64> = [];
    var k = 0;
    while (k < 32) { append(grown, k * 2); k = k + 1; }
    if (length(grown) not match 32) { return 8; }
    if (grown[31] not match 62) { return 9; }
    grown[0] = grown[31];
    if (grown[0] not match 62) { return 10; }
    var بايتات: list<ط8> = [0, 255];
    var نسخة_بايتات: list<ط8> = بايتات;
    نسخة_بايتات[0] = 255;
    if (بايتات[0] not match 0 or نسخة_بايتات[0] not match 255) { return 11; }
    var كسور: list<f64> = [0.5];
    كسور[0] = 1.5;
    if (كسور[0] not match 1.5) { return 12; }
    print("32");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "32"
native: check 0; success / status 0; stdout "32"
نزّل المصدر افتح في المحرر
aspl check list-mutation-en.aspl
aspl run list-mutation-en.aspl
list-mutation-mixed · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    متغير xs: list<ص64> = [1, 2];
    append(xs, 3);
    إذا (طول(xs) not match 3) { أرجع 1. }
    var نسخة: قائمة<i64> = xs;
    نسخة[0] = 9;
    if (xs[0] not match 1) { return 2; }
    إذا (نسخة[0] not match 9) { أرجع 3. }
    append(xs, xs[0]);
    if (طول(xs) not match 4) { return 4; }
    إذا (xs[3] not match 1) { أرجع 5. }
    متغير nested: list<قائمة<ص64>> = [[1], [2]];
    let nested_copy: قائمة<list<ص64>> = nested;
    nested[0][0] = 7;
    if (nested_copy[0][0] not match 1) { return 6; }
    إذا (nested[0][0] not match 7) { أرجع 7. }
    var grown: list<i64> = [];
    متغير k = 0;
    while (k < 32) { أضف(grown, k * 2); k = k + 1. }
    if (length(grown) not match 32) { return 8; }
    if (grown[31] not match 62) { return 9; }
    grown[0] = grown[31];
    إذا (grown[0] not match 62) { أرجع 10. }
    var bytes: قائمة<u8> = [0, 255];
    متغير byte_copy: list<ط8> = bytes.
    byte_copy[0] = 255;
    if (bytes[0] not match 0 or byte_copy[0] not match 255) { return 11. }
    var fractions: قائمة<f64> = [0.5];
    fractions[0] = 1.5;
    إذا (fractions[0] not match 1.5) { أرجع 12. }
    print("32");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "32"
native: check 0; success / status 0; stdout "32"
نزّل المصدر افتح في المحرر
aspl check list-mutation-mixed.aspl
aspl run list-mutation-mixed.aspl
الحدود المعيارية للإصدار

السجلات ودلالات القيمة

أنواع السجلات المسماة

يدعم ASPL 0.7.0 سجل/record في المضيفين. صرح بالسجل على مستوى الملف بحقوله المسماة والمحددة النوع والمفصولة بفواصل. تقبل فاصلة أخيرة. تجمع أسماء السجلات قبل حل أنواع الحقول، فلا يهم ترتيب التصريحات.

السجلات اسمية. يمثل تصريحان بالحقول نفسها نوعين مختلفين، وتتبع الهوية وحدة المصدر التي تعرف النوع. يدعم المتصفح السجلات في ملف الدخول؛ تتطلب وحدات مصدر المستخدم تنفيذا أصليا.

مقطع توضيحي

سجل عنصر { اسم: نص, أعداد: قائمة<ص64> }

البناء والوصول إلى الحقول

ابن القيمة باسم النوع وقدم كل حقل مرة واحدة. تقيم الحقول بترتيب كتابتها. الحقول المجهولة أو المكررة أو المفقودة أو من نوع unit أخطاء مصدر. ترفض الأنواع العودية المباشرة وغير المباشرة، ومنها العودية عبر القوائم أو النتائج.

تقرأ :: اللاحقة حقلا بالقيمة، وتتسلسل مع فهارس القوائم بأسبقية أعلى من الحساب. تبقى أسماء حقول المستخدم بتهجئتها في المصدر العربي والإنجليزي والمختلط. حقول النتيجة ومعلومات الخطأ المدمجة فقط لها أسماء بديلة موردة باللغتين. ضع باني السجل المباشر في شرط إذا/if أو طالما/while بين قوسين لتمييز أقواسه عن الكتلة التالية.

مقطع توضيحي

دع قيمة = عنصر { اسم: "أدوات", أعداد: [2, 3] };
اطبع(قيمة::اسم);

النسخ والتعديل المتداخل

ينسخ الإسناد والمعامل والإرجاع قيم السجلات. للقائمة أو السجل المتداخل في النسخة دلالات قيمة أيضا. لا تغير حقلا أو عنصرا مفهرسا إلا عبر ربط جذري متغير/var. لا يمكن تعديل معامل أو ربط دع/let أو قيمة مؤقتة أو إسقاط حمولة نتيجة. انسخ الحمولة الناجحة إلى ربط جديد قابل للتعديل إذا احتجت إلى تغييرها.

ينسخ المثال الكامل حالة محلل، ويغير مؤشرها وحقل رمز متداخل، ثم يتحقق من بقاء القيم القديمة في الأصل. ويحمل أيضا سجلا داخل result<record-type>.

الإخفاقات والنطاق

لا تدعم مساواة سجلين كاملين. أخطاء الحقول والأنواع أخطاء مصدر؛ يوقف فهرس قائمة متداخلة غير صالح التنفيذ بسبب list-index-out-of-bounds، وقراءة فرع نتيجة خاطئ بسبب wrong-result-branch. توسع السجلات MVP التاريخي، ولا يعتمد سلوكها الحالي على تخطيط بنية C.

اقرأ كل صيغ السجلات والقوائم والنتائج القابلة للاسترداد.

records-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

سجل رمز { نوع: ص64, متن: نص, سطر: ص64, عمود: ص64 }
سجل حالة_محلل { رموز: قائمة<رمز>, مؤشر: ص64 }
دالة رمز_الحالة(حالة: حالة_محلل) -> رمز {
    أرجع حالة::رموز[حالة::مؤشر].
}
دالة ابدأ_الرئيسية() -> ص64 {
    دع زائد: رمز = رمز { نوع: 1, متن: "+" , سطر: 2, عمود: 7 }.
    إذا (زائد::نوع لا يطابق 1) { أرجع 1. }
    إذا (زائد::متن لا يطابق "+") { أرجع 2. }
    إذا (زائد::سطر لا يطابق 2) { أرجع 3. }
    إذا (زائد::عمود لا يطابق 7) { أرجع 4. }
    متغير حالة: حالة_محلل = حالة_محلل { رموز: [زائد], مؤشر: 0 }.
    إذا (رمز_الحالة(حالة)::متن لا يطابق "+") { أرجع 5. }
    متغير منقولة: حالة_محلل = حالة.
    منقولة::مؤشر = 1.
    إذا (حالة::مؤشر لا يطابق 0) { أرجع 6. }
    إذا (منقولة::مؤشر لا يطابق 1) { أرجع 7. }
    منقولة::رموز[0]::عمود = 9.
    إذا (حالة::رموز[0]::عمود لا يطابق 7) { أرجع 8. }
    إذا (منقولة::رموز[0]::عمود لا يطابق 9) { أرجع 9. }
    دع موجود: نتيجة<رمز> = نجاح(زائد).
    إذا (موجود::نجاح) {
        إذا (موجود::قيمة::سطر لا يطابق 2) { أرجع 10. }
    } وإلا {
        أرجع 11.
    }
    اطبع("3 tokens").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "3 tokens"
native: check 0; success / status 0; stdout "3 tokens"
نزّل المصدر افتح في المحرر
aspl check records-ar.aspl
aspl run records-ar.aspl
records-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

record رمز { نوع: i64, متن: string, سطر: i64, عمود: i64 }
record حالة_محلل { رموز: list<رمز>, مؤشر: i64 }
fn رمز_الحالة(حالة: حالة_محلل) -> رمز {
    return حالة::رموز[حالة::مؤشر];
}
fn start_main() -> i64 {
    let زائد: رمز = رمز { نوع: 1, متن: "+" , سطر: 2, عمود: 7 };
    if (زائد::نوع not match 1) { return 1; }
    if (زائد::متن not match "+") { return 2; }
    if (زائد::سطر not match 2) { return 3; }
    if (زائد::عمود not match 7) { return 4; }
    var حالة: حالة_محلل = حالة_محلل { رموز: [زائد], مؤشر: 0 };
    if (رمز_الحالة(حالة)::متن not match "+") { return 5; }
    var منقولة: حالة_محلل = حالة;
    منقولة::مؤشر = 1;
    if (حالة::مؤشر not match 0) { return 6; }
    if (منقولة::مؤشر not match 1) { return 7; }
    منقولة::رموز[0]::عمود = 9;
    if (حالة::رموز[0]::عمود not match 7) { return 8; }
    if (منقولة::رموز[0]::عمود not match 9) { return 9; }
    let موجود: result<رمز> = success(زائد);
    if (موجود::ok) {
        if (موجود::value::سطر not match 2) { return 10; }
    } else {
        return 11;
    }
    print("3 tokens");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "3 tokens"
native: check 0; success / status 0; stdout "3 tokens"
نزّل المصدر افتح في المحرر
aspl check records-en.aspl
aspl run records-en.aspl
records-mixed · ASPL 0.7.0

المتصفح والمضيف الأصلي

record Token { kind: ص64, text: نص, line: ص64, column: i64 }
سجل ParserState { tokens: قائمة<Token>, cursor: ص64 }
fn token_at(state: ParserState) -> Token {
    return state::tokens[state::cursor];
}
fn ابدأ_الرئيسية() -> ص64 {
    دع plus: Token = Token { kind: 1, text: "+", line: 2, column: 7 }.
    if (plus::kind not match 1) { return 1; }
    إذا (plus::text not match "+") { أرجع 2. }
    if (plus::line not match 2) { return 3; }
    إذا (plus::column not match 7) { أرجع 4. }
    var state: ParserState = ParserState { tokens: [plus], cursor: 0 };
    إذا (token_at(state)::text not match "+") { أرجع 5. }
    var moved: ParserState = state.
    moved::cursor = 1.
    if (state::cursor not match 0) { return 6; }
    إذا (moved::cursor not match 1) { أرجع 7. }
    moved::tokens[0]::column = 9.
    if (state::tokens[0]::column not match 7) { return 8; }
    إذا (moved::tokens[0]::column not match 9) { أرجع 9. }
    let found: نتيجة<Token> = success(plus).
    if (found::نجاح) {
        إذا (found::value::line not match 2) { أرجع 10. }
    } وإلا {
        return 11;
    }
    print("3 tokens");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "3 tokens"
native: check 0; success / status 0; stdout "3 tokens"
نزّل المصدر افتح في المحرر
aspl check records-mixed.aspl
aspl run records-mixed.aspl
الحدود المعيارية للإصدار

النتائج القابلة للاسترداد

قيم قابلة للاسترداد

في مضيفي ASPL 0.7.0، تحمل نتيجة<T>/result<T> حمولة ناجحة من النوع T أو معلومات_خطأ/error_info. النتيجة الفاشلة مسار تحكم عادي؛ لا تصدر تشخيصا أو موضع مصدر أو تتبع استدعاء، ولا توقف التنفيذ. تختار أنت إعادة المحاولة أو الاستمرار أو إرجاع حالة العملية.

تستنتج نجاح/success(value) نوع الحمولة أو تفحصه مقابل نوع النتيجة المتوقع. تنشئ success() قيمة result<unit>، أي نجاحا بلا حمولة. تأخذ إخفاق/failure(code, message) نصين وتحتاج نوع النتيجة المتوقع من تصريح أو إسناد أو معامل أو إرجاع. يفشل الفحص دون هذا السياق بسبب result-type-required.

افحص قبل قراءة الفرع

الحقل القيمة المستقبلة النوع
نجاح/ok result<T> bool
قيمة/value result<T> ناجحة T باستثناء unit
الخطأ/error result<T> فاشلة error_info
الرمز/code error_info string
الرسالة/message error_info string

استخدم :: اللاحقة وافحص ok قبل قراءة الفرع الموافق. توقف قراءة value عند الإخفاق أو error عند النجاح التنفيذ بسبب wrong-result-branch. لا تحتوي result<unit> على value قابلة للقراءة؛ محاولة قراءتها خطأ مصدر unit-value-not-allowed. ترفض مساواة نتيجتين كاملتين. يرتبط الوصول إلى الحقل أشد من الحساب ولا يترجم حقول سجلات المستخدم.

الرموز والرسائل والنسخ

اختر الفرع بحسب رموز الخطأ الثابتة مثل invalid-number وnumber-out-of-range وnot-found، لا بحسب صياغة الرسالة. تختار دالتك رموزها ورسائلها الخاصة. للنتائج وحمولاتها المحتفظ بها دلالات قيمة؛ إسقاطات النتائج للقراءة فقط. أسند الحمولة إلى ربط متغير/var لتعديل نسختك.

أنواع الإخفاق المختلفة

يعيد النص العددي غير الصالح وإخفاق الملف النصي المتوقع نتائج. تمنع الأنواع أو الحقول غير الصالحة نجاح الفحص. الفهرسة خارج النطاق والوصول إلى الفرع الخاطئ توقفان غير قابلين للاسترداد. حدود الذاكرة والزمن وفشل التخصيص والإيقاف نتائج تنفيذ منفصلة؛ ليست نتائج فاشلة يمكنك التقاطها.

تعرض أمثلة التحليل ودليل الملفات الاسترداد مع استمرار البرنامج. يشرح مرجع التشخيص أخطاء المصدر والتوقفات.

النطاق والأمثلة الكاملة

توسع النتائج القابلة للاسترداد MVP التاريخي. اقرأ كل صيغ النتائج وواجهة الملفات النصية لقراءة result<string> وكتابة result<unit>.

results-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة حي(الاسم: نص) -> نتيجة<نص> {
    إذا (الاسم يطابق "") {
        أرجع إخفاق("empty-name", "name was empty").
    }
    أرجع نجاح("hello " + الاسم).
}
دالة ابدأ_الرئيسية() -> ص64 {
    دع جيد: نتيجة<نص> = حي("aspl").
    إذا (جيد::نجاح) {
        اطبع(جيد::قيمة).
        اطبع(" ").
    } وإلا {
        أرجع 1.
    }
    دع سيئ: نتيجة<نص> = حي("").
    إذا (سيئ::نجاح) {
        أرجع 2.
    }
    اطبع(سيئ::الخطأ::الرمز).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "hello aspl empty-name"
native: check 0; success / status 0; stdout "hello aspl empty-name"
نزّل المصدر افتح في المحرر
aspl check results-ar.aspl
aspl run results-ar.aspl
results-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn حي(الاسم: string) -> result<string> {
    if (الاسم matches "") {
        return failure("empty-name", "name was empty");
    }
    return success("hello " + الاسم);
}
fn start_main() -> i64 {
    let جيد: result<string> = حي("aspl");
    if (جيد::ok) {
        print(جيد::value);
        print(" ");
    } else {
        return 1;
    }
    let سيئ: result<string> = حي("");
    if (سيئ::ok) {
        return 2;
    }
    print(سيئ::error::code);
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "hello aspl empty-name"
native: check 0; success / status 0; stdout "hello aspl empty-name"
نزّل المصدر افتح في المحرر
aspl check results-en.aspl
aspl run results-en.aspl
results-mixed · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn greet(name: string) -> نتيجة<string> {
    إذا (name matches "") {
        return إخفاق("empty-name", "name was empty");
    }
    return نجاح("hello " + name);
}
fn ابدأ_الرئيسية() -> i64 {
    دع good: result<string> = greet("aspl").
    if (good::نجاح) {
        اطبع(good::value);
        print(" ");
    } وإلا {
        return 1;
    }
    let bad: نتيجة<string> = greet("");
    إذا (bad::ok) {
        أرجع 2.
    }
    print(bad::الخطأ::code);
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "hello aspl empty-name"
native: check 0; success / status 0; stdout "hello aspl empty-name"
نزّل المصدر افتح في المحرر
aspl check results-mixed.aspl
aspl run results-mixed.aspl
الحدود المعيارية للإصدار

واجهة الملفات النصية

واجهة النص الكامل للملف

يدعم المتصفح وتنفيذ ASPL 0.7.0 الأصلي الدالتين المضمنتين. لا تحتاجان استيرادا أو علامة غير_آمن/unsafe. استخدام unsafe مع أي منهما خطأ مصدر unsafe-on-safe-call.

العملية التوقيع النجاح
اقرأ_ملف_نصي/read_text_file (string) -> result<string> الملف كله كنص UTF-8 صحيح
اكتب_ملف_نصي/write_text_file (string, string) -> result<unit> اكتمل الاستبدال الدقيق، بلا حمولة

تحفظ القراءة كل بايت محتوى، بما فيه BOM وCRLF وNUL والتطبيع. تعيد الملفات الفارغة success(""). يعيد UTF-8 غير الصالح invalid-utf8. تستخدم الكتابة بايتات UTF-8 الدقيقة للنص، ولا تضيف سطرا جديدا، وتستبدل المحتوى بدلا من إلحاقه. افحص ok قبل قراءة value أو error؛ لا تحتوي الكتابة الناجحة على value قابلة للقراءة.

يسمي عرض خرج المتصفح محارف التحكم غير المرئية مثل BOM وNUL، ويعرض CRLF كفاصل سطر. لا يغير هذا العرض الآمن محتوى الملف. استخدم تنزيل الملفات لمقارنة البايتات الدقيقة.

دعم المضيف لكل عملية

العملية المتصفح المضيف الأصلي
القراءة بايتات افتراضية مسماة في المسودة الحالية، بلا وصول إلى الشبكة أو القرص المحلي ملف عادي في نظام الملفات، بمسار نسبي إلى مجلد عمل العملية أو مسار مطلق
الكتابة إنشاء اسم افتراضي مسطح أو استبداله؛ يحفظ التنزيل الصريح البايتات إلى القرص تجهيز الملف في مجلد الوجهة ثم استبدال مدخل الوجهة الأخير ذريّا
المسارات اسم UTF-8 دقيق حساس لحالة الأحرف، من 1 حتى 255 بايتا نص غير فارغ بلا NUL، وفق حل مسارات Linux المعتاد
سقف الملف 1048576 بايتا، 1 MiB 16777216 بايتا، 16 MiB

لا تتبع المسارات الأصلية مجلد ملف المصدر. لا يوجد توسيع صدفة لـ~ أو المتغيرات أو أحرف البدل، ولا إنشاء ضمني للمجلدات الأم. تتبع القراءة حل نظام الملفات المعتاد بما فيه الروابط الرمزية، لكنها ترفض المجلدات والأجهزة والأنابيب بسبب not-regular-file. تستبدل الكتابة الناجحة المدخل الأخير، بما فيه الرابط الرمزي الأخير، بدلا من اتباعه. تحفظ الكتابة الفاشلة الوجهة السابقة؛ ولا يلغي توقف لاحق كتابة مكتملة.

ترفض أسماء المتصفح / والشرطة المائلة العكسية وNUL ومحارف التحكم U+0000 حتى U+001F وU+007F حتى U+009F والاسمين . و... لا توجد مجلدات. يقبل المخزن 64 ملفا و8388608 بايتا إجمالا. لكل تشغيل أيضا ميزانية نقل تحديثات كتابة قدرها 8388608 بايتا، تحسب بايتات الاسم والمحتوى و64 بايتا إضافيا لكل كتابة؛ تستهلك الاستبدالات المتكررة هذه الميزانية أيضا. تتبع القراءة والكتابة هذه القيود مستقلة عن لغة الشرح أو المصدر.

أخطاء الملف القابلة للاسترداد

الرمز المعنى والنطاق
invalid-path مسار فارغ أو يحوي NUL في المضيفين، أو اسم مسطح غير صالح في المتصفح
not-found ملف افتراضي مفقود، أو هدف قراءة أصلي أو مجلد كتابة أم مفقود
permission-denied إخفاق صلاحيات نظام الملفات الأصلي
not-regular-file قراءة أصلية لملف غير عادي أو الكتابة إلى مجلد
invalid-utf8 محتوى القراءة ليس UTF-8 صحيحا
file-too-large تجاوز القراءة أو الكتابة سقف الملف في المضيف
virtual-file-limit تجاوز عدد ملفات المتصفح أو مجموع البايتات أو ميزانية نقل تحديثات الكتابة
io-error إخفاق إدخال/إخراج آخر في المضيف
unsupported-host لا يوفر المضيف المضمن محولا لهذه العملية؛ يوفره كلا المضيفين المنشورين

هذه نتائج قابلة للاسترداد، لا تشخيصات مصدر أو توقفات. تبقى حدود الموارد والإلغاء وفشل التخصيص نتائج تنفيذ منفصلة. قد توقف قراءة الفرع الخاطئ التنفيذ. تبقى الكتابات الناجحة قبل إخفاق لاحق متاحة.

ملفات التشغيل المؤقتة والمصدر المحفوظ

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

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

استخدم زر التنزيل الصريح لكل ملف مستورد أو مكتوب بنجاح. يحفظ التنزيل اسمه وبايتاته الدقيقة، بما فيها بايتات مستوردة ليست UTF-8. لا يجعل استيراد helper.aspl كبيانات تشغيل منه وحدة مصدر أصلية، ولا يتيح استيراد المصدر في المتصفح.

الأمثلة الكاملة والنطاق

يحتاج مثال القراءة الافتراضي سطر إدخال واحدا missing.txt ولا يحتاج ملفا مستوردا. يطبع فرع not-found خطأ ويعيد 0. لا يحتاج مثال الكتابة إدخالا أو أصلا؛ ينشئ generated.txt أو يستبدله بالبايتات الدقيقة generated\n، ثم يطبع Output: saved\n.

اقرأ الدليل العملي قبل تجربة قراءة ناجحة أو حفظ البايتات المولدة. تحفظ صفحتا القراءة والكتابة الكاملتان الصيغتين العربية والإنجليزية المورّدتين. توسع هذه الواجهات MVP التاريخي؛ لا تعرف المواصفة المؤرشفة سلوكها الحالي في المضيفين.

read-file-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    اطبع("File: ").
    دع الاسم = اقرأ_سطر().
    دع المحتوى: نتيجة<نص> = اقرأ_ملف_نصي(الاسم).
    إذا (المحتوى::نجاح) {
        اطبع(المحتوى::قيمة).
    } وإلا {
        اطبع("error: ").
        اطبع(المحتوى::الخطأ::الرمز).
        اطبع("\n").
    }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "File: error: not-found\n"
native: check 0; success / status 0; stdout "File: error: not-found\n"
scripted stdin lines: ["missing.txt"]
نزّل المصدر افتح في المحرر
aspl check read-file-ar.aspl
aspl run read-file-ar.aspl
read-file-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    print("File: ");
    let الاسم = read_line();
    let المحتوى: result<string> = read_text_file(الاسم);
    if (المحتوى::ok) {
        print(المحتوى::value);
    } else {
        print("error: ");
        print(المحتوى::error::code);
        print("\n");
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "File: error: not-found\n"
native: check 0; success / status 0; stdout "File: error: not-found\n"
scripted stdin lines: ["missing.txt"]
نزّل المصدر افتح في المحرر
aspl check read-file-en.aspl
aspl run read-file-en.aspl
write-file-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    اطبع("Output: ").
    دع المحفوظ: نتيجة<وحدة> = اكتب_ملف_نصي("generated.txt", "generated\n").
    إذا (المحفوظ::نجاح) {
        اطبع("saved\n").
    } وإلا {
        اطبع("error: ").
        اطبع(المحفوظ::الخطأ::الرمز).
        اطبع("\n").
    }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Output: saved\n"
native: check 0; success / status 0; stdout "Output: saved\n"
نزّل المصدر افتح في المحرر
aspl check write-file-ar.aspl
aspl run write-file-ar.aspl
write-file-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    print("Output: ");
    let المحفوظ: result<unit> = write_text_file("generated.txt", "generated\n");
    if (المحفوظ::ok) {
        print("saved\n");
    } else {
        print("error: ");
        print(المحفوظ::error::code);
        print("\n");
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Output: saved\n"
native: check 0; success / status 0; stdout "Output: saved\n"
نزّل المصدر افتح في المحرر
aspl check write-file-en.aspl
aspl run write-file-en.aspl
الحدود المعيارية للإصدار

الدوال والقيم القابلة للاستدعاء

الدوال على المستوى الأعلى

تدعم ASPL 0.7.0 هذه القواعد في التنفيذ الأصلي والمتصفح. عرّف الدوال المساعدة على مستوى الملف باستخدام fn / دالة مع أنواع معلنة للمعاملات والنتيجة. الأسماء فريدة داخل وحدة المصدر. لا تدعم اللغة التحميل الزائد أو التعريفات المتداخلة أو الإغلاقات أو المعاملات الافتراضية أو الدوال ذات العدد المتغير من المعاملات. لا يمكن لتعريف أن يحل محل اسم مدمج. ضع العبارات التنفيذية داخل الدوال.

ترتيب التعريفات لا يهم، ويجوز الاستدعاء الذاتي. تقيّم الاستدعاءات الوسائط من اليسار إلى اليمين وتمرر القيم بالنسخ. المعاملات غير قابلة للتغيير. تحتفظ القوائم والسجلات بدلالات النسخ عند الاستدعاء. يجب أن يعيد كل مسار في دالة غير unit قيمة من نوع النتيجة المعلن. تعني unit عدم وجود قيمة لتخزينها أو تمريرها.

مقطع توضيحي

دالة طبق(عمل: دالة(ص64) -> ص64, قيمة: ص64) -> ص64 {
    أرجع عمل(قيمة).
}

القيم القابلة للاستدعاء المعلنة النوع

الدالة المسماة على المستوى الأعلى قيمة أيضا. يصف fn(i64) -> i64 / دالة(ص64) -> ص64 معاملا واحدا ونتيجة، دون أسماء المعاملات. يصف fn() -> unit قيمة قابلة للاستدعاء بلا معاملات ولا نتيجة. يجب أن تتطابق أنواع المعاملات والنتيجة كاملة، ولا يحوّل الإسناد توقيع الدالة.

انسخ القيمة أو مررها أو أعدها أو استدعها أو خزّنها في قائمة أو سجل أو نتيجة. يمكن أن يأتي الاستدعاء بعد حقل أو فهرس قائمة أو دالة تعيد قيمة قابلة للاستدعاء، مثل carrier::callback(38) أو saved[0](38) أو choose()(38). لا تلتقط الدالة بيئة محلية. تقارن matches / يطابق وnot matches / لا يطابق هوية الدالة بين أنواع استدعاء متوافقة. لا تدعم هذه القيم الترتيب أو الحساب.

الإتاحة وقيود المدخل

تشير القيم القابلة للاستدعاء إلى دوال المستخدم فقط. المدخل المحجوز start_main / ابدأ_الرئيسية والدوال المدمجة والتعريفات الأجنبية ودوال المكتبات المورّدة ليست قيما قابلة للاستدعاء. لا يمكن استدعاء المدخل من المصدر أيضا.

تعريفات وحدات المصدر الأصلية خاصة افتراضيا. يفشل المرجع المباشر lib::hidden بسبب private-member. يجوز أن تعيد الدالة المصدّرة lib::choose() قيمة تشير إلى مساعدها الخاص، ويصح استلام هذه القيمة واستدعاؤها. يجب ألا تكشف التواقيع المصدّرة سجلا خاصا، حتى داخل قيمة قابلة للاستدعاء أو قائمة أو نتيجة. هذا الفشل هو private-type-exposure.

اقرأ وحدات المصدر والتصدير لقواعد الإتاحة الأصلية. يدعم المتصفح ملف مصدر واحدا ولا يحمّل وحدات مصدر المستخدم.

الإخفاقات والأمثلة الكاملة

يؤدي عدد الوسائط الخاطئ إلى argument-count-mismatch، ويؤدي نوع وسيط أو نتيجة أو قيمة استدعاء غير متوافق إلى type-mismatch. يؤدي مسار بلا إرجاع في دالة غير وحدة إلى missing-return. محاولة أخذ المدخل كقيمة تؤدي إلى undefined-name. هذه أخطاء فحص، منفصلة عن فخاخ الحساب أو حد الاستدعاء الذاتي أثناء التنفيذ.

يعيد مثال المضروب حالة عملية 120 دون خرج. هذا تنفيذ ناجح لغويا بحالة عملية غير صفرية، فتعدّ الصدفة الأمر غير ناجح. يطبع مثال القيم القابلة للاستدعاء 42 ويعيد 0.

راجع مصادر الدوال ومصادر القيم القابلة للاستدعاء والفحص والتشغيل والبناء الأصلي.

functions-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة مضروب(القيمة: ص64) -> ص64 {
    إذا القيمة <= 1 {
        أرجع 1.
    }
    أرجع القيمة * مضروب(القيمة - 1).
}

دالة ابدأ_الرئيسية() -> ص64 {
    أرجع مضروب(5).
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 120; stdout ""
native: check 0; success / status 120; stdout ""
نزّل المصدر افتح في المحرر
aspl check functions-ar.aspl
aspl run functions-ar.aspl
functions-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn مضروب(القيمة: i64) -> i64 {
    if القيمة <= 1 {
        return 1;
    }
    return القيمة * مضروب(القيمة - 1);
}

fn start_main() -> i64 {
    return مضروب(5);
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 120; stdout ""
native: check 0; success / status 120; stdout ""
نزّل المصدر افتح في المحرر
aspl check functions-en.aspl
aspl run functions-en.aspl
callable-values-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة زيادة(قيمة: ص64) -> ص64 { أرجع قيمة + 4. }
دالة اختر() -> دالة(ص64) -> ص64 { أرجع زيادة. }
سجل حامل { استدعاء: دالة(ص64) -> ص64 }
دالة طبق(عمل: دالة(ص64) -> ص64, قيمة: ص64) -> ص64 { أرجع عمل(قيمة). }
دالة ابدأ_الرئيسية() -> ص64 {
    دع محفوظ: قائمة<دالة(ص64) -> ص64> = [اختر()].
    دع مغلف: نتيجة<دالة(ص64) -> ص64> = نجاح(محفوظ[0]).
    دع عنصر = حامل { استدعاء: مغلف::قيمة }.
    إذا عنصر::استدعاء لا يطابق زيادة { أرجع 1. }
    اطبع(نسق_ص64(طبق(عنصر::استدعاء, 38)) + "\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "42\n"
native: check 0; success / status 0; stdout "42\n"
نزّل المصدر افتح في المحرر
aspl check callable-values-ar.aspl
aspl run callable-values-ar.aspl
callable-values-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn increment(value: i64) -> i64 { return value + 4; }
fn choose() -> fn(i64) -> i64 { return increment; }
record Carrier { callback: fn(i64) -> i64 }
fn apply(action: fn(i64) -> i64, value: i64) -> i64 { return action(value); }
fn start_main() -> i64 {
    let saved: list<fn(i64) -> i64> = [choose()];
    let wrapped: result<fn(i64) -> i64> = success(saved[0]);
    let carrier = Carrier { callback: wrapped::value };
    if carrier::callback not matches increment { return 1; }
    print(format_i64(apply(carrier::callback, 38)) + "\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "42\n"
native: check 0; success / status 0; stdout "42\n"
نزّل المصدر افتح في المحرر
aspl check callable-values-en.aspl
aspl run callable-values-en.aspl
الحدود المعيارية للإصدار

وحدات المصدر والاستيراد والتصدير

المضيف وصيغة الاستيراد

هذا عقد وحدات المصدر الأصلية في ASPL 0.7.0. ثبّت الأدوات الأصلية أولا. ملفات المتصفح الافتراضية بيانات تشغيل ولا توفر محمّل وحدات مصدر، حتى إذا انتهت أسماؤها بـ.aspl أو .لبات. للمكتبات المورّدة مثل core::http وcore::raylib وcore::c دعم أصلي خاص، وهي منفصلة عن ملفات المستخدم ومكتبات C المشتركة.

مقطع توضيحي

import helpers.aspl as lib;
استورد services/معالجات.لبات بسم خدمة.

استخدم import / استورد ومسارا نسبيا ينتهي بـ.aspl أو .لبات، مع نطاق أسماء اختياري باستخدام as / بسم. المسارات أوصاف غير محاطة بعلامات اقتباس. اهرب المسافة باستخدام \ . يُرفض مسار الاستيراد المطلق. يبدأ الحل من مجلد الملف المستورِد، بما فيه الاستيرادات المتداخلة، وليس مجلد عمل العملية. دون اسم بديل يجب أن يكون اسم الملف بلا امتداد معرّف نطاق صالحا. استخدم اسما بديلا لملف مثل my-file.aspl.

يقبل ASPL 0.7.0 \ي{...} مع \u{...} داخل مسارات الاستيراد، بأبجديات الأرقام وحدود القيم العددية نفسها في محارف هروب النصوص. ترفض مسارات الاستيراد U+0000. تبقى تهجئات المسافات وعلامات ترقيم ASCII المهربة كما هي؛ لا تقبل المسارات محارف الهروب النصية القصيرة مثل \n و\س. تحتفظ ملفات الإصدار المنشور 0.6.0 بصيغة هروب المسارات الأصلية.

نطاقات الأسماء والتصدير

استخدم lib::answer() لاستدعاء تعريف مصدّر من استيراد مباشر. لا ينفذ الاستيراد شفرة ولا يدمج التعريفات في المستورِد ولا يتيح نطاقات الاستيرادات غير المباشرة. يجوز لوحدات مختلفة استخدام الاسم الخاص نفسه. تشير الاستيرادات المتكررة للملف الفعلي نفسه إلى هويات الدوال والسجلات نفسها، حتى عبر أسماء بديلة مختلفة. يعرّف ملفان مختلفان سجلين مختلفين اسميا ولو تطابق اسماهما.

الدوال والسجلات والتعريفات الأجنبية خاصة افتراضيا. ضع share / شارك قبل التعريف المصدّر. تحتفظ أسماء المستخدم المصدّرة بكتابتها ولا تكتسب أسماء عربية وإنجليزية بديلة. يظل الاستدعاء الأجنبي المصدّر بحاجة إلى علامة unsafe الصريحة. لا يجوز للتواقيع المصدّرة وحقول السجلات كشف أنواع خاصة، حتى داخل أنواع الاستدعاء أو القوائم أو النتائج المتداخلة. صدّر السجل المطلوب أيضا أو غيّر التوقيع العام.

مقطع توضيحي

شارك دالة جواب() -> ص64 { أرجع 42. }
شارك سجل رد { قيمة: ص64 }

يُرفض share import بسبب shared-import، فلا يوجد إعادة تصدير. استورد مباشرة كل نطاق تستخدم اسمه. راجع فشل التعريف الخاص وبرنامج الوحدات المصحح.

المدخل وقيود شبكة الاستيراد

يعرّف ملف المصدر الجذري وحده start_main / ابدأ_الرئيسية بلا معاملات وبحالة عملية من نوع i64. يجب ألا تعرّف الملفات المستوردة مدخلا، ويرفضها imported-entry. لا يجوز تصدير مدخل الجذر، ويرفض ذلك shared-entry. لا يمكن استدعاء أسماء المدخل أو تخزينها كقيم قابلة للاستدعاء.

تفشل الدورات بسبب import-cycle، وتصادمات النطاقات بسبب namespace-collision، والملفات الغائبة بسبب missing-file. الحد الأصلي 1024 وحدة مصدر، وأطول سلسلة استيراد 256 وصلة. يُفحص كل تعريف مستورد، بما فيه المساعد غير المستخدم، فلا يخفي استيراد الملف أخطاء أنواعه.

الفحص والتشغيل والبناء

احتفظ بالمدخل وكل ملفات المصدر المعلنة وفق ترتيب المسارات النسبي الموثق. لا يحتاج هذا المثال إلى ملف بيانات:

aspl check main.ar.aspl
aspl run main.ar.aspl
aspl build -o module-program main.ar.aspl
./module-program

يطبع مثال الوحدات 42 ثم LF ويعيد 0. يتضمن البرنامج الأصلي المبني البرنامج المفحوص والآلة الافتراضية، ويعمل بعد إزالة ملفات مصدره. قد يظل محتاجا إلى مكتبات مشتركة أو ملفات بيانات يستخدمها أثناء التشغيل.

اقرأ الدليل العملي وإتاحة القيم القابلة للاستدعاء ومراحل أوامر Linux ومجموعة البرامج الكاملة.

source-modules-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد helpers.aspl بسم مكتبة.
دالة ابدأ_الرئيسية() -> ص64 {
    دع جواب: مكتبة::Reply = مكتبة::Reply { value: 38 }.
    دع عمل: دالة(ص64) -> ص64 = مكتبة::choose().
    إذا عمل(جواب::value) لا يطابق مكتبة::answer() { أرجع 1. }
    اطبع(نسق_ص64(عمل(جواب::value)) + "\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "42\n"
نزّل المصدر
aspl check source-modules-ar.aspl
aspl run source-modules-ar.aspl
source-modules-en · ASPL 0.7.0

المضيف الأصلي فقط

import helpers.aspl as lib;
fn start_main() -> i64 {
    let reply: lib::Reply = lib::Reply { value: 38 };
    let action: fn(i64) -> i64 = lib::choose();
    if action(reply::value) not matches lib::answer() { return 1; }
    print(format_i64(action(reply::value)) + "\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "42\n"
نزّل المصدر
aspl check source-modules-en.aspl
aspl run source-modules-en.aspl
source-module-private-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد helpers.aspl بسم مكتبة.
دالة ابدأ_الرئيسية() -> ص64 { أرجع مكتبة::answer(). }

النتائج المتوقعة والخرج الحرفي

native: check 1; source-error / status 1 / private-member; stdout ""
نزّل المصدر
aspl check source-module-private-ar.aspl
source-module-private-en · ASPL 0.7.0

المضيف الأصلي فقط

import helpers.aspl as lib;
fn start_main() -> i64 { return lib::answer(); }

النتائج المتوقعة والخرج الحرفي

native: check 1; source-error / status 1 / private-member; stdout ""
نزّل المصدر
aspl check source-module-private-en.aspl
الحدود المعيارية للإصدار

واجهة HTTP وحدودها وأخطاؤها

الخدمة الأصلية ومالكو الجلسات

المضيف الأصلي فقط، ASPL 0.7.0 المنشور. اقرأ دليل HTTP ومجموعة الأمثلة ومتطلبات المضيف. يرفض المتصفح والتضمين الخاص HTTP قبل التنفيذ بالسبب unsupported-supplied-library-profile.

تدير اخدم المعالجات حتى الإغلاق وتعيد نتيجة<وحدة> بعد تحرير الخادم والعمل التابع. تكمل ابدأ البدء وتعيد نتيجة<جلسة<C,S>>، ويكون المستمعون جاهزين عند نجاحها. لا تعمل المعالجات إلا حين يستدعي التطبيق تقدم؛ لا تشغل صيانة النقل أثناء الإدخال أو الرسم معالجات مصدر. تخضع تقدم لميزانية محدودة. تجمّد محاولة الشبكة المجتازة للتحقق اضبط، وتستهلك محاولة الخدمة المجتازة للتحقق فرصة الخدمة الوحيدة حتى إن فشل الربط أو TLS بعدها. لا يستهلك رفض التحقق الخالص الفرصة ولا يجمد الإعدادات. تعمل طلبات العميل قبل الخدمة وداخلها وبعدها.

جلسة<C,S> / Session<C,S> مالك مدار معتم. تشترك نسخه في المورد الأصلي والإغلاق. يمكن الاحتفاظ به في قيم التطبيق، لكنه لا يدخل وسيطَي نوع الإعدادات والحالة في أي عمق. لا منشئ أو حقول عامة أو مساواة أو تحويل C عادي. يغلق فقدان آخر نسخة قابلة للوصول المورد، وينهي التنفيذ صلاحية المالكين أيضا. تبقى الذاكرة الأصلية محسوبة حتى سكون التحرير. تحتفظ نسخ الإعدادات والحالة بالمقابض المدارة نفسها، ولا تنسخ الموارد الأصلية المتغيرة.

عمليات التطبيق فقط هي ابدأ وتقدم وأوقف_الجلسة وأغلق_الجلسة وإعداد_الجلسة وحالة_الجلسة واستبدل_حالة_الجلسة والتقط_حالة_الجلسة واستبدل_حالة_الجلسة_إن_كانت_حالية. تأخذ عمليات المعالج سياق استدعائه: اقرأ_إعدادات واقرأ_حالة واستبدل_حالة والتقط_الحالة واستبدل_الحالة_إن_كانت_حالية وأوقف وتحقق_استجابة. يرفض المدقق استدعاءات التطبيق على مسار معالج حتى عبر دوال مساعدة. ينتهي السياق مع استدعائه ولا يخرج منه أو يدخل المجاميع. في برامج رايليب تكون الإعداد والطلب والخدمة والبدء والتقدم والإيقاف والإغلاق خارج الإطار، وتسمح دوال نسخ إعدادات التطبيق وحالته داخل الإطار. تعيد العمليات الممنوعة داخل إطار فعال http.invalid_order. يعيد سياق التطبيق غير الصالح http.invalid_context.

يحوي حالة_جلسة / SessionStatus الثوابت جلسة_تعمل / SESSION_RUNNING وجلسة_تستكمل_الإغلاق / SESSION_DRAINING وجلسة_مغلقة / SESSION_CLOSED. تطلب أوقف_الجلسة التصريف؛ استمر في تقدم حتى الإغلاق. تنهي أغلق_الجلسة الصلاحية وتحرر المالك وتبطل كل نسخه. يعيد تقدم المغلقة حالتها المغلقة وينجح تكرار الإيقاف والإغلاق. تعيد دوال حالة المغلقة وإعداداتها http.closed_session. يبقى فشل المضيف المحرر بأمان مسجلا. فشل التحرير النهائي ليس نتيجة قابلة للاسترداد.

تعيد اقرأ_حالة وحالة_الجلسة قيما منسوخة؛ لا ينشر تعديلها شيئا. يستبدل النشر غير المشروط الحالة كاملة. للنوع لقطة_حالة<S> / StateSnapshot<S> حقل قيمة / value للقراءة فقط وهوية جلسة وإصدار خفيان. تبقى اللقطة بعد الإغلاق ولا تمنح صلاحية السياق. يزيد كل نشر ناجح الإصدار. يعيد الاستبدال الشرطي نجاحا بقيمة صواب للقطة الحالية، ونجاحا بقيمة خطأ للقطة قديمة من الجلسة نفسها، أو فشلا بالرمز http.invalid_argument للقطة جلسة أخرى. القراءة والانتظار لطلب صادر ثم الاستبدال ليست ذرية؛ استخدم النشر الشرطي لكشف التغييرات أثناء الانتظار. راجع مثال الجلسة.

الأنواع والدوال والقيم الافتراضية

تأخذ وجهة<C,S> / Route<C,S> وموجه<C,S> / Router<C,S> و سياق<C,S> / Context<C,S> وسيطَي نوع محددين للتطبيق. يقبل C وS القيم القابلة للتخزين المسموحة، بما فيها السجلات والقوائم والنتائج والمخازن والمقابض والتسجيلات المدارة. يستبعد السياق الفعلي وقيم الدوال المكشوفة في كل عمق، بما فيه بيانات التسجيل. هذه عائلات توفرها المكتبة وليست أنواعا عامة يعرفها المستخدم. إذا لم يمكن استنتاج الوسيطين فاكتبهما صراحة، مثل ويب::أنشئ_موجه<منطقي,ص64>([]). يجب أن تستخدم الوجهات والمعالجات والإعدادات والحالة هويتَي النوع نفسيهما. يشترك استيراد الوحدة القانونية نفسها في هوية أنواعها ودوالها.

المعالج دالة مستخدم مسماة على المستوى الأعلى بتوقيع دالة(طلب_وارد, سياق<C,S>) -> استجابة_خادم. مرر اسمها مثل handlers::handle دون استدعائها. لا تلتقط قيمة الدالة بيئة محلية. صدّر تعريفات الوحدة عبر شارك / share وتبقى بقية الأسماء خاصة. يمكن تخزين قيم الدوال العادية وتمريرها وإعادتها ومقارنتها بكلمات المساواة. يفحص المدقق كل الأهداف الممكنة عبر الوحدات ويرفض المسارات غير الآمنة أو الحاجبة. لا تجعل دالة تغليف استدعاء C عاديا أو قراءة سطر أو ملف حاجبة صالحة لمسار المعالج.

السجلات التالية قيم عادية. تبقى بايتات الرسائل والترويسات صالحة بعد انتهاء الاتصال أو الخدمة. لا منشئ أو حقول عامة للسياق، ولا يدخل المجاميع أو يخرج من استدعائه أو يقارن أو يعبر استدعاء C عاديا. الوجهة والموجه قيمتان معتمتان يمكن الاحتفاظ بهما دون حقول عامة أو مقابس حية. حقل نجاح النتيجة نجاح / ok، ومحتواها قيمة / value، وخطؤها الخطأ / error، ورمزه الرمز / code. اقرأ المحتوى بعد فحص النجاح. الرسائل البشرية قد تتغير.

أعلام خيارات العميل الثلاثة خطأ افتراضيا ومسار CA فارغ. قائمة مستمعي إعدادات الخادم فارغة افتراضيا ويجب إكمالها قبل الخدمة. يأخذ منشئ المستمع عنوانا ومنفذا 1..65535 ويعيد نقلا عاديا ومساري TLS فارغين. يبدأ منشئ طلب العميل بترويسات ومتن فارغين، ومنشئ الاستجابة بترويسات فارغة وعلم طول تمثيل غير مفعّل وطول صفر. تضبط الاستجابة النصية Content-Type المحدد وبايتات UTF-8 الدقيقة. لا معاملات اختيارية أو تحويل JSON ضمني.

تتولد الجداول التالية من كتالوج التعريفات العامة المراجع. كتابة الأنواع مشتركة بين الصفحتين. الأحجام والأعداد ص64، والمدد ص64 بالمللي ثانية. حدود المجالات مشمولة ولا قيمة تعني بلا حد. MiB يساوي 1048576 بايت.

ProgressBudget / ميزانية_تقدم

English / العربية Type / النوع Default / الافتراضي Range / المجال
max_instructions / حد_التعليمات i64 4096 1..1048576
active_ms / زمن_العمل_مللي i64 2 1..1000
wait_ms / زمن_الانتظار_مللي i64 0 0..1000

Header / ترويسة

English / العربية Type / النوع
name / اسم string
value / قيمة list<u8>

QueryEntry / عنصر_استعلام

English / العربية Type / النوع
name / اسم string
value / قيمة string
has_equals / له_يساوي bool

ClientRequest / طلب_عميل

English / العربية Type / النوع
method / طريقة string
url / رابط string
headers / ترويسات list<Header>
body / متن list<u8>

IncomingRequest / طلب_وارد

English / العربية Type / النوع
method / طريقة string
target / هدف string
authority / جهة string
path / مسار string
query / استعلام string
has_query / له_استعلام bool
headers / ترويسات list<Header>
trailers / ترويسات_ختامية list<Header>
body / متن list<u8>
tls / اتصال_مشفر bool
peer_address / عنوان_الطرف string
local_address / عنوان_محلي string
peer_port / منفذ_الطرف i64
local_port / منفذ_محلي i64
listener_index / فهرس_مستمع i64

ClientResponse / استجابة_عميل

English / العربية Type / النوع
status / حالة i64
headers / ترويسات list<Header>
trailers / ترويسات_ختامية list<Header>
body / متن list<u8>
final_url / رابط_نهائي string
redirect_count / عدد_تحويلات i64
gzip_decoded / فك_ضغط_غزيب bool
encoded_body_bytes / بايتات_متن_مرمز i64

ServerResponse / استجابة_خادم

English / العربية Type / النوع
status / حالة i64
headers / ترويسات list<Header>
body / متن list<u8>
has_representation_length / له_طول_تمثيل bool
representation_length / طول_تمثيل i64

Listener / مستمع

English / العربية Type / النوع
address / عنوان string
port / منفذ i64
tls / اتصال_مشفر bool
certificate_file / ملف_شهادة string
key_file / ملف_مفتاح string

ClientOptions / خيارات_عميل

English / العربية Type / النوع
limits / حدود MessageLimits
timeouts / مهل Timeouts
follow_redirects / اتبع_تحويلات bool
decode_gzip / فك_غزيب bool
use_private_ca / استخدم_مرجع_خاص bool
ca_file / ملف_مرجع string

ServerConfig / إعدادات_خادم

English / العربية Type / النوع
listeners / مستمعون list<Listener>
limits / حدود MessageLimits
timeouts / مهل Timeouts

RuntimeConfig / إعدادات_تنفيذ_ويب

English / العربية Type / النوع Default / الافتراضي Range / المجال
vm_memory_bytes / بايتات_ذاكرة_آلة i64 268435456 1048576..1073741824
backend_memory_bytes / بايتات_ذاكرة_خلفية i64 134217728 1048576..1073741824
inbound_connections / اتصالات_واردة i64 128 1..4096
outbound_connections / اتصالات_صادرة i64 32 1..1024
idle_client_connections / اتصالات_عميل_خاملة i64 16 1..outbound_connections / اتصالات_صادرة
queued_requests / طلبات_منتظرة i64 32 1..1024
live_handlers / معالجات_حية i64 32 1..1024
outbound_operations / عمليات_صادرة i64 32 1..1024
max_listeners / أقصى_مستمعين i64 8 1..64
max_routes / أقصى_وجهات i64 1024 1..16384
trust_configurations / إعدادات_ثقة i64 16 1..128
tls_file_bytes / بايتات_ملف_تشفير i64 1048576 1..16777216
query_bytes / بايتات_استعلام i64 8192 1..1048576
query_entries / عدد_عناصر_استعلام i64 1024 1..16384

MessageLimits / حدود_رسالة

English / العربية Type / النوع Default / الافتراضي Range / المجال
target_bytes / بايتات_هدف i64 8192 1..1048576
header_bytes / بايتات_ترويسات i64 32768 1..1048576
header_fields / عدد_ترويسات i64 100 1..4096
chunk_line_bytes / بايتات_سطر_جزء i64 1024 1..65536
body_bytes / بايتات_متن i64 16777216 1..1073741824
decoded_body_bytes / بايتات_متن_مفكوك i64 16777216 1..1073741824
informational_responses / عدد_استجابات_تمهيدية i64 8 1..64
max_redirect_hops / أقصى_تحويلات i64 5 0..32

Timeouts / مهل

English / العربية Type / النوع Default / الافتراضي Range / المجال
total_ms / مهلة_كلية i64 30000 1..86400000
connect_ms / مهلة_اتصال i64 10000 1..86400000
tls_ms / مهلة_تشفير i64 10000 1..86400000
headers_ms / مهلة_ترويسات i64 10000 1..86400000
body_ms / مهلة_متن i64 30000 1..86400000
write_ms / مهلة_كتابة i64 10000 1..86400000
idle_ms / مهلة_خمول i64 30000 1..86400000
drain_ms / مهلة_تصريف i64 5000 1..86400000
cleanup_ms / مهلة_تنظيف i64 1000 1000..86400000

Functions / الدوال

English / العربية Signature / التوقيع
progress_budget / ميزانية_التقدم () -> ProgressBudget
runtime_config / إعدادات_تنفيذ () -> RuntimeConfig
message_limits / حدود_رسائل () -> MessageLimits
timeouts / مهل_افتراضية () -> Timeouts
client_options / خيارات_طلب () -> ClientOptions
server_config / إعدادات_خدمة () -> ServerConfig
listener / أنشئ_مستمع (string, i64) -> result<Listener>
configure / اضبط (RuntimeConfig) -> result<unit>
client_request / أنشئ_طلب (string, string) -> result<ClientRequest>
request / اطلب (ClientRequest, ClientOptions) -> result<ClientResponse>
response / أنشئ_استجابة (i64, list<u8>) -> result<ServerResponse>
text_response / استجابة_نصية (i64, string, string) -> result<ServerResponse>
encode_utf8 / رمز_نص (string) -> list<u8>
decode_utf8 / فك_نص (list<u8>) -> result<string>
header / أنشئ_ترويسة (string, list<u8>) -> result<Header>
text_header / ترويسة_نصية (string, string) -> result<Header>
header_values / قيم_ترويسة (list<Header>, string) -> result<list<list<u8>>>
query_entries / عناصر_استعلام (string) -> result<list<QueryEntry>>
query_values / قيم_استعلام (list<QueryEntry>, string) -> list<string>
snapshot_state / التقط_الحالة (Context<C,S>) -> StateSnapshot<S>
snapshot_session_state / التقط_حالة_الجلسة (Session<C,S>) -> result<StateSnapshot<S>>
replace_session_state / استبدل_حالة_الجلسة (Session<C,S>, S) -> result<unit>
replace_state_if_current / استبدل_الحالة_إن_كانت_حالية (Context<C,S>, StateSnapshot<S>, S) -> result<bool>
replace_session_state_if_current / استبدل_حالة_الجلسة_إن_كانت_حالية (Session<C,S>, StateSnapshot<S>, S) -> result<bool>
start / ابدأ (ServerConfig, Router<C,S>, C, S) -> result<Session<C,S>>
session_config / إعداد_الجلسة (Session<C,S>) -> result<C>
session_state / حالة_الجلسة (Session<C,S>) -> result<S>
close_session / أغلق_الجلسة (Session<C,S>) -> result<unit>
progress / تقدم (Session<C,S>, ProgressBudget) -> result<SessionStatus>
stop_session / أوقف_الجلسة (Session<C,S>) -> result<unit>
route / أنشئ_وجهة (string, string, fn(IncomingRequest, Context<C,S>) -> ServerResponse) -> result<Route<C,S>>
router / أنشئ_موجه (list<Route<C,S>>) -> result<Router<C,S>>
with_catch_all / أضف_معالج_عام (Router<C,S>, fn(IncomingRequest, Context<C,S>) -> ServerResponse) -> result<Router<C,S>>
serve / اخدم (ServerConfig, Router<C,S>, C, S) -> result<unit>
read_config / اقرأ_إعدادات (Context<C,S>) -> C
read_state / اقرأ_حالة (Context<C,S>) -> S
replace_state / استبدل_حالة (Context<C,S>, S) -> unit
stop / أوقف (Context<C,S>) -> unit
check_response / تحقق_استجابة (Context<C,S>, IncomingRequest, ServerResponse) -> result<unit>

البايتات والترويسات والاستعلام

المتن قيمة كاملة مخزنة في قائمة<ط8>. ينسخ رمز_نص UTF-8 بدقة، ويرفض فك_نص النص غير الصالح بالرمز http.invalid_utf8. لا يحذفان BOM أو NUL ولا يطبّعان Unicode أو يخمنان الترميز أو يستبدلان البايتات السيئة. JSON نص ونوع محتوى صريحان، ولا توفر المكتبة محللا أو مولّدا له.

الترويسات حقول مرتبة قابلة للتكرار، بأسماء ASCII token وقيم بايتات. تقبل القيم HTAB وASCII القابل للطباعة و0x80..0xFF، وترفض NUL وCR وLF وDEL وبقية التحكم. يحذف التحليل SP وHTAB المحيطين ويحتفظ بالداخل والترتيب وحالة أحرف الاسم. يعيد قيم_ترويسة كل المطابقات بالترتيب دون اعتبار لحالة الاسم، ولا يجمعها بفواصل أو يفك نصها. تبقى Set-Cookie المكررة منفصلة، وكذلك الترويسات الختامية عن الأولى.

لا يضبط التطبيق Content-Length أو Transfer-Encoding أو Connection أو Keep-Alive أو Proxy-Connection أو TE أو Trailer أو Upgrade أو Expect في الرسائل الصادرة، ولا Host في طلب العميل. تستنتج المكتبة Host والتأطير وتضيف Date لاستجابة الخادم عند غيابه. Content-Encoding اختيار صريح، ولا ضغط تلقائيا للخادم. يفشل تعارض الأطوال أو جمع Transfer-Encoding مع Content-Length أو طي الحقول أو التأطير الملتبس. تبقى ترويسات التحكم الواردة بيانات قابلة للقراءة. لا تنقل طول المتن المضغوط أو ترويسة ترميزه عميانا إلى استجابة جديدة.

URL العميل URI مطلق ASCII لـHTTP أو HTTPS. رمز النص غير ASCII في المسار والاستعلام بنسبة مئوية، وقدّم الأسماء الدولية بصيغة A-label. تدعم أسماء DNS وIPv4 وIPv6 بين قوسين مربعين. ترفض بيانات المستخدم والفراغ والتحكم والهروب السيئ والمنفذ غير الصالح ومعرفات منطقة IPv6. يحذف fragment ويصبح المسار الفارغ /. يحتفظ الطلب الأول بالنقاط والشرطات وهروب النسبة. يحذف رابط_نهائي fragment ويصغر أحرف البروتوكول واسم DNS ويحذف المنفذ الافتراضي ويستعمل / للفارغ، مع حفظ وجود الاستعلام وكتابة الهروب.

يحفظ هدف الطلب ترميز origin-form أو absolute-form لـHTTP وHTTPS، ويقبل OPTIONS أيضا *. يُستخرج المسار والاستعلام قبل الفك. تأتي جهة من الهدف المطلق أو Host الصالح. يميز له_استعلام بين /p و/p?. لا تغير الترويسات الممررة هذه الحقول أو معلومات TLS والعنوان الفعلية. فهارس المستمعين تبدأ من صفر. يفشل الهدف غير الصالح قبل المعالج.

يقسم عناصر_استعلام النص الخام عند & وأول = قبل فك النسبة مرة واحدة. لا تمرر ? الأول. يبقى + علامة جمع و; بيانات، وتبقى %26 داخل العنصر وتصبح %252F القيمة %2F. لا تنتج المقاطع الفارغة عناصر. يختلف flag عن flag= بحقل له_يساوي، ويكون اسم =x فارغا. يحفظ تكرار الأسماء الترتيب، و%00 قيمة NUL صالحة. يبقى الاستعلام الخام متاحا إذا فشل الهروب أو UTF-8 المفكوك. يطابق قيم_استعلام الاسم المفكوك تماما ويعيد قيمة فارغة للمفتاح دون مساواة.

التوجيه والاستجابات

الطرق ASCII tokens غير فارغة وحساسة لحالة الأحرف. لا يدعم CONNECT أو ترقية البروتوكول. تتطابق المسارات المرمزة تماما، بما فيه حالة الهروب والشرطات والنقاط. تختلف /a%2Fb و/a%2fb و/a/b و/a/../b. تبدأ الوجهة بـ/ دون استعلام أو fragment وبهروب صالح، و* لـOPTIONS فقط. يفشل تكرار زوج الطريقة والمسار أو إضافة معالج عام ثان.

الأولوية للوجهة المطابقة، ثم HEAD باستخدام GET، ثم 405 لمسار معروف، ثم المعالج العام للمسار المجهول أو 404 الافتراضي. يتقدم HEAD الصريح. ترتب Allow الطرق حسب البايتات وتضيف HEAD عند وجود GET دون اختراع OPTIONS. المتنان الافتراضيان Not found وMethod not allowed مع text/plain; charset=utf-8. لا يصل طلب غير صالح إلى المعالج العام.

حالات المعالج النهائية 200..599. استجابة عميل مكتملة 404 أو 500 نتيجة ناجحة. يستهلك الردود التمهيدية ضمن الحدود، ويرفض 101 وإصدارات السلك غير المدعومة. يحذف HEAD المتن بعد الفحص والمحاسبة. يحسب بديل GET طول المتن، ويمكن لـHEAD الصريح أو العام التصريح بطول تمثيل أو حذفه. يجب أن يطابق الطول المصرح متن HEAD غير الفارغ. يتطلب علم طول التمثيل غير المفعّل طولا صفرا.

تتطلب 204 و205 و304 متنا فارغا. تحذف 204 Content-Length وتضع 205 صفرا، ويمكن لـ304 التصريح بطول تمثيل أو حذفه. يسمح بهذا الطول فقط لـHEAD و304 ويجب ألا يكون سالبا. تتقدم قواعد الحالة على بديل HEAD. يعيد العميل في الردود دون متن متنا فارغا وعدد بايتات مرمزة صفرا وعلم gzip غير مفعّل، دون حجز أو فك التمثيل الافتراضي. ما زالت 205 تتطلب تأطيرا صالحا لرسالة فارغة.

يفحص تحقق_استجابة حدود الخدمة والبيانات دون إرسال، ويقبل طلب استدعائه فقط وفق هويته المخفية. تحتفظ النسخ بالهوية ولا يغير تعديل الطريقة العامة سلطة HEAD الفعلية. يفشل طلب استدعاء آخر أو سجل أنشأه التطبيق بالرمز http.invalid_argument. يعاد الفحص عند العودة. تنتج الاستجابة غير الصالحة أو المتجاوزة 500 عاما محدودا مع إغلاق الاتصال. يبقى فخ ASPL نهائيا.

قبل المعالج، يستخدم الطلب السيئ 400، والهدف الكبير 414، والترويسات الكبيرة 431، والمتن الكبير 413، والنقل أو CONNECT غير المدعوم 501، والتوقعات 417، وإصدار HTTP غير المدعوم 505. يتلقى Expect: 100-continue الصالح المقبول 100 قبل المتن. قد تعيد مهلة المرحلة 408 ما دامت الكلية حية، ويعيد الطلب المكتمل دون سعة انتظار أو معالجة 503. تغلق الاتصالات المرفوضة، وتكون متون الرفض الثابتة فارغة. قد يفشل قبول النقل أو TLS أو انتهاء الأب أو قطع الاتصال أو نفاد الميزانية دون رد HTTP.

التحويلات وgzip وإعادة الاستخدام

اتباع التحويلات وفك gzip غير مفعّلين افتراضيا. يتبع التفعيل 301/302/303/307/308 داخل origin واحد وفق البروتوكول والمضيف والمنفذ الفعلي. تحل المراجع النسبية مع معالجة النقاط الحرفية. تحول 301 و302 POST إلى GET وتحذف متنه وتبقي بقية الطرق. تحافظ 303 على HEAD أو تختار GET وتحذف المتن. تعيد 307 و308 الطريقة والبايتات نفسها. عند حذف المتن تحذف Content-Type وContent-Encoding وContent-Language وContent-Location وContent-Range وDigest وContent-Digest ويعاد اشتقاق التأطير.

غياب Location يعيد الرد. يفشل تكرارها أو خطؤها أو عدم صلاحية وجهتها. Location النسبي الفارغ صالح لكنه محدود بعدد الخطوات. تعاد الوجهة الصالحة خارج origin دون اتباع، بما فيه HTTPS إلى HTTP. يعد عدد_تحويلات الانتقالات المتبعة ورابط_نهائي آخر URL مطلوب. تشترك الخطوات في المهلة الكلية الأصلية. لا إعادة تلقائية لطلب التطبيق عند فشل النقل أو اتصال معاد الاستخدام.

عند تعطيل الفك تعاد البايتات المرمزة دون توليد Accept-Encoding. عند تفعيله تولد Accept-Encoding: gzip وترفض قيمة التطبيق لها. غياب الترميز أو identity وحدها يبقي البايتات. يفك gzip واحد دون اعتبار لحالة الاسم. يفشل التراكم والتكرار والترميز الآخر. يفحص اكتمال الأعضاء والبصمات ويقبل الأعضاء المتتابعة الصالحة ويرفض البتر والبيانات الزائدة. تحتفظ الترويسات والختامية ببيانات الضغط الأصلية. لا يعد بايتات_متن_مرمز تأطير النقل، ويكون متن مفكوكا فقط عندما يكون فك_ضغط_غزيب مفعّلا. يطبق حدي المتن المرمز والمفكوك قبل قبول البايتات التالية.

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

الحالة والحدود والمهل

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

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

ذاكرة الآلة 256 MiB والخلفية المشتركة 128 MiB افتراضيا. تشمل محاسبة الأصل السعات المحتفظ بها والقمم المؤقتة وحالة TLS وDNS والفك والأحداث. تحسب قيم ASPL الحية ضمن الآلة. مخازن المقابس في النواة خارج محاسبة الحجز، لكن المقابس المقبولة والخاملة ضمن الأعداد المحدودة. لا تتجاوز قائمة انتظار الاستماع المطلوبة لكل مستمع طلبات_منتظرة وقد يخفضها المضيف. يرفض امتلاء الانتظار أو المعالجات أو العمليات الصادرة القبول بدلا من إنشاء طوابير مخفية. قد تقيد حدود المضيف والذاكرة الفعلية إعدادا عدديا صالحا؛ لا يحجز الإعداد موارده ولا يضمن قبول العمل. يجب أيضا ألا تتجاوز اتصالات_عميل_خاملة قيمة اتصالات_صادرة. عند خفض سعة الصادر إلى أقل من 16، اخفض عدد الخامل الافتراضي معها وإلا أعادت اضبط الرمز http.invalid_argument. يثبت المثال المفحوص limits.aspl الرفض والتصحيح.

المهل زمن رتيب. تبدأ كلية العميل عند الاستدعاء وكلية الخادم عند أول بايت طلب وتشمل الانتظار وCPU والطلبات الصادرة والكتابة. تشمل مهلة الاتصال DNS وTCP وTLS معا. قد تقصر مهلة TLS أو الترويسات أو المتن أو الكتابة المهلة الأصلية ولا تمددها. يقيد الأب أبناءه. تسبق مصافحة TLS للخادم كلية أول بايت. تغطي مهلة الخمول غياب النشاط والتصريف انتظار الإيقاف. يستخدم التنظيف مهلة أصلية واحدة لكل الموارد في نطاق الملكية، افتراضها وأدناها 1000 ms. الاستقصاء كل 10 ms هدف استجابة وليس ضمانا للزمن الحقيقي.

يلغي انتهاء الأب أو قطع الاتصال أو انتهاء التصريف استدعاءه وأبناءه ويلغي النتائج المتأخرة ونشر الحالة، وتبقى المعالجات الأخرى حية. لا يسلم نتيجة فاشلة إلى الأب الملغى. إغلاق جهة استقبال فقط لا يثبت قطع الاتصال. يصرّف الإيقاف الصريح ويعود عاديا بعد التحرير. الإشارة الأولى تصرّف ثم تنهي التنفيذ بالحالة 7 والثانية تتجاوز التصريف. حالة الفخ 5 ولا يصبح 500 تلقائيا. تبقى حدود الآلة وفشل الحجز أو الثوابت وفشل التنظيف المحدود نتائج نهائية.

الإعدادات والبدء

استخدم configure(RuntimeConfig) قبل أول محاولة شبكة اجتازت التحقق. تعيد المجالات غير الصالحة أو idle_client_connections > outbound_connections الرمز http.invalid_argument دون تثبيت الإعدادات. تثبت محاولات العميل أو الخدمة المجتازة للتحقق الإعدادات حتى لو فشل بدء النقل؛ يعيد الضبط اللاحق http.already_started. لا تهيئ الأدوات المساعدة والفحص والبناء دون شبكة HTTP. تنسخ الخيارات والمستمعين وإعدادات التطبيق ولا تعمل كإعدادات قابلة للتغيير المباشر.

يتطلب Listener::tls=false مساري شهادة ومفتاح فارغين؛ ويتطلب true كليهما غير فارغ. منفذ المستمع 1..65535، ومستمع IPv6 خاص بـIPv6. يستهلك serve أو start المجتاز للتحقق فرصة الخدمة الوحيدة للتنفيذ. يحرر فشل البدء المستمعين والعمل المنشأين قبل إعادة رمزه المستقر. صحح المدخلات وابدأ تنفيذا جديدا. راجع إعدادات النشر ومثال الحدود.

الثقة الافتراضية والخاصة

يختار ClientOptions الافتراضي اكتشاف CA المضيف، مع use_private_ca=false وca_file فارغ. يتطلب use_private_ca=true مسار CA خاص غير فارغ بصيغة PEM ويحل محل مخزن المضيف. يعطي الجمع غير الصالح للعلم والمسار http.invalid_argument. تعطي الثقة المختارة الغائبة أو المشوهة أو غير المقروءة أو المتجاوزة للحجم http.ca_load_failed قبل الاتصال؛ وتعطي الثقة المحملة غير المتعلقة http.tls_verify_failed أثناء التحقق. لا تعطل هذه الخيارات فحص السلسلة والتاريخ والهوية.

أول حزمة افتراضية موجودة هي المرجع. لا ينتقل الاختيار من حزمة سيئة إلى التالية ولا يغير SSL_CERT_FILE أو SSL_CERT_DIR الاكتشاف. عند غياب الحزم المرشحة كلها يطبق اكتشاف مجلد محدود. تثبت الثقة المحللة بنجاح للتنفيذ. راجع ترتيب الاكتشاف الدقيق والتجهيز المحلي؛ لا تستنتج أن كل ترتيب ثقة لمضيف يعمل.

طلبات الطرف العلوي المرتبطة بالسياق

يتطلب request(ClientRequest, ClientOptions) داخل المعالج إطار طلبه الحي. تعيد read_config(ctx) إعدادات تطبيق الخدمة المنسوخة؛ توفر في عائلة الخدمة رابط الطرف العلوي ومسار CA الصريح. شهادة ومفتاح الخادم الوارد مستقلان عن ثقته الصادرة. يمرر المعالج المفحوص الحالة وبايتات المتن عمدا دون نسخ بيانات تمثيل الطرف المقابل المضغوط.

تبقى ردود 404 و500 الكاملة نتائج عميل ناجحة. يصل فشل الابن القابل للاسترداد إلى الأب الحي كنتيجة عادية؛ يحول المثال رمزه المستقر إلى متن 502. ينقض انتهاء مهلة الأب أو اكتشاف انقطاعه أو انتهاء التصريف عمل الابن ويسقط خرج المعالج ونشره المتأخرين بدلا من تسليم نتيجة فاشلة للمعالج الملغى. لا تمدد مهل الابن مهلة الأب. لا إعادة محاولة تلقائية أو وكيل صادر أو تراجع عن آثار الطرف المقابل. اتبع تمرين الطرف العلوي TLS الكامل.

مدخلات TLS

يفحص عميل TLS 1.2 و1.3 السلسلة والتواريخ وSAN للاسم أو IP دائما. يحمل الخادم سلسلة PEM ومفتاحا غير مشفر مطابقا لكل مستمع. تدعم مفاتيح rsaEncryption العادية 2048..8192 بت وأسّا فرديا أكبر من واحد لا يتجاوز 32 بت. تدعم منحنيات P-256 وP-384 وP-521 المسماة. تدعم توقيعات RSA-PSS بمفتاح RSA عادي، وترفض مفاتيح rsassaPss المقيدة وEd25519 وEd448 والمنحنيات الأخرى ومعاملات المنحنى الصريحة.

حد ملف TLS الافتراضي 1 MiB ومجاله 1..16 MiB. للمفتاح أيضا حد 65536 بايت، وللمسار أقل من 4096 بايت. حد كتلة PEM المحلية 65536 بايت وشهادة DER 49152 بايت ورسالة مصافحة شهادات الطرف المقابل 524288 بايت. حد شهادات الثقة 8192 بما فيها التكرار ولسلسلة المستمع ثماني شهادات ولـCA الوسيطة ست. يفحص مجلد الثقة حتى 16384 عنصرا و8192 ملفا عاديا فريدا. راجع اكتشاف الثقة وتوقيت فشل البدء.

أخطاء مستقرة قابلة للاسترداد

الرموز ASCII مستقلة عن لغة التشخيص. تعيد المنشئات والأدوات وعمليات الشبكة نتائج عادية قابلة للاسترداد للإخفاقات المتوقعة التالية. قد يفشل الطلب بعد تنفيذ الطرف المقابل له، ولا ضمان للتراجع هناك. ينظف فشل مضيف الخدمة غير المتوقع مواردها قبل عودة اخدم بالرمز http.host_failure.

Code / الرمز Meaning / المعنى
http.invalid_argument إعدادات أو مجال أو مستمع أو جمع خيارات غير صالح
http.invalid_url URL عميل غير صالح
http.invalid_header ترويسة صادرة غير صالحة أو ممنوعة
http.invalid_route طريقة أو مسار أو تسجيل غير صالح
http.duplicate_route زوج طريقة ومسار مكرر أو معالج عام ثان
http.invalid_response حالة أو متن أو بيانات تمثيل المعالج غير صالحة
http.invalid_utf8 بايتات التحويل أو الاستعلام ليست UTF-8 صالحا
http.invalid_query هروب نسبة غير صالح
http.query_limit تجاوز بايتات الاستعلام أو عدد عناصره
http.resolve_failed فشل حل اسم العميل أو المستمع
http.connect_failed فشل إنشاء TCP أو النقل القائم
http.tls_verify_failed فشل فحص السلسلة أو التواريخ أو SAN أو الهوية
http.tls_handshake_failed فشل تفاوض TLS غير التحقق والمهلة
http.ca_load_failed ثقة غائبة أو سيئة أو غير مقروءة أو كبيرة
http.tls_config_failed سلسلة أو مفتاح خادم سيئ أو مشفر أو غير مطابق
http.timeout انتهاء مهلة عميل كلية أو مرحلية مع بقاء المستدعي حيا
http.cancelled إلغاء محلي لابن مع بقاء المستدعي حيا
http.parse_failed صياغة أو تأطير أو ختامية غير صالحة أو ملتبسة
http.truncated_body انتهى متن ذو طول أو أجزاء قبل اكتماله
http.unsupported_protocol إصدار سلك أو ترقية أو نفق أو نقل غير مدعوم
http.unsupported_content_encoding ترميز متراكم أو مكرر أو غير مدعوم أثناء الفك
http.decode_failed فشل بصمة gzip أو بتره أو عضوه أو بياناته الزائدة
http.body_limit تجاوز المتن المرسل أو المستلم المرمز حده
http.decoded_body_limit تجاوز المتن المفكوك حده
http.header_limit تجاوز حد الترويسات أو الحقول أو سطر الجزء أو الردود التمهيدية
http.target_limit تجاوز URL أو هدف الطلب حده
http.resource_limit نفاد ميزانية الخلفية أو سعة إعدادات أو مخبأ محدود
http.overloaded غياب سعة قبول عميل أو خادم
http.redirect_invalid قيم Location متعددة أو سيئة أو غير قابلة للاستخدام
http.redirect_limit تجاوز الانتقال المؤهل التالي حد التحويلات
http.bind_failed تعذر ربط كل عناوين المستمع المحلولة
http.listen_failed تعذر بدء الاستماع على عنوان مربوط
http.already_started إعدادات تنفيذ ثابتة أو استدعاء خدمة أو بدء ثان أو متداخل
http.host_failure فشل مضيف أو خدمة غير متوقع بعد التنظيف
http.closed_session دوال حالة التطبيق أو إعداداته بعد الإغلاق المشترك
http.invalid_context عملية خارج سياق التطبيق المسموح
http.invalid_order عملية تستلزم خارج الإطار أثناء إطار رسم فعال

المستبعدات الحالية

HTTP/1.1 أصلي فقط. لا شبكة للمتصفح أو التضمين الخاص، ولا HTTP/2 أو HTTP/3 أو CONNECT أو WebSocket أو ترقية أخرى، ولا واجهة بث للمتن أو أدوات multipart أو SSE أو تحليل وتوليد JSON أو معاملات وجهات مسماة أو middleware أو إدارة تلقائية للكوكيز أو المصادقة أو وكيل صادر أو تحويل IDN تلقائي أو ضغط خادم أو إعادة تحميل شهادة أو اختيارها بـSNI أو مصادقة بشهادة عميل أو اتباع تحويلات تلقائي خارج origin.

استخدم دليل النشر الحالي لمسارات 0.7.0 الأصلي المنشور. يبقى مصدر النشر الخام السابق (يفتح في نافذة جديدة) بنطاق إصداره السابق.

الحدود المعيارية للإصدار

واجهة Raylib وحدودها وأخطاؤها

العقد الأصلي

المضيف الأصلي فقط، ASPL 0.7.0 المنشور. استورد core::raylib أو أساسي::رايليب في كل وحدة مصدر تستخدمها. تقبل كل بادئة قصيرة مستوردة مفردات الأعضاء باللغتين، واستورد الصيغتين لاستخدام البادئتين. تحتفظ معرفات المستخدم وحقول سجلاته ونصوصه ومساراته بهويتها. لا تحتاج العمليات الموردة إلى تصريح unsafe ولا تكشف واصفات أصلية.

اقرأ دليل الرسم والنص والصوت ومجموعة الأمثلة. لا يحتاج الفحص والبناء إلى شاشة أو مترجم C. تحتاج عمليات النافذة إلى رسوم Linux مدعومة مع OpenGL 3.3 core، والصوت إلى جهاز PulseAudio متوافق أو ALSA متاح. لا يحتاج النص على المعالج إلى أي منهما. راجع متطلبات النشر. يرفض المتصفح والتضمين الخاص هذه المكتبة الموردة بالرمز unsupported-supplied-library-profile حتى مع الاستيراد غير المستخدم.

تعيد كل الاستدعاءات العادية نتائج مفحوصة. الفحوص الكلية السبعة IsWindowReady وIsTextureValid وIsFontValid وIsTextLayoutValid وIsAudioDeviceReady وIsSoundValid وIsMusicValid تعيد bool. اقرأ فرع النتيجة المحدد وحده. أحجام الأعداد دقيقة، وحوّل القيمة الأوسع ذات النوع المحدد صراحة. تحفظ الجداول أدناه التصريحات المزدوجة المقبولة والمفحوصة مقابل فهرس الإنتاج. تسري قواعد السياق عبر المساعدات وقيم الدوال أيضا.

تحتاج السجلات إلى كل حقل مرة واحدة. تعد صيغتا الحقل الواحد تكرارا. تنسخ السجلات بالقيمة وتحتاج الطفرة إلى جذر قابل للتعديل. تقبل تعدادات المفتاح والفأرة والمرشح والالتفاف واتجاه النص ومحاذاته التخزين والمساواة من النوع نفسه دون بناء من أعداد أو حساب أو ترتيب. يقبل WindowFlags عمليات | و& و^ و~ المحدودة والمساواة من النوع نفسه باستعمال البتات الخمسة المدعومة والمجموعة الفارغة. يقبل TextureFilter القيمتين POINT وBILINEAR، وTextureWrap القيمتين REPEAT وCLAMP. Texture وFont وTextLayout وSound وMusic ملاك مدارون مشتركون معتمون.

الأنواع والحقول

English / العربية Policy / القاعدة
Vector2 / متجه2 record / سجل
Rectangle / مستطيل record / سجل
Color / لون record / سجل
Camera2D / كاميرا2 record / سجل
TextOptions / خيارات_النص record / سجل
TextMetrics / مقاييس_النص record / سجل
Texture / نسيج shared opaque owner / مالك مشترك معتم
Font / خط shared opaque owner / مالك مشترك معتم
Sound / صوت shared opaque owner / مالك مشترك معتم
Music / موسيقى shared opaque owner / مالك مشترك معتم
TextLayout / تخطيط_نص shared opaque owner / مالك مشترك معتم
Key / مفتاح nominal enum / تعداد اسمي
MouseButton / زر_فأرة nominal enum / تعداد اسمي
TextureFilter / مرشح_نسيج nominal enum / تعداد اسمي
TextureWrap / التفاف_نسيج nominal enum / تعداد اسمي
TextDirection / اتجاه_نص nominal enum / تعداد اسمي
TextAlignment / محاذاة_نص nominal enum / تعداد اسمي
WindowFlags / أعلام_نافذة bounded flags / أعلام محدودة

Vector2 / متجه2

English / العربية Type / النوع
x / س f32
y / ص f32

Rectangle / مستطيل

English / العربية Type / النوع
x / س f32
y / ص f32
width / عرض f32
height / ارتفاع f32

Color / لون

English / العربية Type / النوع
r / أحمر u8
g / أخضر u8
b / أزرق u8
a / ألفا u8

Camera2D / كاميرا2

English / العربية Type / النوع
offset / إزاحة Vector2
target / هدف Vector2
rotation / دوران f32
zoom / تكبير f32

TextOptions / خيارات_النص

English / العربية Type / النوع
font_size / حجم_الخط f32
direction / اتجاه TextDirection
has_width / له_عرض bool
width / عرض f32
alignment / محاذاة TextAlignment
line_spacing / تباعد_الأسطر f32

TextMetrics / مقاييس_النص

English / العربية Type / النوع
size / حجم Vector2
ink / حبر Rectangle

الثوابت

English / العربية Type / النوع Value / القيمة
KEY_NULL / مفتاح_لا_شيء Key 0
KEY_APOSTROPHE / مفتاح_اقتباس_مفرد Key 39
KEY_COMMA / مفتاح_فاصلة Key 44
KEY_MINUS / مفتاح_ناقص Key 45
KEY_PERIOD / مفتاح_نقطة Key 46
KEY_SLASH / مفتاح_شرطة_مائلة Key 47
KEY_ZERO / مفتاح_0 Key 48
KEY_ONE / مفتاح_1 Key 49
KEY_TWO / مفتاح_2 Key 50
KEY_THREE / مفتاح_3 Key 51
KEY_FOUR / مفتاح_4 Key 52
KEY_FIVE / مفتاح_5 Key 53
KEY_SIX / مفتاح_6 Key 54
KEY_SEVEN / مفتاح_7 Key 55
KEY_EIGHT / مفتاح_8 Key 56
KEY_NINE / مفتاح_9 Key 57
KEY_SEMICOLON / مفتاح_فاصلة_منقوطة Key 59
KEY_EQUAL / مفتاح_يساوي Key 61
KEY_A / مفتاح_A Key 65
KEY_B / مفتاح_B Key 66
KEY_C / مفتاح_C Key 67
KEY_D / مفتاح_D Key 68
KEY_E / مفتاح_E Key 69
KEY_F / مفتاح_F Key 70
KEY_G / مفتاح_G Key 71
KEY_H / مفتاح_H Key 72
KEY_I / مفتاح_I Key 73
KEY_J / مفتاح_J Key 74
KEY_K / مفتاح_K Key 75
KEY_L / مفتاح_L Key 76
KEY_M / مفتاح_M Key 77
KEY_N / مفتاح_N Key 78
KEY_O / مفتاح_O Key 79
KEY_P / مفتاح_P Key 80
KEY_Q / مفتاح_Q Key 81
KEY_R / مفتاح_R Key 82
KEY_S / مفتاح_S Key 83
KEY_T / مفتاح_T Key 84
KEY_U / مفتاح_U Key 85
KEY_V / مفتاح_V Key 86
KEY_W / مفتاح_W Key 87
KEY_X / مفتاح_X Key 88
KEY_Y / مفتاح_Y Key 89
KEY_Z / مفتاح_Z Key 90
KEY_LEFT_BRACKET / مفتاح_قوس_مربع_أيسر Key 91
KEY_BACKSLASH / مفتاح_شرطة_مائلة_عكسية Key 92
KEY_RIGHT_BRACKET / مفتاح_قوس_مربع_أيمن Key 93
KEY_GRAVE / مفتاح_اقتباس_خلفي Key 96
KEY_SPACE / مفتاح_مسافة Key 32
KEY_ESCAPE / مفتاح_هروب Key 256
KEY_ENTER / مفتاح_إدخال Key 257
KEY_TAB / مفتاح_جدولة Key 258
KEY_BACKSPACE / مفتاح_مسح_خلفي Key 259
KEY_INSERT / مفتاح_إدراج Key 260
KEY_DELETE / مفتاح_حذف Key 261
KEY_RIGHT / مفتاح_يمين Key 262
KEY_LEFT / مفتاح_يسار Key 263
KEY_DOWN / مفتاح_أسفل Key 264
KEY_UP / مفتاح_أعلى Key 265
KEY_PAGE_UP / مفتاح_صفحة_لأعلى Key 266
KEY_PAGE_DOWN / مفتاح_صفحة_لأسفل Key 267
KEY_HOME / مفتاح_بداية Key 268
KEY_END / مفتاح_نهاية Key 269
KEY_CAPS_LOCK / مفتاح_قفل_الأحرف Key 280
KEY_SCROLL_LOCK / مفتاح_قفل_التمرير Key 281
KEY_NUM_LOCK / مفتاح_قفل_الأرقام Key 282
KEY_PRINT_SCREEN / مفتاح_طباعة_الشاشة Key 283
KEY_PAUSE / مفتاح_إيقاف_مؤقت Key 284
KEY_F1 / مفتاح_F1 Key 290
KEY_F2 / مفتاح_F2 Key 291
KEY_F3 / مفتاح_F3 Key 292
KEY_F4 / مفتاح_F4 Key 293
KEY_F5 / مفتاح_F5 Key 294
KEY_F6 / مفتاح_F6 Key 295
KEY_F7 / مفتاح_F7 Key 296
KEY_F8 / مفتاح_F8 Key 297
KEY_F9 / مفتاح_F9 Key 298
KEY_F10 / مفتاح_F10 Key 299
KEY_F11 / مفتاح_F11 Key 300
KEY_F12 / مفتاح_F12 Key 301
KEY_LEFT_SHIFT / مفتاح_تبديل_أيسر Key 340
KEY_LEFT_CONTROL / مفتاح_تحكم_أيسر Key 341
KEY_LEFT_ALT / مفتاح_بديل_أيسر Key 342
KEY_LEFT_SUPER / مفتاح_نظام_أيسر Key 343
KEY_RIGHT_SHIFT / مفتاح_تبديل_أيمن Key 344
KEY_RIGHT_CONTROL / مفتاح_تحكم_أيمن Key 345
KEY_RIGHT_ALT / مفتاح_بديل_أيمن Key 346
KEY_RIGHT_SUPER / مفتاح_نظام_أيمن Key 347
KEY_KB_MENU / مفتاح_قائمة_لوحة_المفاتيح Key 348
KEY_KP_0 / مفتاح_لوحة_أرقام_0 Key 320
KEY_KP_1 / مفتاح_لوحة_أرقام_1 Key 321
KEY_KP_2 / مفتاح_لوحة_أرقام_2 Key 322
KEY_KP_3 / مفتاح_لوحة_أرقام_3 Key 323
KEY_KP_4 / مفتاح_لوحة_أرقام_4 Key 324
KEY_KP_5 / مفتاح_لوحة_أرقام_5 Key 325
KEY_KP_6 / مفتاح_لوحة_أرقام_6 Key 326
KEY_KP_7 / مفتاح_لوحة_أرقام_7 Key 327
KEY_KP_8 / مفتاح_لوحة_أرقام_8 Key 328
KEY_KP_9 / مفتاح_لوحة_أرقام_9 Key 329
KEY_KP_DECIMAL / مفتاح_لوحة_أرقام_عشرية Key 330
KEY_KP_DIVIDE / مفتاح_لوحة_أرقام_قسمة Key 331
KEY_KP_MULTIPLY / مفتاح_لوحة_أرقام_ضرب Key 332
KEY_KP_SUBTRACT / مفتاح_لوحة_أرقام_طرح Key 333
KEY_KP_ADD / مفتاح_لوحة_أرقام_جمع Key 334
KEY_KP_ENTER / مفتاح_لوحة_أرقام_إدخال Key 335
KEY_KP_EQUAL / مفتاح_لوحة_أرقام_يساوي Key 336
KEY_BACK / مفتاح_رجوع Key 4
KEY_MENU / مفتاح_قائمة Key 5
KEY_VOLUME_UP / مفتاح_رفع_الصوت Key 24
KEY_VOLUME_DOWN / مفتاح_خفض_الصوت Key 25
MOUSE_BUTTON_LEFT / زر_فأرة_أيسر MouseButton 0
MOUSE_BUTTON_RIGHT / زر_فأرة_أيمن MouseButton 1
MOUSE_BUTTON_MIDDLE / زر_فأرة_أوسط MouseButton 2
MOUSE_BUTTON_SIDE / زر_فأرة_جانبي MouseButton 3
MOUSE_BUTTON_EXTRA / زر_فأرة_إضافي MouseButton 4
MOUSE_BUTTON_FORWARD / زر_فأرة_تقدم MouseButton 5
MOUSE_BUTTON_BACK / زر_فأرة_رجوع MouseButton 6
TEXTURE_FILTER_POINT / مرشح_نسيج_نقطي TextureFilter 0
TEXTURE_FILTER_BILINEAR / مرشح_نسيج_ثنائي_الخطية TextureFilter 1
TEXTURE_WRAP_REPEAT / التفاف_نسيج_تكرار TextureWrap 0
TEXTURE_WRAP_CLAMP / التفاف_نسيج_تثبيت TextureWrap 1
FLAG_VSYNC_HINT / علم_تلميح_تزامن_رأسي WindowFlags 64
FLAG_FULLSCREEN_MODE / علم_ملء_الشاشة WindowFlags 2
FLAG_WINDOW_RESIZABLE / علم_نافذة_قابلة_للتحجيم WindowFlags 4
FLAG_WINDOW_HIGHDPI / علم_نافذة_عالية_الكثافة WindowFlags 8192
FLAG_MSAA_4X_HINT / علم_تلميح_تنعيم_4X WindowFlags 32
WINDOW_FLAGS_NONE / أعلام_نافذة_فارغة WindowFlags 0
LIGHTGRAY / رمادي_فاتح Color [200, 200, 200, 255]
GRAY / رمادي Color [130, 130, 130, 255]
DARKGRAY / رمادي_داكن Color [80, 80, 80, 255]
YELLOW / أصفر Color [253, 249, 0, 255]
GOLD / ذهبي Color [255, 203, 0, 255]
ORANGE / برتقالي Color [255, 161, 0, 255]
PINK / وردي Color [255, 109, 194, 255]
RED / أحمر Color [230, 41, 55, 255]
MAROON / عنابي Color [190, 33, 55, 255]
GREEN / أخضر Color [0, 228, 48, 255]
LIME / أخضر_ليموني Color [0, 158, 47, 255]
DARKGREEN / أخضر_داكن Color [0, 117, 44, 255]
SKYBLUE / أزرق_سماوي Color [102, 191, 255, 255]
BLUE / أزرق Color [0, 121, 241, 255]
DARKBLUE / أزرق_داكن Color [0, 82, 172, 255]
PURPLE / أرجواني Color [200, 122, 255, 255]
VIOLET / بنفسجي Color [135, 60, 190, 255]
DARKPURPLE / أرجواني_داكن Color [112, 31, 126, 255]
BEIGE / بيج Color [211, 176, 131, 255]
BROWN / بني Color [127, 106, 79, 255]
DARKBROWN / بني_داكن Color [76, 63, 47, 255]
WHITE / أبيض Color [255, 255, 255, 255]
BLACK / أسود Color [0, 0, 0, 255]
BLANK / شفاف Color [0, 0, 0, 0]
MAGENTA / فوشي Color [255, 0, 255, 255]
RAYWHITE / أبيض_رايليب Color [245, 245, 245, 255]
TEXT_DIRECTION_AUTO / اتجاه_نص_تلقائي TextDirection Auto
TEXT_DIRECTION_LTR / اتجاه_نص_من_اليسار_إلى_اليمين TextDirection LTR
TEXT_DIRECTION_RTL / اتجاه_نص_من_اليمين_إلى_اليسار TextDirection RTL
TEXT_ALIGNMENT_START / محاذاة_نص_بداية TextAlignment Start
TEXT_ALIGNMENT_END / محاذاة_نص_نهاية TextAlignment End
TEXT_ALIGNMENT_CENTER / محاذاة_نص_وسط TextAlignment Center
TEXT_ALIGNMENT_LEFT / محاذاة_نص_يسار TextAlignment Left
TEXT_ALIGNMENT_RIGHT / محاذاة_نص_يمين TextAlignment Right

النافذة ودورة الحياة

SetConfigFlags / اضبط_أعلام_الإعداد

(flags: WindowFlags) -> result<unit>

التطبيق والخيط الرئيسي وخارج إطار الرسم، مع شروط الجهاز والمالك.

يستبدل أعلام النافذة التالية المحفوظة. يشترط عدم وجود نافذة حية وتبقى الأعلام بعد إعادة الفتح.

InitWindow / هيئ_نافذة

(width: i32, height: i32, title: string) -> result<unit>

التطبيق والخيط الرئيسي وخارج إطار الرسم، مع شروط الجهاز والمالك.

أبعاد موجبة، ونسخة محفوظة من بايتات العنوان. يعيد الجيل الجديد مفتاح هروب والإدخال والتوقيت إلى البداية.

IsWindowReady / هل_النافذة_جاهزة

() -> bool

فحص كلي، مسموح للمعالجات والدوال الراجعة، دون دخول جهاز أصلي.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

WindowShouldClose / هل_يجب_إغلاق_النافذة

() -> result<bool>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

CloseWindow / أغلق_النافذة

() -> result<unit>

التطبيق والخيط الرئيسي وخارج إطار الرسم، مع شروط الجهاز والمالك.

يغلق نسخ الأنسجة ومخابئ GPU قبل تدمير السياق. تبقى الخطوط والتخطيطات على المعالج.

SetWindowTitle / اضبط_عنوان_النافذة

(title: string) -> result<unit>

التطبيق والخيط الرئيسي وخارج إطار الرسم، مع شروط الجهاز والمالك.

يحتفظ بنسخة العنوان حتى الاستبدال وانتهاء الاستخدام الأصلي. يبقى العنوان الحالي عند الرفض ويرفض NUL.

GetScreenWidth / عرض_الشاشة

() -> result<i32>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetScreenHeight / ارتفاع_الشاشة

() -> result<i32>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetRenderWidth / عرض_التصيير

() -> result<i32>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetRenderHeight / ارتفاع_التصيير

() -> result<i32>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

IsWindowResized / هل_تغير_حجم_النافذة

() -> result<bool>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

إطارات الرسم والتوقيت

BeginDrawing / ابدأ_الرسم

() -> result<unit>

التطبيق والخيط الرئيسي، مع قواعد أزواج الرسم ووضع الكاميرا.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

EndDrawing / أنه_الرسم

() -> result<unit>

التطبيق والخيط الرئيسي، مع قواعد أزواج الرسم ووضع الكاميرا.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

ClearBackground / امسح_الخلفية

(color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

SetTargetFPS / اضبط_معدل_الإطارات

(fps: i32) -> result<unit>

التطبيق والخيط الرئيسي وخارج إطار الرسم، مع شروط الجهاز والمالك.

معدل غير سالب. الصفر بلا سقف وتبقى إعدادات التوقيت بعد إعادة الفتح.

GetFrameTime / زمن_الإطار

() -> result<f32>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetTime / الزمن

() -> result<f64>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetFPS / معدل_الإطارات

() -> result<i32>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

إدخال لوحة المفاتيح والفأرة والحجم

IsKeyPressed / هل_ضغط_المفتاح

(key: Key) -> result<bool>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

IsKeyPressedRepeat / هل_تكرر_ضغط_المفتاح

(key: Key) -> result<bool>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

IsKeyDown / هل_المفتاح_مضغوط

(key: Key) -> result<bool>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

IsKeyReleased / هل_حرر_المفتاح

(key: Key) -> result<bool>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

IsKeyUp / هل_المفتاح_غير_مضغوط

(key: Key) -> result<bool>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetKeyPressed / المفتاح_المضغوط

() -> result<Key>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

يستهلك عنصرا واحدا من الطابور. يعيد مفتاح_لا_شيء عندما يكون الطابور فارغا.

GetCharPressed / المحرف_المدخل

() -> result<i32>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

يستهلك عنصرا واحدا من الطابور ويعيد صفرا أو قيمة Unicode مفحوصة من نوع ص32.

SetExitKey / اضبط_مفتاح_الخروج

(key: Key) -> result<unit>

التطبيق والخيط الرئيسي وخارج إطار الرسم، مع شروط الجهاز والمالك.

مفتاح_لا_شيء يعطل مفتاح الخروج. يعيد الفتح مفتاح هروب.

IsMouseButtonPressed / هل_ضغط_زر_الفأرة

(button: MouseButton) -> result<bool>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

IsMouseButtonDown / هل_زر_الفأرة_مضغوط

(button: MouseButton) -> result<bool>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

IsMouseButtonReleased / هل_حرر_زر_الفأرة

(button: MouseButton) -> result<bool>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

IsMouseButtonUp / هل_زر_الفأرة_غير_مضغوط

(button: MouseButton) -> result<bool>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetMousePosition / موضع_الفأرة

() -> result<Vector2>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetMouseDelta / تغير_موضع_الفأرة

() -> result<Vector2>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetMouseWheelMove / حركة_عجلة_الفأرة

() -> result<f32>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetMouseWheelMoveV / حركة_عجلة_الفأرة_بمتجه

() -> result<Vector2>

التطبيق والخيط الرئيسي ونافذة حية، وتسمح الملاحظات المأخوذة داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

الرسم ثنائي الأبعاد

DrawPixel / ارسم_بكسلا

(posX: i32, posY: i32, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawPixelV / ارسم_بكسلا_بمتجه

(position: Vector2, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawLine / ارسم_خطا

(startPosX: i32, startPosY: i32, endPosX: i32, endPosY: i32, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawLineV / ارسم_خطا_بمتجه

(startPos: Vector2, endPos: Vector2, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawLineEx / ارسم_خطا_موسعا

(startPos: Vector2, endPos: Vector2, thick: f32, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawCircle / ارسم_دائرة

(centerX: i32, centerY: i32, radius: f32, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawCircleV / ارسم_دائرة_بمتجه

(center: Vector2, radius: f32, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawCircleLines / ارسم_محيط_دائرة

(centerX: i32, centerY: i32, radius: f32, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawRectangle / ارسم_مستطيلا

(posX: i32, posY: i32, width: i32, height: i32, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawRectangleV / ارسم_مستطيلا_بمتجه

(position: Vector2, size: Vector2, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawRectangleRec / ارسم_مستطيلا_بسجل

(rec: Rectangle, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawRectanglePro / ارسم_مستطيلا_متقدما

(rec: Rectangle, origin: Vector2, rotation: f32, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawRectangleLines / ارسم_محيط_مستطيل

(posX: i32, posY: i32, width: i32, height: i32, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawRectangleLinesEx / ارسم_محيط_مستطيل_موسعا

(rec: Rectangle, lineThick: f32, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawTriangle / ارسم_مثلثا

(v1: Vector2, v2: Vector2, v3: Vector2, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawTriangleLines / ارسم_محيط_مثلث

(v1: Vector2, v2: Vector2, v3: Vector2, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

الأنسجة والصور

LoadTexture / حمل_نسيجا

(fileName: string) -> result<Texture>

التطبيق والخيط الرئيسي وخارج إطار الرسم، مع شروط الجهاز والمالك.

PNG فقط، بمسار نسبة إلى مجلد العمل ونسخة من بايتات المسار. يتطلب نافذة حية.

IsTextureValid / هل_النسيج_صالح

(texture: Texture) -> bool

فحص كلي، مسموح للمعالجات والدوال الراجعة، دون دخول جهاز أصلي.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

UnloadTexture / حرر_النسيج

(texture: Texture) -> result<unit>

التطبيق والخيط الرئيسي. يجوز الإغلاق المنطقي داخل إطار وينجح تحرير المورد المغلق.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

SetTextureFilter / اضبط_مرشح_النسيج

(texture: Texture, filter: TextureFilter) -> result<unit>

التطبيق والخيط الرئيسي وخارج إطار الرسم، مع شروط الجهاز والمالك.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

SetTextureWrap / اضبط_التفاف_النسيج

(texture: Texture, wrap: TextureWrap) -> result<unit>

التطبيق والخيط الرئيسي وخارج إطار الرسم، مع شروط الجهاز والمالك.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

DrawTexture / ارسم_نسيجا

(texture: Texture, posX: i32, posY: i32, tint: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

الأبعاد الموقعة للمصدر تحفظ الانعكاس. يبقى سلوك رايليب المسموح للمقياس الصفري والسالب والوجهات الموقعة، مع فحص إمكان تمثيل الحسابات الناتجة.

DrawTextureV / ارسم_نسيجا_بمتجه

(texture: Texture, position: Vector2, tint: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

الأبعاد الموقعة للمصدر تحفظ الانعكاس. يبقى سلوك رايليب المسموح للمقياس الصفري والسالب والوجهات الموقعة، مع فحص إمكان تمثيل الحسابات الناتجة.

DrawTextureEx / ارسم_نسيجا_موسعا

(texture: Texture, position: Vector2, rotation: f32, scale: f32, tint: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

الأبعاد الموقعة للمصدر تحفظ الانعكاس. يبقى سلوك رايليب المسموح للمقياس الصفري والسالب والوجهات الموقعة، مع فحص إمكان تمثيل الحسابات الناتجة.

DrawTextureRec / ارسم_جزء_نسيج

(texture: Texture, source: Rectangle, position: Vector2, tint: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

الأبعاد الموقعة للمصدر تحفظ الانعكاس. يبقى سلوك رايليب المسموح للمقياس الصفري والسالب والوجهات الموقعة، مع فحص إمكان تمثيل الحسابات الناتجة.

DrawTexturePro / ارسم_نسيجا_متقدما

(texture: Texture, source: Rectangle, dest: Rectangle, origin: Vector2, rotation: f32, tint: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

الأبعاد الموقعة للمصدر تحفظ الانعكاس. يبقى سلوك رايليب المسموح للمقياس الصفري والسالب والوجهات الموقعة، مع فحص إمكان تمثيل الحسابات الناتجة.

GetTextureWidth / عرض_النسيج

(texture: Texture) -> result<i32>

بيانات مالك للقراءة فقط، مسموحة للمعالجات والدوال الراجعة مع فحص إغلاق المالك.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetTextureHeight / ارتفاع_النسيج

(texture: Texture) -> result<i32>

بيانات مالك للقراءة فقط، مسموحة للمعالجات والدوال الراجعة مع فحص إغلاق المالك.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

أوضاع كاميرا2 وتحويلاتها

BeginMode2D / ابدأ_وضع_ثنائي_الأبعاد

(camera: Camera2D) -> result<unit>

التطبيق والخيط الرئيسي، مع قواعد أزواج الرسم ووضع الكاميرا.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

EndMode2D / أنه_وضع_ثنائي_الأبعاد

() -> result<unit>

التطبيق والخيط الرئيسي، مع قواعد أزواج الرسم ووضع الكاميرا.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetWorldToScreen2D / من_العالم_إلى_الشاشة

(position: Vector2, camera: Camera2D) -> result<Vector2>

حساب مفحوص، مسموح للمعالجات والدوال الراجعة، دون اشتراط جهاز أو إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetScreenToWorld2D / من_الشاشة_إلى_العالم

(position: Vector2, camera: Camera2D) -> result<Vector2>

حساب مفحوص، مسموح للمعالجات والدوال الراجعة، دون اشتراط جهاز أو إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

هندسة التصادم

CheckCollisionRecs / هل_يتداخل_مستطيلان

(rec1: Rectangle, rec2: Rectangle) -> result<bool>

حساب مفحوص، مسموح للمعالجات والدوال الراجعة، دون اشتراط جهاز أو إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

CheckCollisionCircles / هل_تتداخل_دائرتان

(center1: Vector2, radius1: f32, center2: Vector2, radius2: f32) -> result<bool>

حساب مفحوص، مسموح للمعالجات والدوال الراجعة، دون اشتراط جهاز أو إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

CheckCollisionCircleRec / هل_تتداخل_دائرة_ومستطيل

(center: Vector2, radius: f32, rec: Rectangle) -> result<bool>

حساب مفحوص، مسموح للمعالجات والدوال الراجعة، دون اشتراط جهاز أو إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

CheckCollisionPointRec / هل_النقطة_في_مستطيل

(point: Vector2, rec: Rectangle) -> result<bool>

حساب مفحوص، مسموح للمعالجات والدوال الراجعة، دون اشتراط جهاز أو إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

CheckCollisionPointCircle / هل_النقطة_في_دائرة

(point: Vector2, center: Vector2, radius: f32) -> result<bool>

حساب مفحوص، مسموح للمعالجات والدوال الراجعة، دون اشتراط جهاز أو إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

CheckCollisionPointTriangle / هل_النقطة_في_مثلث

(point: Vector2, p1: Vector2, p2: Vector2, p3: Vector2) -> result<bool>

حساب مفحوص، مسموح للمعالجات والدوال الراجعة، دون اشتراط جهاز أو إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetCollisionRec / مستطيل_التداخل

(rec1: Rectangle, rec2: Rectangle) -> result<Rectangle>

حساب مفحوص، مسموح للمعالجات والدوال الراجعة، دون اشتراط جهاز أو إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

اختيار الخطوط وملكيتها

GetFontDefault / الخط_الافتراضي

() -> result<Font>

نص على المعالج، مسموح للمعالجات والدوال الراجعة، دون نافذة.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

LoadFont / حمل_خطا

(fileName: string) -> result<Font>

التطبيق والخيط الرئيسي وخارج إطار الرسم، مع شروط الجهاز والمالك.

خط TrueType ذو وجه واحد وحدود متجهة. تبقى بايتات الملف المنسوخة بعد استبداله وتتوفر الخطوط الاحتياطية المضمنة.

LoadFontEx / حمل_خطا_موسعا

(fileName: string, fontSize: i32, codepoints: list<i32>) -> result<Font>

التطبيق والخيط الرئيسي وخارج إطار الرسم، مع شروط الجهاز والمالك.

حجم أساسي 1..4096. قائمة ص32 تلميحات لتجهيز المحارف تنسخها المكتبة. القائمة الفارغة بلا تلميحات ولا تحد التغطية.

IsFontValid / هل_الخط_صالح

(font: Font) -> bool

فحص كلي، مسموح للمعالجات والدوال الراجعة، دون دخول جهاز أصلي.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

UnloadFont / حرر_الخط

(font: Font) -> result<unit>

نص على المعالج، مسموح للمعالجات والدوال الراجعة، دون نافذة.

يغلق النسخ المشتركة بأمان. تحتفظ التخطيطات ببيانات الخط المستقلة ويقبل تحرير الخط الافتراضي دون إغلاقه.

GetFontBaseSize / حجم_الخط_الأساسي

(font: Font) -> result<i32>

نص على المعالج، مسموح للمعالجات والدوال الراجعة، دون نافذة.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

تخطيطات النص الثابتة

CreateTextLayout / أنشئ_تخطيط_نص

(font: Font, text: string, options: TextOptions) -> result<TextLayout>

نص على المعالج، مسموح للمعالجات والدوال الراجعة، دون نافذة.

تخطيط ثابت على المعالج. يجب تحديد كل حقول الخيارات ويحتفظ بالخطوط ويبقى بعد إعادة إنشاء النافذة.

MeasureTextLayout / قس_تخطيط_النص

(layout: TextLayout) -> result<TextMetrics>

نص على المعالج، مسموح للمعالجات والدوال الراجعة، دون نافذة.

حجم هو الصندوق المنطقي وحبر هو حدود المحارف المحلية. القياس والرسم يستخدمان المواضع نفسها.

IsTextLayoutValid / هل_تخطيط_النص_صالح

(layout: TextLayout) -> bool

فحص كلي، مسموح للمعالجات والدوال الراجعة، دون دخول جهاز أصلي.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

UnloadTextLayout / حرر_تخطيط_النص

(layout: TextLayout) -> result<unit>

نص على المعالج، مسموح للمعالجات والدوال الراجعة، دون نافذة.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

قياس النص المشكل

MeasureText / قس_النص

(text: string, fontSize: i32) -> result<i32>

نص على المعالج، مسموح للمعالجات والدوال الراجعة، دون نافذة.

عرض بخط افتراضي مشكل، يقرب لأعلى إلى ص32 مفحوص. الحجم 1..4096.

MeasureTextEx / قس_النص_موسعا

(font: Font, text: string, fontSize: f32, spacing: f32) -> result<Vector2>

نص على المعالج، مسموح للمعالجات والدوال الراجعة، دون نافذة.

حجم منطقي لنص مشكل. التباعد صفر وحجم الخط 0.5..4096.

رسم النص المشكل

DrawText / ارسم_نصا

(text: string, posX: i32, posY: i32, fontSize: i32, color: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

نص عربي ولاتيني مشكل في ترتيب منطقي. فشل التجهيز المعروف لا يرسل أي رسم لهذا الطلب. تباعد Ex وPro يجب أن يكون صفرا.

DrawTextEx / ارسم_نصا_موسعا

(font: Font, text: string, position: Vector2, fontSize: f32, spacing: f32, tint: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

نص عربي ولاتيني مشكل في ترتيب منطقي. فشل التجهيز المعروف لا يرسل أي رسم لهذا الطلب. تباعد Ex وPro يجب أن يكون صفرا.

DrawTextPro / ارسم_نصا_متقدما

(font: Font, text: string, position: Vector2, origin: Vector2, rotation: f32, fontSize: f32, spacing: f32, tint: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

نص عربي ولاتيني مشكل في ترتيب منطقي. فشل التجهيز المعروف لا يرسل أي رسم لهذا الطلب. تباعد Ex وPro يجب أن يكون صفرا.

DrawTextLayout / ارسم_تخطيط_النص

(layout: TextLayout, position: Vector2, tint: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

نص عربي ولاتيني مشكل في ترتيب منطقي. فشل التجهيز المعروف لا يرسل أي رسم لهذا الطلب. تباعد Ex وPro يجب أن يكون صفرا.

DrawTextLayoutPro / ارسم_تخطيط_النص_متقدما

(layout: TextLayout, position: Vector2, origin: Vector2, rotation: f32, tint: Color) -> result<unit>

التطبيق والخيط الرئيسي وداخل إطار رسم.

نص عربي ولاتيني مشكل في ترتيب منطقي. فشل التجهيز المعروف لا يرسل أي رسم لهذا الطلب. تباعد Ex وPro يجب أن يكون صفرا.

جهاز الصوت والأصوات

InitAudioDevice / هيئ_جهاز_الصوت

() -> result<unit>

التطبيق والخيط الرئيسي وخارج إطار الرسم، مع شروط الجهاز والمالك.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

CloseAudioDevice / أغلق_جهاز_الصوت

() -> result<unit>

التطبيق والخيط الرئيسي وخارج إطار الرسم، مع شروط الجهاز والمالك.

يوقف ويغلق نسخ الصوت والموسيقى التابعة قبل تحرير الجهاز.

IsAudioDeviceReady / هل_جهاز_الصوت_جاهز

() -> bool

فحص كلي، مسموح للمعالجات والدوال الراجعة، دون دخول جهاز أصلي.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

SetMasterVolume / اضبط_مستوى_الصوت_العام

(volume: f32) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

مستوى الصوت 0..1.

GetMasterVolume / مستوى_الصوت_العام

() -> result<f32>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

LoadSound / حمل_صوتا

(fileName: string) -> result<Sound>

التطبيق والخيط الرئيسي وخارج إطار الرسم، مع شروط الجهاز والمالك.

ملفات WAV وOGG وMP3، بمسار نسبة إلى مجلد العمل. المورد تابع لجيل الصوت الحالي.

IsSoundValid / هل_الصوت_صالح

(sound: Sound) -> bool

فحص كلي، مسموح للمعالجات والدوال الراجعة، دون دخول جهاز أصلي.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

UnloadSound / حرر_الصوت

(sound: Sound) -> result<unit>

التطبيق والخيط الرئيسي. يجوز الإغلاق المنطقي داخل إطار وينجح تحرير المورد المغلق.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

PlaySound / شغل_الصوت

(sound: Sound) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

StopSound / أوقف_الصوت

(sound: Sound) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

PauseSound / أوقف_الصوت_مؤقتا

(sound: Sound) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

ResumeSound / استأنف_الصوت

(sound: Sound) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

IsSoundPlaying / هل_الصوت_يعمل

(sound: Sound) -> result<bool>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

SetSoundVolume / اضبط_مستوى_الصوت

(sound: Sound, volume: f32) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

مستوى الصوت 0..1.

SetSoundPitch / اضبط_حدة_الصوت

(sound: Sound, pitch: f32) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

درجة صوت موجبة ومنتهية مع فحص معدل إعادة التعيين الناتج. الرفض قبل الدخول الأصلي يحفظ الدرجة السابقة.

SetSoundPan / اضبط_توازن_الصوت

(sound: Sound, pan: f32) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

توازن الصوت -1..1.

بث الموسيقى الصريح

LoadMusicStream / حمل_تدفق_موسيقى

(fileName: string) -> result<Music>

التطبيق والخيط الرئيسي وخارج إطار الرسم، مع شروط الجهاز والمالك.

ملفات WAV وOGG وMP3، بمسار نسبة إلى مجلد العمل. المورد تابع لجيل الصوت الحالي.

IsMusicValid / هل_الموسيقى_صالحة

(music: Music) -> bool

فحص كلي، مسموح للمعالجات والدوال الراجعة، دون دخول جهاز أصلي.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

UnloadMusicStream / حرر_تدفق_الموسيقى

(music: Music) -> result<unit>

التطبيق والخيط الرئيسي. يجوز الإغلاق المنطقي داخل إطار وينجح تحرير المورد المغلق.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

PlayMusicStream / شغل_تدفق_الموسيقى

(music: Music) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

IsMusicStreamPlaying / هل_تدفق_الموسيقى_يعمل

(music: Music) -> result<bool>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

UpdateMusicStream / حدث_تدفق_الموسيقى

(music: Music) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

تحديث صريح من التطبيق، دون حلقة بث تلقائية أو استدعاء دالة مصدر.

StopMusicStream / أوقف_تدفق_الموسيقى

(music: Music) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

PauseMusicStream / أوقف_تدفق_الموسيقى_مؤقتا

(music: Music) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

ResumeMusicStream / استأنف_تدفق_الموسيقى

(music: Music) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

SeekMusicStream / اضبط_موضع_تدفق_الموسيقى

(music: Music, position: f32) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

ثوان منتهية بين صفر والطول المبلغ عنه شاملا الطرفين. الطرف الأخير نهاية منطقية. التحديث التالي يعيد الموسيقى الجارية المتكررة أو يوقف غير المتكررة والفارغة. رفض المفكك يغلق المالك.

SetMusicVolume / اضبط_مستوى_الموسيقى

(music: Music, volume: f32) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

مستوى الصوت 0..1.

SetMusicPitch / اضبط_حدة_الموسيقى

(music: Music, pitch: f32) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

درجة صوت موجبة ومنتهية مع فحص معدل إعادة التعيين الناتج. الرفض قبل الدخول الأصلي يحفظ الدرجة السابقة.

SetMusicPan / اضبط_توازن_الموسيقى

(music: Music, pan: f32) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

توازن الصوت -1..1.

GetMusicTimeLength / مدة_الموسيقى

(music: Music) -> result<f32>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetMusicTimePlayed / زمن_الموسيقى_المنقضي

(music: Music) -> result<f32>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

تتبع الأحجام المفحوصة وأجيال المالك والنتائج الدليل. الرفض قبل الدخول يحفظ الحالة.

GetMusicLooping / هل_الموسيقى_تتكرر

(music: Music) -> result<bool>

بيانات مالك للقراءة فقط، مسموحة للمعالجات والدوال الراجعة مع فحص إغلاق المالك.

يقرأ بيانات محفوظة دون دخول جهاز الصوت.

SetMusicLooping / اضبط_تكرار_الموسيقى

(music: Music, looping: bool) -> result<unit>

التطبيق والخيط الرئيسي وجهاز صوت أو مالك حي، مسموح داخل إطار.

تحكم صوتي يتطلب سياق التطبيق ومالك صوت حي.

حدود الأعداد والموارد

يجب أن تكون المدخلات العائمة الفعالة منتهية. أبعاد النافذة وتكبير الكاميرا موجبة. نصف القطر وFPS المستهدف غير سالبين، وسماكة الخط موجبة. يجب أن تبقى الإحداثيات والحسابات الناتجة قابلة للتمثيل حتى عندما تكون المدخلات المفردة منتهية. تحتفظ مستطيلات النسيج الموقعة والمقياس الصفري أو السالب والأشكال المنحلة المقبولة بالسلوك المثبت. تستخدم السجلات إحداثيات f32 وقنوات لون u8 وأحجام الأعداد الدقيقة في كل توقيع.

ترفض نصوص العنوان والمسار NUL. يقبل LoadTexture صيغة PNG فقط. تحل المسارات نسبة إلى مجلد عمل العملية. توفر عائلة الصور الأطلس الدقيق بحجم 32 في 16 RGBA وإشعاره Apache-2.0 OR MIT. يحتاج التحميل وتغيير المرشح والالتفاف إلى إطار مغلق. لا تحتاج هذه العائلات العامة إلى Raylib نظامي أو وحدات مصدر مساعدة.

الحدود الافتراضية 256 MiB لذاكرة الآلة الافتراضية وحساب خلفية مشترك واحد قدره 128 MiB لـRaylib وHTTP. تحسب التخصيصات الأصلية ونسخ العناوين وذاكرة المسارات وتخزين النسيج والذاكرة المحتفظ بها ضمن الحد المناسب. لا يحرر الإغلاق المنطقي التكلفة حتى انتهاء الاستخدام الأصلي. تبقى حدود تعليمات الآلة الافتراضية والزمن وإطارات الاستدعاء والخانات سارية.

يمتلك تنفيذ واحد حجز أجهزة العملية. يتبع النسيج جيل نافذته وتتشارك نسخه الإغلاق. يبطل CloseWindow النسخ قبل تدمير السياق ولا تعيد إعادة الفتح إحياءها. ينجح تكرار UnloadTexture حتى داخل الإطار، وقد يحتفظ الرسم المقبول بالذاكرة حتى العرض أو انتهاء الاستخدام. تسبق فحوص إغلاق المالك غياب الجهاز السابق. يسمح ببيانات القراءة فقط والفحوص الكلية والتحويلات النقية ومساعدات التصادم في المعالجات والاستدعاءات الراجعة. الدخول إلى الجهاز والرسم للتطبيق فقط على الخيط الرئيسي.

يجب إقران BeginDrawing وEndDrawing وBeginMode2D وEndMode2D دون تداخل. أنه وضع الكاميرا قبل الإطار. تحتاج دورة الحياة والتحميل وتغييرات العنوان ومفتاح الخروج وFPS والمرشح والالتفاف إلى إطار مغلق. يسمح بملاحظات عينات الإدخال والتوقيت داخله. يحفظ الرفض قبل الدخول الأصلي الحالة الحالية. يضمن الفشل بعد الآثار تنظيف الموارد المملوكة دون تراجع عام. يهجر الرجوع أو المصيدة أو الحد أو الإلغاء الإطار المفتوح، ويحرر التنظيف عمل GPU قبل نافذته. يحتفظ التحرير الأصلي غير المثبت بالذاكرة والحجز. لا يوجد ضمان قطع قسري داخل العملية لتعليق برنامج تشغيل المضيف.

أحجام النص الصحيحة 1..4096 أو f32 المنتهية 0.5..4096، وتقرب إلى 1/64 مع كسر التعادل نحو الزوجي. يجب أن يكون تباعد المحارف في Ex وPro صفرا. تتطلب TextOptions حقولها الستة، والعرض النشط منته وموجب والتباعد الإضافي للأسطر منته وغير سالب. يستخدم Auto أول محرف قوي أو LTR للفقرات المحايدة، ويتبع Start وEnd ذلك الاتجاه. يشترك الصندوق المنطقي وحدود الحبر في مواضع الرسم. تتبع فواصل الفقرات والأسطر والالتفاف والعناقيد الكبيرة دليل التخطيط. تتضمن رسائل النص تفاصيل scalar_index وscalar أو byte_offset الأصلي، وليست حقول نتيجة جديدة.

ينسخ تحميل الخط بايتات الملف المرخص وتلميحات المحارف. Font وTextLayout مالكان على المعالج يبقيان بعد إعادة إنشاء النافذة، وتبقى بيانات التخطيط بعد إغلاق الخط المخصص. ينجح تحرير الخط الافتراضي دون إغلاقه. يتبع Sound وMusic جيل الصوت، ويبطل التحرير أو إغلاق الجهاز النسخ. يسمح بالتحكم في التشغيل والتحديثات الصريحة داخل إطار. مستوى الصوت 0..1 والتوازن -1..1 والحدة موجبة مع فحص معدل إعادة التعيين. يقبل البحث الطرف الأخير المبلغ عنه نهاية منطقية، ويغلق رفض المفكك مالك الموسيقى. يسمح بالفحوص الكلية وبيانات GetMusicLooping المحفوظة في المعالجات، أما ملاحظات التشغيل فللتطبيق فقط.

تشارك تخصيصات الخط والمفكك والمازج والمحارف والمخابئ والبيانات المحتفظ بها حساب الخلفية. يحجز الصوت مكدس عامل مفحوصا قدره 1 MiB وحارسا 64 KiB حتى نجاح الانضمام. لا ترسل إخفاقات تجهيز رسم النص أي جزء من الطلب الفاشل. يحرر التنظيف عمل المازج والمفكك قبل إغلاق الصوت. راجع التنظيف والمقاطعة للموعد الواحد غير المتجدد وتصريف الإشارات.

الأخطاء والرفض

افحص ok قبل value أو error، وافحص error::code وerror::message. تؤدي قراءة الفرع الخطأ إلى مصيدة. تحدد رموز ASCII الثابتة الإخفاقات، وتضم رسائل Raylib الجديدة اللغتين. تستخدم تشخيصات المصدر لغة CLI المختارة ولا تتبع مفردات المصدر.

الرمز المعنى في ASPL 0.7.0
raylib.invalid_argument مجال أو اختيار تعداد أو علم غير صحيح، أو NUL في العنوان أو المسار، أو نصف قطر سالب أو تكبير أو سماكة غير موجبين.
raylib.numeric_overflow تحويل أو هندسة ناتجة غير قابلة للتمثيل حتى مع معاملات منتهية.
raylib.invalid_order غياب النافذة أو تكرار التهيئة أو رسم خارج إطار أو أزواج رسم أو كاميرا متداخلة أو غير مقترنة أو تغيير ممنوع داخل إطار.
raylib.invalid_context تنفيذ أو خيط أو سياق آثار غير صحيح.
raylib.owner_busy تنفيذ آخر يمتلك حجز الجهاز.
raylib.closed_resource وصول عبر مالك مورد مشترك مغلق منطقيا.
raylib.load_failed فشل قراءة الملف أو فك الصورة أو الصوت المختار أو البحث في الموسيقى. يغلق رفض البحث من المفكك ذلك المالك.
raylib.unsupported_asset صيغة صورة أو صوت غير مختارة.
raylib.invalid_font دليل الخط أو الجداول المطلوبة معطوبة.
raylib.unsupported_font مجموعة خطوط أو CFF/PostScript أو WOFF/WOFF2 أو صور نقطية أو ألوان.
raylib.invalid_text مدخل معطوب أو تحكم غير مدعوم مثل NUL أو الجدولة أو DEL.
raylib.missing_glyph لا يغطي خط مخصص أو افتراضي مقبول العنقود أو تسلسل الوصل.
raylib.resource_limit استنفاد حد الخلفية المشترك أو سعة أصلية محدودة.
raylib.host_unavailable مكتبة مفقودة أو خدمة صوت أو شاشة غير متاحة، ولا ينجح فتح نافذة بلا DISPLAY وWAYLAND_DISPLAY.
raylib.host_incompatible رمز مطلوب مفقود أو بروتوكول أو سياق رسوم غير متوافق.
raylib.initialization_failed فشل تهيئة نافذة أو سياق أو صوت أو بدء تشغيل مقبول مع تحرير آمن.
raylib.host_failure فشل أصلي أو رفع آخر. قد ينهي تعذر إثبات التحرير الأصلي التنفيذ بدلا من ذلك.

تفشل الأبعاد غير الصحيحة أو العنوان ذو NUL قبل اكتساب الشاشة. يمكن أن تنتقل محاولة محررة بأمان إلى نقطة شاشة أخرى مضبوطة. لا تؤدي المعاملات غير الصحيحة أو الميزانيات المستنفدة إلى الانتقال بين المضيفين. إذا فشلت كل محاولات الشاشة بأمان تصف فئة المحاولة الأخيرة كل الخلفيات المجربة.

من الأمثلة المهمة إعادة InitWindow(0, 240, "x") للرمز raylib.invalid_argument، وإعادة SetWindowTitle دون نافذة للرمز raylib.invalid_order، وإعادة كاميرا بتكبير صفري للرمز raylib.invalid_argument. تعيد بداية الكاميرا المتداخلة أو EndDrawing مع وضع كاميرا نشط raylib.invalid_order مع حفظ الزوج الحالي. يغلق تحرير نسخة النسيج كل النسخ، ثم تعيد قراءة العرض raylib.closed_resource. تفشل مقارنة التعدادات الاسمية بأعداد أو بناؤها منها أثناء فحص المصدر بالرمز type-mismatch، وتفشل عمليات الجهاز داخل معالجات HTTP في فحص الآثار عبر مسارات الاستدعاء.

يعيد MeasureText("bad\ttext", 32) الرمز raylib.invalid_text مع scalar_index=3 وscalar=U+0009. يعيد تباعد MeasureTextEx غير الصفري وعرض التخطيط النشط الصفري raylib.invalid_argument. تعيد ملفات الخط المخصص المفقودة raylib.load_failed، والبيانات المطلوبة المعطوبة raylib.invalid_font. يغلق UnloadTextLayout كل النسخ ويعيد القياس اللاحق raylib.closed_resource. يعيد تحميل الصوت دون تهيئة raylib.invalid_order. لا يمكن بناء TextDirection وTextAlignment الاسميين من أعداد. راجع برنامج الهوية دون أجهزة وبرنامج النص والصوت.

تبقى الحالات النهائية 5 للمصيدة و6 للحد و7 للإلغاء و8 لفشل المضيف. تحتفظ النتيجة الأساسية السابقة بنسبة التنظيف المنفصلة. اختر تشخيصات CLI عبر --diagnostic-language=en وتشخيصات البرنامج الناتج عبر --aspl-diagnostic-language=en.

يغطي المرجع الحالي عمليات Raylib البالغ عددها 123 و18 نوعا وستة مخططات و161 ثابتا. تحتفظ جلسات HTTP وحالتها وتقدمها الصريح بمرجع HTTP مصدرا لها. يشرح دليل الجمع ترتيب الإطارات والآثار. يحتفظ المرجع الكامل الأصلي (يفتح في نافذة جديدة) بمساره الخام المنشور وبايتاته. لا تمنح قوائم محولات المساهمين وتجهيزاتهم صفة التشغيل العام.

الحدود المعيارية للإصدار

الحدود المعيارية

هذه حدود أرشيف بيان المطابقة 0.1.1. يربط كل معرّف بالنص المرجعي الذي يملكه، ولا تصف ميزات إدخال ASPL 0.7.0.

ASPL-SEMANTIC-0403
يقتصر إصدار ASPL الأدنى على خمسة أنواع قابلة للتخزين، وتبقى النصوص ثابتة ومنشأة من القيم الحرفية فقط.
ASPL-SEMANTIC-0404
يقتصر إصدار ASPL الأدنى على خمسة أنواع قابلة للتخزين، وتبقى النصوص ثابتة ومنشأة من القيم الحرفية فقط.
ASPL-SEMANTIC-0405
يقتصر إصدار ASPL الأدنى على خمسة أنواع قابلة للتخزين، وتبقى النصوص ثابتة ومنشأة من القيم الحرفية فقط.
ASPL-SEMANTIC-0406
يقتصر إصدار ASPL الأدنى على خمسة أنواع قابلة للتخزين، وتبقى النصوص ثابتة ومنشأة من القيم الحرفية فقط.
ASPL-SEMANTIC-0407
يقتصر إصدار ASPL الأدنى على خمسة أنواع قابلة للتخزين، وتبقى النصوص ثابتة ومنشأة من القيم الحرفية فقط.
ASPL-SEMANTIC-0189
يقبل إصدار ASPL الأدنى ملف مصدر واحداً ولا يوفر الوحدات أو نظام حزم أو معاملات للبرنامج.
ASPL-BYTECODE-0531
صيغة ASPL bytecode خاصة ومتطابقة الإصدار وليست ABI عامة مستقرة.
ASPL-BYTECODE-0532
صيغة ASPL bytecode خاصة ومتطابقة الإصدار وليست ABI عامة مستقرة.
ASPL-BYTECODE-0533
صيغة ASPL bytecode خاصة ومتطابقة الإصدار وليست ABI عامة مستقرة.
ASPL-BYTECODE-0534
صيغة ASPL bytecode خاصة ومتطابقة الإصدار وليست ABI عامة مستقرة.
ASPL-BYTECODE-0535
صيغة ASPL bytecode خاصة ومتطابقة الإصدار وليست ABI عامة مستقرة.
ASPL-CLI-0605
لا يعزل التنفيذ الأصلي الشفرة الأجنبية غير الآمنة.
ASPL-CLI-0606
لا يعزل التنفيذ الأصلي الشفرة الأجنبية غير الآمنة.
ASPL-CLI-0607
لا يعزل التنفيذ الأصلي الشفرة الأجنبية غير الآمنة.
ASPL-CLI-0608
لا يعزل التنفيذ الأصلي الشفرة الأجنبية غير الآمنة.
ASPL-BROWSER-0347
لا تنشئ دالة إخراج المتصفح استيرادًا خارجيًا.
ASPL-BROWSER-0348
لا تضيف دالة إخراج المتصفح جسرًا لنظام الملفات.
ASPL-BROWSER-0349
لا تضيف دالة إخراج المتصفح جسرًا للشبكة.
ASPL-BROWSER-0350
لا تضيف دالة إخراج المتصفح جسرًا للخادم.
ASPL-DIST-0109
يستهدف الإصدار الأصلي الأول Linux x86-64 مع glibc 2.34 أو أحدث فقط.
ASPL-DIST-0144
يوفر SHA-256 فحص سلامة فقط، من دون مصادقة للناشر أو توقيع للإصدار.
ASPL-PERF-0161
تقتصر ادعاءات أداء البناء والمتصفح على الجهاز والبروتوكول والمتصفحات المثبتة في المواصفة.
ASPL-CONFORMANCE-0672
لا يدّعي إصدار ASPL الأدنى الجاهزية للإنتاج.
ASPL-CONFORMANCE-0673
لا يدّعي إصدار ASPL الأدنى الاستبدال الكامل للغة C.
ASPL-CONFORMANCE-0674
لا يَعِد إصدار ASPL الأدنى بمدة دعم أمني محددة.
ASPL-CONFORMANCE-0675
لا يدّعي إصدار ASPL الأدنى ثبات صيغة البايت كود العامة.

تعلم ASPL

المحرر في المتصفح

عدّل الترحيب ثم اختر تشغيل. يجري الفحص والتنفيذ في هذا المتصفح. لا يبدأ التنفيذ إلا عندما تختار تشغيل.

اختر مسارك

ابدأ دون تثبيت من البرنامج الأول في المتصفح. إذا كنت تتعلم البرمجة، اقرأ مدخل الدروس.

لديك خبرة برمجية؟ انتقل إلى البرنامج الأصلي الأول أو التنزيلات ومتطلبات النظام.

ارجع إلى مرجع البرنامج وحالة العملية لفهم دالة البداية وحالة الخروج، أو تصفح مجموعات الأمثلة.

يمكنك أيضا فتح برنامج hello الكامل أدناه في مسودة مستقلة. لن يستبدل مصدرك الحالي ولن يبدأ التنفيذ تلقائيا.

الحدود المعيارية للإصدار

ابدأ

البرنامج الأول في المتصفح

اقرأ عقد البرنامج، ثم عاين برنامج hello الكامل أدناه. اختر مفردات المصدر، ثم افتحه في مسودة جديدة على الصفحة الرئيسية. لن يبدأ التنفيذ حتى تختار تشغيل.

يفحص المتصفح مصدر ASPL 0.7.0 وينفذه محليا. لا ينفذ الملعب برامج ELF ولا يحمل مكتبات Linux المشتركة أو وحدات مصدر المستخدم. تغيير لغة القراءة لا يترجم المسودة.

البرنامج الأصلي الأول

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

التنزيلات ومتطلبات النظام

اختر من الأرشيفات الأصلية والبصمات ومدخلات الحزم وسجل الإصدارات. افحص متطلبات النظام الأصلية والمكتبية قبل التثبيت. Console واجهة Qt اختيارية منفصلة؛ لا يحتاج إليها سطر الأوامر أو ملعب المتصفح.

الحدود المعيارية للإصدار

الدروس

ابدأ دون تثبيت

لا تحتاج إلى خبرة برمجية لتبدأ. افتح البرنامج الأول في المتصفح، واقرأ المصدر والخرج. تغيير لغة التوثيق لا يترجم المصدر أو أسماء المستخدم أو النصوص داخله.

مسار التعلم

ابدأ بالخرج وقراءة الأخطاء. تابع إلى الأسماء والحساب والشروط والحلقات والدوال، ثم إدخال النص وتحويل الأعداد والسلاسل والقوائم والسجلات والنتائج القابلة للاسترداد والملفات الافتراضية.

الدروس مستقلة. ينتهي المسار باختبار حسابي في ملف واحد داخل المتصفح. بعده يمكنك اختيار التثبيت الأصلي والتعلم عن وحدات المصدر. تصفح أمثلة الأساسيات أثناء التعلم.

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

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

تابع إلى درس القوائم.

تابع إلى درس السجلات.

تابع إلى درس النتائج القابلة للاسترداد.

تابع إلى درس ملفات المتصفح الافتراضية.

تابع إلى اختبار في ملف واحد.

اختر إلى أين تتجه بعد ذلك للدروس الأصلية الاختيارية والأدلة العملية.

الحدود المعيارية للإصدار

الحلقات

ما ستتعلمه

ستجمع الأعداد الصحيحة من 1 إلى 5، وتتتبع عدادا ومجموعا متغيرين، وتشرح لماذا تتوقف الحلقة.

قبل أن تبدأ

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

كرر ما دام الشرط صحيحا

تصرح متغير / var بارتباط قابل للتغيير. لكل من counter وsum النوع ص64 / i64، ويبدآن بالقيمتين 1 و0. يحتفظ sum بالمجموع المتراكم. تختبر طالما / while الشرط counter <= 5 قبل كل دورة، بما فيها الأولى. ينفذ الشرط الصحيح الجسم بين القوسين المعقوفين، وينقل الشرط الخاطئ التنفيذ إلى ما بعده.

داخل الجسم، تضيف sum = sum + counter العداد الحالي إلى المجموع. ثم تنتقل counter = counter + 1 إلى العدد الصحيح التالي. يستبدل الإسناد قيمة الارتباط. الترتيب مهم، أضف العدد الحالي قبل زيادة العداد.

تشغل دالة الدخول المحجوزة ابدأ_الرئيسية() -> ص64 / start_main() -> i64 البرنامج. بعد الحلقة، تحول نسق_ص64 / format_i64 المجموع إلى نص، وتكتبه اطبع / print مع نهاية السطر الصريحة \n. الخرج هو 15\n حرفيا. تنهي أرجع 0 / return 0 الأخيرة البرنامج بصورة طبيعية بحالة عملية 0، وهي منفصلة عن المجموع المطبوع.

تتبع الدورات

توقع المجموع والعداد بعد كل تنفيذ للجسم قبل التشغيل.

الدورة العداد قبل الجسم المجموع قبل الجسم المجموع بعد الإضافة العداد بعد التحديث
1 1 0 1 2
2 2 1 3 3
3 3 3 6 4
4 4 6 10 5
5 5 10 15 6

الاختبار التالي هو 6 <= 5، وهو خاطئ. لا ينفذ الجسم دورة سادسة. تحديث العداد هو ما ينهي هذه الحلقة. بدونه يبقى الشرط صحيحا عند 1، ولا يصل التنفيذ إلى الطباعة. ينهي زر الإيقاف مثل هذا التشغيل في المتصفح، لكنه لا يجعل الحلقة تكتمل بصورة طبيعية. لو بدأ العداد عند 6 لما نفذ الجسم أي دورة، ولبقي المجموع 0.

أضف عددا آخر

غير الحد الأعلى فقط من 5 إلى 6. توقع الدورة الإضافية. الخرج المتوقع هو 21\n حرفيا، والحالة الطبيعية 0.

غير حد الحلقة إلى 6. توقع المجموع النهائي وقيمة العداد التي توقف الحلقة.

تلميح: أبق المجموع والعداد الأوليين وتعليمتي التحديث. غير العدد في counter <= 5 فقط.

اعرض الإجابة المشروحة

يبقى مجموع الدورات الخمس الأولى 15. تضيف السادسة العدد 6 فيصبح المجموع 21، ثم تزيد العداد إلى 7. الاختبار 7 <= 6 خاطئ، فتنتهي الحلقة. يطبع البرنامج 21 ونهاية سطر واحدة، ثم يرجع الحالة 0.

تحقق من فهمك

اشرح لماذا يقبل الارتباطان التغيير، ومتى ينفذ الشرط، ولماذا يتجاوز العداد النهائي الحد بواحد. قارن تتبعك بالخرج بعد اختيار التشغيل صراحة. لا تحفظ درجة أو تقدم، ويبقى التنقل مفتوحا. عد إلى مسار الدروس أو اقرأ مرجع التحكم.

lesson-loops-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    متغير sum: ص64 = 0.
    متغير counter: ص64 = 1.
    طالما counter <= 5 {
        sum = sum + counter.
        counter = counter + 1.
    }
    اطبع(نسق_ص64(sum) + "\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "15\n"
native: check 0; success / status 0; stdout "15\n"
نزّل المصدر افتح في المحرر
aspl check lesson-loops-ar.aspl
aspl run lesson-loops-ar.aspl
lesson-loops-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    var sum: i64 = 0;
    var counter: i64 = 1;
    while counter <= 5 {
        sum = sum + counter;
        counter = counter + 1;
    }
    print(format_i64(sum) + "\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "15\n"
native: check 0; success / status 0; stdout "15\n"
نزّل المصدر افتح في المحرر
aspl check lesson-loops-en.aspl
aspl run lesson-loops-en.aspl
lesson-loops-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    متغير sum: ص64 = 0.
    متغير counter: ص64 = 1.
    طالما counter <= 6 {
        sum = sum + counter.
        counter = counter + 1.
    }
    اطبع(نسق_ص64(sum) + "\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "21\n"
native: check 0; success / status 0; stdout "21\n"
نزّل المصدر افتح في المحرر
aspl check lesson-loops-solution-ar.aspl
aspl run lesson-loops-solution-ar.aspl
lesson-loops-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    var sum: i64 = 0;
    var counter: i64 = 1;
    while counter <= 6 {
        sum = sum + counter;
        counter = counter + 1;
    }
    print(format_i64(sum) + "\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "21\n"
native: check 0; success / status 0; stdout "21\n"
نزّل المصدر افتح في المحرر
aspl check lesson-loops-solution-en.aspl
aspl run lesson-loops-solution-en.aspl
الحدود المعيارية للإصدار

الشروط

ما ستتعلمه

ستقارن قيمة بحد فاصل، وتختار إحدى رسالتين، وتشرح ما يحدث للقيم الأصغر من الحد والمساوية له والأكبر منه.

قبل أن تبدأ

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

اختر فرعا

تهيئ دع age = 17 اسما بعدد صحيح. يسأل age >= 18 عما إذا كانت هذه القيمة أكبر من 18 أو مساوية له. تنتج المقارنة قيمة منطقية، تكون صحيحة أو خاطئة، بدلا من عدد نطبعه.

تختبر إذا / if الشرط المنطقي. حين يكون صحيحا يدخل التنفيذ الكتلة الأولى بين القوسين المعقوفين. تقدم وإلا / else الكتلة البديلة للشرط الخاطئ. تنفذ واحدة فقط من هاتين الكتلتين. بعد الكتلة المختارة يستمر التنفيذ إلى تعليمة الإرجاع الأخيرة. تجمع الأقواس تعليمات كل فرع. تساعد المسافة البادئة على رؤية هذه المجموعات لكنها لا تحل محل الأقواس.

عند 17 تكون المقارنة خاطئة، فيطبع الفرع الأدنى Under 18\n، أي أقل من 18. لو كانت صحيحة لطبع الفرع الأعلى 18 or over\n، أي 18 أو أكثر. تبقى هذه النصوص الإنجليزية كما وردت حتى مع الكلمات العربية. تتضمن السلسلتان نهاية سطر صريحة كما في الدرس الأول. تقع أرجع 0 الأخيرة خارج الفرعين، فينتهي أي اختيار بصورة طبيعية بحالة 0.

توقع الحالات الثلاث

أبق الحد عند 18. توقع كل حالة قبل تشغيلها. تنتمي المساواة عمدا إلى الفرع الأعلى لأن العامل هو >=.

قيمة age هل age >= 18 صحيحة؟ الفرع المختار الخرج الحرفي
17 لا، فهي أقل من 18 وإلا، الأدنى Under 18\n
18 نعم، فهي تساوي 18 إذا، الأعلى 18 or over\n
19 نعم، فهي أكبر من 18 إذا، الأعلى 18 or over\n

تستبعد > المساواة، فتختار القيمة 18 الفرع الأدنى عند استخدامها. تهيئ = ارتباطا أو تسند إليه قيمة، وتقارن == قيمتين للتحقق من المساواة. نحتاج هنا إلى >= ليشمل المساواة والقيم الأكبر معا.

ضع المساواة في الفرع الأعلى

غير القيمة الأولية لـ age فقط من 17 إلى 18. أبق المقارنة كما هي. الخرج المتوقع هو 18 or over\n حرفيا، والحالة الطبيعية 0.

غير age إلى 18. اشرح لماذا تطبع الرسالة العليا الآن.

تلميح: غير العدد الصحيح في تصريح الارتباط. أبق >= 18 الذي يشمل المساواة.

اعرض الإجابة المشروحة

المقارنة 18 >= 18 صحيحة، فتنفذ الكتلة الأولى وحدها وتطبع 18 or over ثم نهاية سطر واحدة. يتجاوز التنفيذ الرسالة الدنيا. وتعطي تعليمة الإرجاع الأخيرة المشتركة الحالة 0.

غير الآن 18 إلى 19 في الارتباط، مع إبقاء الحد 18، وقارن توقعك الثالث. نقدم هذه النسخة الكاملة المتحقق منها للمقارنة.

تختار القيمتان 18 و19 الرسالة العليا لسببين مختلفين: المساواة والأكبر من. لا تطبع أي من الحالتين الرسالتين معا.

تحقق من فهمك

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

lesson-conditions-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع age = 17.
    إذا age >= 18 {
        اطبع("18 or over\n").
    } وإلا {
        اطبع("Under 18\n").
    }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Under 18\n"
native: check 0; success / status 0; stdout "Under 18\n"
نزّل المصدر افتح في المحرر
aspl check lesson-conditions-ar.aspl
aspl run lesson-conditions-ar.aspl
lesson-conditions-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let age = 17;
    if age >= 18 {
        print("18 or over\n");
    } else {
        print("Under 18\n");
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Under 18\n"
native: check 0; success / status 0; stdout "Under 18\n"
نزّل المصدر افتح في المحرر
aspl check lesson-conditions-en.aspl
aspl run lesson-conditions-en.aspl
lesson-conditions-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع age = 18.
    إذا age >= 18 {
        اطبع("18 or over\n").
    } وإلا {
        اطبع("Under 18\n").
    }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "18 or over\n"
native: check 0; success / status 0; stdout "18 or over\n"
نزّل المصدر افتح في المحرر
aspl check lesson-conditions-solution-ar.aspl
aspl run lesson-conditions-solution-ar.aspl
lesson-conditions-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let age = 18;
    if age >= 18 {
        print("18 or over\n");
    } else {
        print("Under 18\n");
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "18 or over\n"
native: check 0; success / status 0; stdout "18 or over\n"
نزّل المصدر افتح في المحرر
aspl check lesson-conditions-solution-en.aspl
aspl run lesson-conditions-solution-en.aspl
lesson-conditions-above-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع age = 19.
    إذا age >= 18 {
        اطبع("18 or over\n").
    } وإلا {
        اطبع("Under 18\n").
    }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "18 or over\n"
native: check 0; success / status 0; stdout "18 or over\n"
نزّل المصدر افتح في المحرر
aspl check lesson-conditions-above-ar.aspl
aspl run lesson-conditions-above-ar.aspl
lesson-conditions-above-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let age = 19;
    if age >= 18 {
        print("18 or over\n");
    } else {
        print("Under 18\n");
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "18 or over\n"
native: check 0; success / status 0; stdout "18 or over\n"
نزّل المصدر افتح في المحرر
aspl check lesson-conditions-above-en.aspl
aspl run lesson-conditions-above-en.aspl
الحدود المعيارية للإصدار

الأدلة

أدلة عملية

ابدأ من مصادر الأدلة العملية للعمل مع الملفات والتوافق مع C وHTTP وRaylib.

مرجع اللغة

اقرأ البرنامج وحالة العملية لعقد دالة البداية ومجال حالة الخروج ومثال كامل.

للتفاصيل الأصلية، اقرأ أوامر Linux ومراحلها والإدخال الأصلي والبرامج المبنية.

ارجع مباشرة إلى قواعد 0.7.0 الحالية:

مرجع الواجهات

ارجع إلى مصادر مرجع الواجهات للتواقيع والحدود والأخطاء.

يغطي مرجع الملفات النصية ودليل الملفات العملي الحاليان المضيفين.

الأرشيف

المواصفات المؤرشفة تحتفظ بنطاقها التاريخي ولغاتها المتاحة. لا تصف تلقائيا الإصدار الحالي.

الدوال والقيم القابلة للاستدعاء · وحدات المصدر والاستيراد والتصدير.

تواقيع C والمخازن وإعارة النص الحالية.

الحدود المعيارية للإصدار

الأمثلة

مجموعات بحسب الموضوع

الحدود المعيارية للإصدار

الأساسيات

البرامج والمصادر

البرامج المشتركة للمتصفح والمضيف الأصلي. حلقة حد التنفيذ للمتصفح فقط.

عائلات كاملة بمصادرها المقدمة وإدخالها ونتائجها المتوقعة:

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

الدوال على المستوى الأعلى · القيم القابلة للاستدعاء المعلنة النوع.

الحدود المعيارية للإصدار

النصوص والمجموعات والملفات

البرامج والتجهيز

تدعم أمثلة ASPL 0.7.0 الكاملة هذه المتصفح والتنفيذ الأصلي. تعرض صفحات العائلات الصيغ المورّدة والإدخال المطلوب والنتائج الدقيقة قبل المصدر. ملفات المتصفح بيانات تشغيل مؤقتة لكل مسودة.

اقرأ الملفات النصية والإخفاقات القابلة للاسترداد قبل استيراد البيانات أو تنزيلها. تبقى تنزيلات المصدر الأصلي في بطاقاته.

الحدود المعيارية للإصدار

وحدات المصدر والبرامج الكاملة

البرامج والمصادر

ASPL 0.7.0 المختارة. تصرّح كل مجموعة بالمضيف ومفردات المصدر المورّدة والملفات المطلوبة قبل المصدر. تفتح البرامج المدعومة في المتصفح مسودات جديدة دون التنفيذ، وتستخدم وحدات المصدر الأصلية تنزيلات دقيقة وأوامر أصلية.

وحدات المصدر الأصلية

وحدات المصدر أصلية فقط. احتفظ بالمدخل بجانب مساعده المطلوب. لا تحتاج مجموعات الوحدات هذه ملفات بيانات. لا يوفر استيراد ملفات تشغيل المتصفح محمّل مصدر. ابدأ بـالتثبيت الأصلي.

برنامج متقدم في ملف واحد

اللغة الحسابية المصغرة مثال متقدم لتحليل الرموز والنحو والتفسير وتوليد المصدر. يعمل في المتصفح وأصليا، ويحتاج demo.txt لعرضه المفحوص، ومصدره الإنجليزي وحده مورّد. إنه منفصل عن اختبار المبتدئين. يظل شرحه الأصلي متاحا من صفحة المجموعة.

للأمثلة المشتركة الأصغر، راجع الدوال على المستوى الأعلى والقيم القابلة للاستدعاء المعلنة النوع.

الحدود المعيارية للإصدار

التوافق مع C

البرامج والمصادر

المضيف الأصلي فقط، إصدار ASPL 0.7.0 المنشور. تحتاج البرامج Linux x86-64 مع glibc ولا تعمل في ساحة التجربة على الإنترنت. تسرد كل صفحة المكتبات المشتركة والنسختين العربية والإنجليزية والأوامر والنتائج الدقيقة المتوقعة قبل التشغيل. لا أسطر إدخال أو وحدات مصدر أو ملفات بيانات مطلوبة.

ثبّت الأداة الأصلية · اتبع دليل C · راجع الواجهة الخارجية.

ملفات تعريف المحوّلات الخارجية

التواقيع الثابتة الدقيقة

يستخدم abs وstrlen المكتبة libc.so.6 وتوقيع ص32 الدقيق وإعارة نص UTF-8 منسوخة. لا يطبع النجاح شيئا ويخرج بالحالة 0.

بايتات مخزن منسوخة

يستخدم المخزن وmemset المكتبتين أساسي::سي وlibc.so.6 لفحص تخزين البايتات المنسوخ والنسخ المشتركة ومديات الإخراج والاستخراج الأكبر من السعة والإغلاق المتكرر. لا يطبع النجاح شيئا ويخرج بالحالة 0.

حدود النشر والإدارة

توفر أداة الإنتاج العامة الأمثلة أعلاه. تستبعد تجهيزات اختبار الاستدعاءات الراجعة الخاصة بالمساهمين. لا تكتسب التصريحات الخارجية العادية غير الآمنة امتيازات الإدارة. استخدم مجموعتي HTTP وRaylib المنفصلتين لواجهاتهما الموردة والمراجعة.

يحتفظ مصدر دليل C الأصلي (يفتح في نافذة جديدة) بتعليمات 0.5.0 السابقة وسياق المساهمين. اتبع الدليل الحالي أعلاه لإصدار 0.7.0 المنشور.

الحدود المعيارية للإصدار

HTTP

البرامج الأصلية ومصادرها

المضيف الأصلي فقط، ASPL 0.7.0 المنشور. اتبع التثبيت الأصلي ودليل HTTP والواجهة والحدود والأخطاء. احفظ كل نسخة مصدر في مجلد منفصل مع وحداتها المطلوبة الدقيقة. تسبق متطلبات النظراء وملفات TLS ومجلد العمل المصدر. لا إجراء لفتح مسودة متصفح أو تنفيذها.

دليل HTTP الخام السابق (يفتح في نافذة جديدة). يبقى بنطاق إصداره السابق؛ استخدم الدليل الحالي أعلاه لـ0.7.0. تعليمات النشر عمل منفصل.

اتبع دليل النشر الحالي للشهادات والثقة وإعدادات الطرف العلوي.

http-direct-tls-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد أساسي::ويب.
استورد settings.aspl بسم app.
استورد handlers.لبات بسم handlers.
دالة ابدأ_الرئيسية() -> ص64 {
    دع result = ويب::اخدم(app::server(صواب), handlers::routes(),
        app::Config { upstream: "https://localhost:9443/hello", ca: "server.pem" },
        app::State { count: 0 }).
    إذا ليس result::نجاح { اطبع(result::الخطأ::الرمز). أرجع 1. }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout ""
نزّل المصدر
aspl check http-direct-tls-ar.aspl
aspl run http-direct-tls-ar.aspl
http-direct-tls-en · ASPL 0.7.0

المضيف الأصلي فقط

import core::http;
import settings.aspl as app;
import handlers.لبات as handlers;
fn start_main() -> i64 {
    let result = http::serve(app::server(true), handlers::routes(),
        app::Config { upstream: "https://localhost:9443/hello", ca: "server.pem" },
        app::State { count: 0 });
    if not result::ok { print(result::error::code); return 1; }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout ""
نزّل المصدر
aspl check http-direct-tls-en.aspl
aspl run http-direct-tls-en.aspl
http-client-tls-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد requests.لبات بسم requests.
دالة ابدأ_الرئيسية() -> ص64 { أرجع requests::exercise("https://localhost:8443", صواب). }

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "checked text, JSON, 00 FF 41, and 404"
نزّل المصدر
aspl check http-client-tls-ar.aspl
aspl run http-client-tls-ar.aspl
http-client-tls-en · ASPL 0.7.0

المضيف الأصلي فقط

import requests.لبات as requests;
fn start_main() -> i64 { return requests::exercise("https://localhost:8443", true); }

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "checked text, JSON, 00 FF 41, and 404"
نزّل المصدر
aspl check http-client-tls-en.aspl
aspl run http-client-tls-en.aspl
http-default-trust-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد أساسي::ويب.
دالة ابدأ_الرئيسية() -> ص64 {
    دع outbound = ويب::أنشئ_طلب("GET", "https://localhost:9443/hello")::قيمة.
    دع reply = ويب::اطلب(outbound, ويب::خيارات_طلب()).
    إذا ليس reply::نجاح { اطبع(reply::الخطأ::الرمز). أرجع 1. }
    اطبع(ويب::فك_نص(reply::قيمة::متن)::قيمة).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "مرحبا من ASPL"
نزّل المصدر
aspl check http-default-trust-ar.aspl
aspl run http-default-trust-ar.aspl
http-default-trust-en · ASPL 0.7.0

المضيف الأصلي فقط

import core::http;
fn start_main() -> i64 {
    let outbound = http::client_request("GET", "https://localhost:9443/hello")::value;
    let reply = http::request(outbound, http::client_options());
    if not reply::ok { print(reply::error::code); return 1; }
    print(http::decode_utf8(reply::value::body)::value);
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "مرحبا من ASPL"
نزّل المصدر
aspl check http-default-trust-en.aspl
aspl run http-default-trust-en.aspl
http-refusal-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد أساسي::ويب.
دالة ابدأ_الرئيسية() -> ص64 {
    دع outbound = ويب::أنشئ_طلب("GET", "http://127.0.0.1:9/")::قيمة.
    دع reply = ويب::اطلب(outbound, ويب::خيارات_طلب()).
    إذا reply::نجاح { أرجع 1. }
    اطبع(reply::الخطأ::الرمز).
    إذا reply::الخطأ::الرمز ليس يطابق "http.connect_failed" { أرجع 2. }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "http.connect_failed"
نزّل المصدر
aspl check http-refusal-ar.aspl
aspl run http-refusal-ar.aspl
http-refusal-en · ASPL 0.7.0

المضيف الأصلي فقط

import core::http;
fn start_main() -> i64 {
    let outbound = http::client_request("GET", "http://127.0.0.1:9/")::value;
    let reply = http::request(outbound, http::client_options());
    if reply::ok { return 1; }
    print(reply::error::code);
    if reply::error::code not matches "http.connect_failed" { return 2; }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "http.connect_failed"
نزّل المصدر
aspl check http-refusal-en.aspl
aspl run http-refusal-en.aspl
http-limits-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد أساسي::ويب.
دالة ابدأ_الرئيسية() -> ص64 {
    متغير settings = ويب::إعدادات_تنفيذ().
    settings::اتصالات_صادرة = 1.
    دع invalid = ويب::اضبط(settings).
    إذا invalid::نجاح أو invalid::الخطأ::الرمز ليس يطابق "http.invalid_argument" { أرجع 1. }
    settings::اتصالات_عميل_خاملة = 1.
    إذا ليس ويب::اضبط(settings)::نجاح { أرجع 2. }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout ""
نزّل المصدر
aspl check http-limits-ar.aspl
aspl run http-limits-ar.aspl
http-limits-en · ASPL 0.7.0

المضيف الأصلي فقط

import core::http;
fn start_main() -> i64 {
    var settings = http::runtime_config();
    settings::outbound_connections = 1;
    let invalid = http::configure(settings);
    if invalid::ok or invalid::error::code not matches "http.invalid_argument" { return 1; }
    settings::idle_client_connections = 1;
    if not http::configure(settings)::ok { return 2; }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout ""
نزّل المصدر
aspl check http-limits-en.aspl
aspl run http-limits-en.aspl
الحدود المعيارية للإصدار

Raylib

برامج Raylib الأصلية

المضيف الأصلي فقط، ASPL 0.7.0 المنشور. افحص وابن دون أجهزة. تحتاج برامج النافذة إلى شاشة Wayland/EGL أو X11/GLX مدعومة وOpenGL 3.3 core، والصوت أيضا إلى خدمة PulseAudio متوافقة أو جهاز ALSA. لا تحتاج عائلة الهوية والنصوص إلى أي منهما.

الدليل · الواجهة والحدود والأخطاء.

تحدد كل عائلة مصادرها الموردة الدقيقة ونتائجها المفحوصة وأصولها وإشعاراتها. لا تتوفر لهذه البرامج عملية فتح في المتصفح. محولات المساهمين وتجهيزات التحقق ليست عائلات برامج قابلة للتنزيل. إرشادات يحتفظ مصدر الدليل الأصلي (يفتح في نافذة جديدة) بنطاقه المنشور.

النشر ومكتبات المضيف.

raylib-window-mixed · ASPL 0.7.0

المضيف الأصلي فقط

// Run with: aspl run docs/examples/raylib-window.mixed.aspl
// Press Enter twice to observe title replacement and a fresh window.
import core::raylib;
استورد أساسي::رايليب.

fn start_main() -> i64 {
    let flags = raylib::اضبط_أعلام_الإعداد(raylib::FLAG_WINDOW_RESIZABLE);
    if not flags::ok { print(flags::error::message); return 1; }
    let opened = رايليب::InitWindow(640, 360, "ASPL / نافذة رايليب");
    if not opened::ok { print(opened::error::message); return 2; }
    if not raylib::هل_النافذة_جاهزة() { return 3; }
    let titled = raylib::SetWindowTitle("ASPL title / عنوان جديد");
    if not titled::ok { print(titled::error::message); return 4; }
    print("Window ready. Press Enter to close and reopen. / اضغط إدخال لإعادة الفتح.\n");
    let first = read_line();
    let closed = رايليب::أغلق_النافذة();
    if not closed::ok { print(closed::error::message); return 5; }
    if raylib::IsWindowReady() { return 6; }
    let reopened = raylib::هيئ_نافذة(640, 360, "ASPL reopened / نافذة جديدة");
    if not reopened::ok { print(reopened::error::message); return 7; }
    print("Window reopened. Press Enter to finish. / اضغط إدخال للإنهاء.\n");
    let second = read_line();
    let finished = raylib::CloseWindow();
    if not finished::ok { print(finished::error::message); return 8; }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "Window ready. Press Enter to close and reopen. / اضغط إدخال لإعادة الفتح.\nWindow reopened. Press Enter to finish. / اضغط إدخال للإنهاء.\n"
scripted stdin lines: ["",""]
نزّل المصدر
aspl check raylib-window-mixed.aspl
aspl run raylib-window-mixed.aspl
raylib-frames-mixed · ASPL 0.7.0

المضيف الأصلي فقط

// Run with: aspl run docs/examples/raylib-frames.mixed.aspl
// Two brief clear-and-present loops show fresh timing after reopening.
import core::raylib;
استورد أساسي::رايليب.

fn draw_frames() -> i64 {
    var frame: i64 = 0;
    while frame < 30 {
        let begun = raylib::ابدأ_الرسم();
        if not begun::ok { print(begun::error::message); return 1; }
        var color = raylib::SKYBLUE;
        if frame >= 15 { color = رايليب::MAROON; }
        let cleared = رايليب::ClearBackground(color);
        if not cleared::ok { print(cleared::error::message); return 2; }
        let ended = raylib::أنه_الرسم();
        if not ended::ok { print(ended::error::message); return 3; }
        frame = frame + 1;
    }
    let time = raylib::الزمن();
    let delta = raylib::GetFrameTime();
    let fps = رايليب::معدل_الإطارات();
    if not time::ok or not delta::ok or not fps::ok { return 4; }
    print("Frames / إطارات: time="); print(format_f64(time::value));
    print(" frame="); print(format_f32(delta::value));
    print(" fps="); print(format_i64(i64(fps::value))); print("\n");
    return 0;
}

fn start_main() -> i64 {
    let target = raylib::SetTargetFPS(60);
    if not target::ok { print(target::error::message); return 1; }
    var generation: i64 = 0;
    while generation < 2 {
        let opened = رايليب::هيئ_نافذة(640, 360, "ASPL frames / إطارات رايليب");
        if not opened::ok { print(opened::error::message); return 2; }
        if raylib::زمن_الإطار()::value not match 0.0 or raylib::GetFPS()::value not match 0 { return 3; }
        let drawn = draw_frames();
        if drawn not match 0 { return drawn; }
        let closed = raylib::أغلق_النافذة();
        if not closed::ok { print(closed::error::message); return 4; }
        generation = generation + 1;
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout undefined
نزّل المصدر
aspl check raylib-frames-mixed.aspl
aspl run raylib-frames-mixed.aspl
raylib-shapes-mixed · ASPL 0.7.0

المضيف الأصلي فقط

import core::raylib;
استورد أساسي::رايليب.
fn start_main() -> i64 {
    if not raylib::InitWindow(640, 360, "ASPL Camera2D shapes")::ok { return 1; }
    let camera = رايليب::كاميرا2 {
        إزاحة: raylib::Vector2 { x: 320.0, y: 180.0 },
        هدف: raylib::Vector2 { x: 0.0, y: 0.0 }, دوران: 15.0, تكبير: 1.5
    };
    if not raylib::SetTargetFPS(60)::ok { return 2; }
    var frame: i32 = 0;
    while frame < 20 and not raylib::WindowShouldClose()::value {
        if not raylib::BeginDrawing()::ok { return 3; }
        if not رايليب::امسح_الخلفية(raylib::RAYWHITE)::ok { return 4; }
        if not raylib::BeginMode2D(camera)::ok { return 5; }
        if not raylib::DrawRectanglePro(raylib::Rectangle { x: -100.0, y: -50.0, width: 80.0, height: 60.0 },
            raylib::Vector2 { x: 40.0, y: 30.0 }, 20.0, raylib::BLUE)::ok { return 6; }
        if not raylib::DrawCircleV(raylib::Vector2 { x: 50.0, y: 0.0 }, 35.0, raylib::RED)::ok { return 7; }
        if not raylib::DrawLineEx(raylib::Vector2 { x: -150.0, y: 70.0 }, raylib::Vector2 { x: 150.0, y: 70.0 }, 4.0, raylib::DARKGRAY)::ok { return 8; }
        if not raylib::DrawTriangle(raylib::Vector2 { x: 100.0, y: -60.0 }, raylib::Vector2 { x: 100.0, y: 0.0 },
            raylib::Vector2 { x: 150.0, y: 0.0 }, raylib::GREEN)::ok { return 9; }
        if not raylib::EndMode2D()::ok { return 10; }
        if not raylib::DrawPixel(10, 10, raylib::BLACK)::ok { return 11; }
        if not raylib::DrawRectangleLines(5, 5, 630, 350, raylib::GRAY)::ok { return 12; }
        if not raylib::EndDrawing()::ok { return 13; }
        frame = frame + 1;
    }
    if not raylib::CloseWindow()::ok { return 14; }
    print("camera shapes complete");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "camera shapes complete"
نزّل المصدر
aspl check raylib-shapes-mixed.aspl
aspl run raylib-shapes-mixed.aspl
الحدود المعيارية للإصدار

جمع الأعداد من 1 إلى 10

ما الذي يفعله البرنامج

يجمع هذا البرنامج الكامل الأعداد الصحيحة من 1 إلى 10. يستخدم روابط أعداد صحيحة قابلة للتغيير وحلقة while وعبارة if. يبقى المصدر كما هو عند تغيير لغة القراءة.

المصدر العربي

تستخدم هذه النسخة مفردات عربية. افتحها في مسودة مستقلة على الصفحة الرئيسية؛ لن تستبدل مسودة أخرى ولن تعمل تلقائيا.

المصدر الإنجليزي

تستخدم هذه النسخة مفردات إنجليزية. تنتمي إلى عائلة المثال sum نفسها التي تضم النسختين العربية والمختلطة.

المصدر المختلط

تستخدم هذه النسخة المفردات العربية والإنجليزية معا. إنها ملف مصدر مستقل، ولا يولد الموقع ترجمة له.

تحقق من النتيجة

يسجل الفهرس النتيجة المفحوصة لمضيف المتصفح والمضيف الأصلي. توقع الخرج وحالة العملية المعادة قبل توسيع النتيجة.

اعرض النتائج المتوقعة للمضيفين في المصدر الإنجليزي.
{
  "browser": {
    "check": "success",
    "class": "success",
    "output": "55\n",
    "processStatus": 0
  },
  "native": {
    "check": 0,
    "status": 0,
    "output": "55\n"
  }
}
الحدود المعيارية للإصدار

مصادر الأدلة العملية

المراجع المتاحة

تحتفظ مصادر الأدلة الخام التالية بنطاق الإصدار المذكور في كل مستند؛ لا تفترض أنه مراجعة كاملة للإصدار 0.7.0. HTTP وRaylib خاصان بالمضيف الأصلي.

وحدات المصدر الأصلية مع تصحيح تصدير التعريف الخاص.

الحدود المعيارية للإصدار

مصادر مرجع الواجهات

المراجع المتاحة

تحتفظ مصادر الأدلة الخام التالية بنطاق الإصدار المذكور في كل مستند؛ لا تفترض أنه مراجعة كاملة للإصدار 0.7.0. التوافق مع C وHTTP وRaylib خاص بالمضيف الأصلي.

تواقيع C والمخازن وإعارة النص الحالية.

الحدود المعيارية للإصدار

المواصفات المؤرشفة

النطاق التاريخي واللغة المتاحة

مواصفة ASPL MVP التاريخية، باللغة الأصلية الإنجليزية محفوظة للرجوع إلى القرارات السابقة. لا توجد هنا ترجمة عربية تاريخية مكافئة. يغير زر اللغة واجهة الفهرس فقط ويحافظ على نص المصدر.

ارجع إلى مرجع البرنامج الحالي لعقد دالة البداية في الإصدار 0.7.0.

اقرأ الحدود التاريخية الستة والعشرين أو تصفح فهرس القرارات الأصلي بالإنجليزية.

الحدود المعيارية للإصدار

حدود MVP الأصلية

نطاق MVP الأصلي

يسجل هذا العرض الحدود التاريخية الستة والعشرين من مواصفة ASPL MVP الأصلية وفهرس مطابقة 0.1.1 المؤرشف. يصف ذلك النطاق التاريخي، ولا يصف جميع قواعد ASPL 0.7.0 أو قدراته. قد يظل بعض القيود ساريا؛ راجع الإرشادات الحالية قبل الاعتماد عليه.

مصادر المواصفات الأصلية متاحة بالإنجليزية فقط. يشرح هذا العرض الثنائي اللغة نطاقها، وليس ترجمة لتلك المواصفات. اقرأ المواصفة الأصلية أو فهرس القرارات.

ASPL-SEMANTIC-0403

القيد التاريخي في MVP: يقتصر إصدار ASPL الأدنى على خمسة أنواع قابلة للتخزين، وتبقى النصوص ثابتة ومنشأة من القيم الحرفية فقط.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-SEMANTIC-0404

القيد التاريخي في MVP: يقتصر إصدار ASPL الأدنى على خمسة أنواع قابلة للتخزين، وتبقى النصوص ثابتة ومنشأة من القيم الحرفية فقط.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-SEMANTIC-0405

القيد التاريخي في MVP: يقتصر إصدار ASPL الأدنى على خمسة أنواع قابلة للتخزين، وتبقى النصوص ثابتة ومنشأة من القيم الحرفية فقط.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-SEMANTIC-0406

القيد التاريخي في MVP: يقتصر إصدار ASPL الأدنى على خمسة أنواع قابلة للتخزين، وتبقى النصوص ثابتة ومنشأة من القيم الحرفية فقط.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-SEMANTIC-0407

القيد التاريخي في MVP: يقتصر إصدار ASPL الأدنى على خمسة أنواع قابلة للتخزين، وتبقى النصوص ثابتة ومنشأة من القيم الحرفية فقط.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-SEMANTIC-0189

القيد التاريخي في MVP: يقبل إصدار ASPL الأدنى ملف مصدر واحداً ولا يوفر الوحدات أو نظام حزم أو معاملات للبرنامج.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-BYTECODE-0531

القيد التاريخي في MVP: صيغة ASPL bytecode خاصة ومتطابقة الإصدار وليست ABI عامة مستقرة.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-BYTECODE-0532

القيد التاريخي في MVP: صيغة ASPL bytecode خاصة ومتطابقة الإصدار وليست ABI عامة مستقرة.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-BYTECODE-0533

القيد التاريخي في MVP: صيغة ASPL bytecode خاصة ومتطابقة الإصدار وليست ABI عامة مستقرة.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-BYTECODE-0534

القيد التاريخي في MVP: صيغة ASPL bytecode خاصة ومتطابقة الإصدار وليست ABI عامة مستقرة.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-BYTECODE-0535

القيد التاريخي في MVP: صيغة ASPL bytecode خاصة ومتطابقة الإصدار وليست ABI عامة مستقرة.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-CLI-0605

القيد التاريخي في MVP: لا يعزل التنفيذ الأصلي الشفرة الأجنبية غير الآمنة.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-CLI-0606

القيد التاريخي في MVP: لا يعزل التنفيذ الأصلي الشفرة الأجنبية غير الآمنة.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-CLI-0607

القيد التاريخي في MVP: لا يعزل التنفيذ الأصلي الشفرة الأجنبية غير الآمنة.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-CLI-0608

القيد التاريخي في MVP: لا يعزل التنفيذ الأصلي الشفرة الأجنبية غير الآمنة.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-BROWSER-0347

القيد التاريخي في MVP: لا تنشئ دالة إخراج المتصفح استيرادًا خارجيًا.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-BROWSER-0348

القيد التاريخي في MVP: لا تضيف دالة إخراج المتصفح جسرًا لنظام الملفات.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-BROWSER-0349

القيد التاريخي في MVP: لا تضيف دالة إخراج المتصفح جسرًا للشبكة.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: إرشادات HTTP الأصلية.

ASPL-BROWSER-0350

القيد التاريخي في MVP: لا تضيف دالة إخراج المتصفح جسرًا للخادم.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: إرشادات HTTP الأصلية.

ASPL-DIST-0109

القيد التاريخي في MVP: يستهدف الإصدار الأصلي الأول Linux x86-64 مع glibc 2.34 أو أحدث فقط.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: التنزيلات ومتطلبات المضيف.

ASPL-DIST-0144

القيد التاريخي في MVP: يوفر SHA-256 فحص سلامة فقط، من دون مصادقة للناشر أو توقيع للإصدار.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: التنزيلات ومتطلبات المضيف.

ASPL-PERF-0161

القيد التاريخي في MVP: تقتصر ادعاءات أداء البناء والمتصفح على الجهاز والبروتوكول والمتصفحات المثبتة في المواصفة.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-CONFORMANCE-0672

القيد التاريخي في MVP: لا يدّعي إصدار ASPL الأدنى الجاهزية للإنتاج.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-CONFORMANCE-0673

القيد التاريخي في MVP: لا يدّعي إصدار ASPL الأدنى الاستبدال الكامل للغة C.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-CONFORMANCE-0674

القيد التاريخي في MVP: لا يَعِد إصدار ASPL الأدنى بمدة دعم أمني محددة.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

ASPL-CONFORMANCE-0675

القيد التاريخي في MVP: لا يدّعي إصدار ASPL الأدنى ثبات صيغة البايت كود العامة.

المصدر الأصلي بالإنجليزية. الإرشادات الحالية ذات الصلة: مدخل مرجع اللغة للإصدار ASPL 0.7.0.

الحدود المعيارية للإصدار

تثبيت Console وإدارته

التحقق من أرشيف Console المنفصل

Console واجهة ASPL 0.7.0 المكتبية الاختيارية. ثبت الأداة الأصلية منفصلا، وافحص متطلبات مضيف Qt. نزّل أرشيف Console وملف SHA256SUMS الخاص به في مجلد جديد منفصل عن تنزيلات الأداة الأصلية. توقف عند فشل أي خطوة تحقق.

sha256sum --check SHA256SUMS &&
tar -tJf aspl-console-0.7.0-linux-x86_64.tar.xz &&
tar -xJf aspl-console-0.7.0-linux-x86_64.tar.xz &&
./aspl-console-0.7.0-linux-x86_64/bin/aspl-console --version
./aspl-console-0.7.0-linux-x86_64/bin/aspl-console --help

توقع ASPL Console 0.7.0. تتضمن المساعدة --aspl <PATH> ومسار مصدر اختياري. حتى المساعدة والإصدار يهيئان Qt؛ قد يمنع غياب Qt أو إضافة المنصة أو شاشة صالحة بدء التطبيق. راجع README الأصلي وبيانات الإصدار.

اختيار الأداة وملف المصدر

./aspl-console-0.7.0-linux-x86_64/bin/aspl-console --aspl "$HOME/.local/bin/aspl" hello.aspl

يحدد التطبيق المصدر دون تنفيذه. اختر تشغيل لبدء التنفيذ. يبدأ Console بالعربية، وتختار قائمة اللغة الإنجليزية. يستخدم مجلد ملف المصدر المختار دليلا للعمل. تذهب أسطر الإدخال إلى البرنامج الجاري. احفظ المصدر قبل التشغيل، واستخدم مسار الأوامر الأصلية لبناء برنامج مستقل.

تثبيت Console وإدارته

يمكنك التشغيل مباشرة من المجلد المستخرج. للتثبيت في بادئة المستخدم، انسخ bin/ وshare/ من الأرشيف إلى المجلدين المطابقين تحت $HOME/.local/. احتفظ بـshare/aspl-console/translations/ بجانب مجلد bin/ للتثبيت كي تتاح اللغتان. يتضمن الأرشيف أيضا مدخل سطح مكتب وأيقونة ورخصا وإشعارات. افحص ملفات Console الموجودة قبل استبدالها.

mkdir -p "$HOME/.local/bin" "$HOME/.local/share"
cp -a aspl-console-0.7.0-linux-x86_64/bin/. "$HOME/.local/bin/"
cp -a aspl-console-0.7.0-linux-x86_64/share/. "$HOME/.local/share/"
"$HOME/.local/bin/aspl-console" --version

رقّ Console منفصلا بأرشيف إصداره وبصماته ومتطلباته. احتفظ بالأرشيف السابق أو مجلد الإصدار الكامل. للرجوع، شغل الملف التنفيذي من المجلد السابق مع مسار ASPL المقصود وتحقق من الإصدارين. لا يغير تعديل وصلة ASPL وحدها إصدار Console.

للتثبيت المستخرج، احذف مجلد Console المحدد فقط. للتثبيت المنسوخ في بادئة المستخدم، احذف فقط الملف التنفيذي ومدخل سطح المكتب والأيقونة وملفات الترجمة المملوكة لـConsole والمحددة في بيانات الإصدار. أبق مجلدي bin/ وshare/ المشتركين وASPL ومصادرك. افحص اختيار PATH إذا بقي تثبيت آخر لـConsole.

rm "$HOME/.local/bin/aspl-console"
rm "$HOME/.local/share/applications/aspl-console.desktop"
rm "$HOME/.local/share/icons/hicolor/scalable/apps/aspl-console.svg"
rm "$HOME/.local/share/aspl-console/translations/aspl_console_ar.qm"
rm "$HOME/.local/share/aspl-console/translations/aspl_console_en.qm"
الحدود المعيارية للإصدار

دالة البداية دون خرج

الغرض والنتيجة

يعرف هذا البرنامج دالة البداية ويرجع 0 دون خرج. مثال الخرج في صفحة اطبع.

راجع مرجع البرنامج.

المصدر العربي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

المصدر الإنجليزي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

فحص النتيجة

تعرض بطاقة المصدر المضيف والإدخال والنتيجة من الفهرس المعتمد. لغة القراءة لا تغيّر النص أو النتيجة.

الحدود المعيارية للإصدار

الأنواع العددية الدقيقة

الغرض والنتيجة

يستخدم الأنواع العشرة والحد الأعلى لـu64 والتقريب لـf32 والتنسيق. يطبع numeric types\n ويرجع 0.

راجع عائلة الأعداد الدقيقة.

المصدر العربي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

المصدر الإنجليزي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

المصدر المختلط

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

فحص النتيجة

تعرض بطاقة المصدر المضيف والإدخال والنتيجة من الفهرس المعتمد. لغة القراءة لا تغيّر النص أو النتيجة.

الحدود المعيارية للإصدار

رفض حرفية خارج المجال

الغرض والنتيجة

هذا فشل فحص مقصود. الحرفية 256 لا تلائم u8. لا يبدأ التنفيذ، والسبب numeric-literal-out-of-range.

راجع عائلة الأعداد الدقيقة.

المصدر العربي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

المصدر الإنجليزي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

فحص النتيجة

تعرض بطاقة المصدر المضيف والإدخال والنتيجة من الفهرس المعتمد. لغة القراءة لا تغيّر النص أو النتيجة.

الحدود المعيارية للإصدار

فخ التحويل العددي

الغرض والنتيجة

ينجح الفحص، ثم التحويل الصريح u8 أو ط8 للقيمة 256 يفخ بـinvalid-numeric-conversion. الحالة الأصلية 5 ولا يوجد خرج.

راجع عائلة الأعداد الدقيقة.

المصدر العربي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

المصدر الإنجليزي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

فحص النتيجة

تعرض بطاقة المصدر المضيف والإدخال والنتيجة من الفهرس المعتمد. لغة القراءة لا تغيّر النص أو النتيجة.

الحدود المعيارية للإصدار

تشخيص الرابط الثابت

الغرض والنتيجة

هذا فشل مصدر مقصود بـimmutable-assignment. ادرس الموضع الأولي. لا يقدم هذا التشخيص تعديلا تلقائيا؛ استبدل يدويا let أو دع بـvar أو متغير، أو افتح المصدر المصحح في مسودة منفصلة.

راجع التشخيص والتصحيح.

المصدر العربي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

المصدر الإنجليزي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

فحص النتيجة

تعرض بطاقة المصدر المضيف والإدخال والنتيجة من الفهرس المعتمد. لغة القراءة لا تغيّر النص أو النتيجة.

الحدود المعيارية للإصدار

تصحيح الرابط القابل للتغيير

الغرض والنتيجة

يستبدل التصحيح دع / let بـمتغير / var. ينجح البرنامج ويرجع 1 دون خرج. الحالة غير الصفرية ليست خطأ مصدر أو فخا.

راجع التشخيص والتصحيح.

المصدر العربي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

المصدر الإنجليزي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

فحص النتيجة

تعرض بطاقة المصدر المضيف والإدخال والنتيجة من الفهرس المعتمد. لغة القراءة لا تغيّر النص أو النتيجة.

الحدود المعيارية للإصدار

خرج نصي مع سطر جديد

الغرض والنتيجة

يطبع مرحبا\n كما هي ويرجع 0. السطر الجديد صريح في النص ولا يضيفه اطبع / print.

راجع الطباعة الآمنة.

المصدر العربي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

المصدر الإنجليزي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

فحص النتيجة

تعرض بطاقة المصدر المضيف والإدخال والنتيجة من الفهرس المعتمد. لغة القراءة لا تغيّر النص أو النتيجة.

الحدود المعيارية للإصدار

التحية بإدخال سطر

الغرض والنتيجة

يطبع سؤالا، ويقرأ اسما، ثم يطبع التحية ويرجع 0. أرسل سطر الإدخال المعلن للنسخة المختارة. EOF قبل السطر يفخ بـinput-exhausted ويحفظ السؤال المطبوع.

راجع إدخال سطر.

المصدر العربي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

المصدر الإنجليزي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

المصدر المختلط

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

فحص النتيجة

تعرض بطاقة المصدر المضيف والإدخال والنتيجة من الفهرس المعتمد. لغة القراءة لا تغيّر النص أو النتيجة.

الحدود المعيارية للإصدار

بلوغ حد التنفيذ في المتصفح

الغرض والنتيجة

هذه حلقة لا تنتهي، ومضيف المثال المتصفح فقط. النتيجة المتوقعة limit-stop / execution-instruction-limit عند 10000000 تعليمة. قد يصل حد الوقت أولا على جهاز بطيء. لا تشغّل الحلقة أصليا.

راجع المضيف وحدود التنفيذ.

المصدر العربي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

المصدر الإنجليزي

هذا مصدر مقدم كامل. فتحه ينشئ مسودة جديدة؛ يبدأ Run بفعل صريح منك.

فحص النتيجة

تعرض بطاقة المصدر المضيف والإدخال والنتيجة من الفهرس المعتمد. لغة القراءة لا تغيّر النص أو النتيجة.

الحدود المعيارية للإصدار

الملفات النصية والإخفاقات القابلة للاسترداد

اختر المضيف وجهز المدخلات

يستخدم هذا الدليل ASPL 0.7.0 في المضيفين. ملفات المتصفح بايتات افتراضية مؤقتة لكل مسودة؛ ويستخدم التنفيذ الأصلي مسارات نظام ملفات حقيقية نسبة إلى مجلد عمل العملية. يوضح مرجع الواجهة قواعد المسارات والسقوف.

يحتاج مثال القراءة المورّد سطر اسم ملف واحدا. للنتيجة الافتراضية لملف مفقود، اترك missing.txt غير موجود. لا يحتاج مثال الكتابة المورّد إدخالا أو أصلا مستوردا؛ يستبدل generated.txt بالبايتات الدقيقة generated\n. اختر قبل التشغيل الأصلي مجلد عمل تقصد فيه هذا الاستبدال.

ينشئ فتح أي مصدر مورّد مسودة جديدة بلا ملفات تشغيل ولا يشغلها. اقرأ المتطلبات أولا وافتح المسودة المقصودة ثم استورد البيانات إليها. تبقى مسودات مصدرك الأخرى متاحة.

عالج ملفا مفقودا

افتح مثال القراءة واختر التشغيل ثم أرسل missing.txt كسطر الإدخال. يطبع File: error: not-found\n ويعيد 0. لا تنهي النتيجة الفاشلة التنفيذ. في Linux تتطلب النتيجة نفسها غياب هذا الاسم من مجلد عمل العملية.

يفحص البرنامج ok قبل قراءة value أو error::code. حافظ على فحص الفرع عند تعديله. استخدم رموز الخطأ الثابتة لاختيار التصرف؛ الرسائل للعرض.

اقرأ النص المستورد بدقة

لقراءة ناجحة في المتصفح:

  1. افتح مثال القراءة كمسودة جديدة.
  2. جهز ملف UTF-8 باسم notes.txt يحوي بالضبط hello\n، أي LF أخيرة بعد hello.
  3. استورد notes.txt في أداة الملفات لتلك المسودة قبل التشغيل. استيراد المصدر إجراء آخر.
  4. اختر التشغيل وأرسل notes.txt. الخرج الدقيق File: hello\n والحالة 0.
  5. نزل notes.txt صراحة إذا أردت نسخة قرص من تلك البايتات.

للقراءة الأصلية نفسها، ضع notes.txt في مجلد العمل ونزل المصدر وشغل aspl run read-file.ar.aspl. أرسل notes.txt. تعمل أيضا المسارات الأصلية المطلقة والمجلدات الفرعية؛ أسماء المتصفح مسطحة ولا يمكن أن تسميها.

يقبل استيراد الملف الخام أي بايتات. تفشل قراءة ملف يحوي بايتا مثل FF بسبب invalid-utf8؛ ويبقى الملف الأصلي قابلا للتنزيل دون تغيير. تبقى BOM أو CRLF أو NUL أو المحارف المفككة في القراءة الناجحة. لا ينظف النص تلقائيا.

يعرض المتصفح محارف التحكم غير المرئية في الخرج بتسميات وCRLF كفاصل سطر. نزل الملف لفحص بايتاته الدقيقة؛ لا يعدله تمثيل العرض.

اكتب واقرأ النتيجة ونزلها

تكتب العملية generated.txt بالبايتات 67 65 6E 65 72 61 74 65 64 0A، أي نص UTF-8 generated\n. وتطبع Output: saved\n. افتح الملفات في المتصفح ونزل generated.txt؛ لا تحفظ الكتابة الناجحة وحدها الملف إلى حاسوبك. يظهر الملف أصليا في مجلد العمل. يستبدله تشغيل لاحق بالبايتات نفسها.

لقراءته في مسودة المتصفح نفسها، انسخ مصدر read-file المورّد إلى المحرر الحالي ثم شغل وأرسل generated.txt. الخرج File: generated\n. يمنح فتح مثال القراءة كمسودة جديدة أخرى ملفات تشغيل منفصلة وفارغة. شغل المثال الأصلي من مجلد العمل نفسه.

تكتب السلسلة الفارغة ملفا فارغا. لا تضيف الكتابة سطرا جديدا غير ما تقدمه. يحفظ الاستبدال الفاشل الملف السابق، لكن الكتابة المكتملة تبقى بعد توقف لاحق أو إيقاف. لا يكتب الفحص ملفات في أي مضيف.

الإخفاقات القابلة للاسترداد والتوقفات وأخطاء المصدر

not-found وinvalid-utf8 وfile-too-large نتائج فاشلة يمكنك فحصها والاسترداد منها. يعيد التحليل العددي الصارم أيضا invalid-number أو number-out-of-range؛ لا تحول أرقام الإدخال مثل ٢ إلى ASCII.

توقف قراءة value من نتيجة فاشلة التنفيذ بسبب wrong-result-branch. قراءة value من result<unit> خطأ مصدر. للحدود وفشل التخصيص في المضيف والإلغاء نتائجها الخاصة. اقرأ النتائج القابلة للاسترداد قبل اعتبار أي تشغيل فاشل نتيجة فاشلة.

افصل المصدر عن الملفات المؤقتة

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

يفحص الاستيراد الدفعة كلها. لا تغير الأسماء غير الصالحة أو حدود الحجم أو فشل القراءة أو إلغاء الاستبدال أو الإلغاء أي ملف موجود. يقفل التشغيل تعديل الملفات ويستخدم لقطة ثابتة. يمكن تنزيل البايتات المستوردة والمكتوبة بنجاح صراحة، ومنها الكتابات السابقة لإخفاق لاحق.

helper.aspl المستورد عبر الملفات بيانات تنفيذ وليس source-module. لا يلبي استيراد مصدر في المتصفح. تتبع وحدات المصدر الأصلية مجموعة مصادر البرنامج الأصلي، ويحمّلها المترجم مستقلة عن عمليات الملفات النصية هذه.

الحدود المعيارية للإصدار

النصوص ويونيكود

الغرض والتجهيز

المتصفح والمضيف الأصلي، ASPL 0.7.0. يفحص فهرسة القيم العددية واقتطاع العربية والرموز التعبيرية ثم يطبع aمرحبا😀! بالحالة 0.

اقرأ المرجع الحالي. لا تلزم وحدة مصدر أو مكتبة خارجية.

المصدر العربي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر الإنجليزي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر المختلط

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

افحص النتيجة

تعرض بطاقات المصدر مدخلات الفهرس ونتائجه الدقيقة. لا يترجم تغيير اللغة المصدر المورّد. يحفظ التنزيل بايتات المصدر الأصلية.

الحدود المعيارية للإصدار

جمع قائمة نصوص

الغرض والتجهيز

المتصفح والمضيف الأصلي، ASPL 0.7.0. يفحص جمع قائمة فارغة وذات عنصر واحد وعدة عناصر ثم يطبع a,b,c بالحالة 0.

اقرأ المرجع الحالي. لا تلزم وحدة مصدر أو مكتبة خارجية.

المصدر العربي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر الإنجليزي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر المختلط

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

افحص النتيجة

تعرض بطاقات المصدر مدخلات الفهرس ونتائجه الدقيقة. لا يترجم تغيير اللغة المصدر المورّد. يحفظ التنزيل بايتات المصدر الأصلية.

الحدود المعيارية للإصدار

الاسترداد من إخفاق تحليل الصحيح

الغرض والتجهيز

المتصفح والمضيف الأصلي، ASPL 0.7.0. أرسل 256 ثم 41. يعيد تحليل u8 الرمز number-out-of-range؛ وينجح تحليل i64 ويطبع 42. الحالة 0.

اقرأ المرجع الحالي. لا تلزم وحدة مصدر أو مكتبة خارجية.

المصدر العربي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر الإنجليزي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر المختلط

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

افحص النتيجة

تعرض بطاقات المصدر مدخلات الفهرس ونتائجه الدقيقة. لا يترجم تغيير اللغة المصدر المورّد. يحفظ التنزيل بايتات المصدر الأصلية.

الحدود المعيارية للإصدار

الاسترداد من إخفاق تحليل العشري

الغرض والتجهيز

المتصفح والمضيف الأصلي، ASPL 0.7.0. أرسل 12x ثم 41. يعيد تحليل f32 الرمز invalid-number؛ وينجح تحليل f64 ويطبع 42. الحالة 0.

اقرأ المرجع الحالي. لا تلزم وحدة مصدر أو مكتبة خارجية.

المصدر العربي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر الإنجليزي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر المختلط

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

افحص النتيجة

تعرض بطاقات المصدر مدخلات الفهرس ونتائجه الدقيقة. لا يترجم تغيير اللغة المصدر المورّد. يحفظ التنزيل بايتات المصدر الأصلية.

الحدود المعيارية للإصدار

معالجة نتيجة قابلة للاسترداد

الغرض والتجهيز

المتصفح والمضيف الأصلي، ASPL 0.7.0. يفحص فرعي النجاح والإخفاق ويطبع hello aspl empty-name ويعيد 0. يعالج النتيجة الفاشلة دون توقف.

اقرأ المرجع الحالي. لا تلزم وحدة مصدر أو مكتبة خارجية.

المصدر العربي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر الإنجليزي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر المختلط

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

افحص النتيجة

تعرض بطاقات المصدر مدخلات الفهرس ونتائجه الدقيقة. لا يترجم تغيير اللغة المصدر المورّد. يحفظ التنزيل بايتات المصدر الأصلية.

الحدود المعيارية للإصدار

قيم القوائم المحددة النوع

الغرض والتجهيز

المتصفح والمضيف الأصلي، ASPL 0.7.0. يمرر قائمة محددة النوع إلى دالة ويفحص العناصر العددية الدقيقة ويطبع 12 بالحالة 0.

اقرأ المرجع الحالي. لا تلزم وحدة مصدر أو مكتبة خارجية.

المصدر العربي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر الإنجليزي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر المختلط

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

افحص النتيجة

تعرض بطاقات المصدر مدخلات الفهرس ونتائجه الدقيقة. لا يترجم تغيير اللغة المصدر المورّد. يحفظ التنزيل بايتات المصدر الأصلية.

الحدود المعيارية للإصدار

تعديل نسخ قوائم مستقلة

الغرض والتجهيز

المتصفح والمضيف الأصلي، ASPL 0.7.0. يضيف ويستبدل العناصر ويفحص استقلال النسخ المتداخلة وذات العرض الدقيق. يطبع 32 بالحالة 0.

اقرأ المرجع الحالي. لا تلزم وحدة مصدر أو مكتبة خارجية.

المصدر العربي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر الإنجليزي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر المختلط

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

افحص النتيجة

تعرض بطاقات المصدر مدخلات الفهرس ونتائجه الدقيقة. لا يترجم تغيير اللغة المصدر المورّد. يحفظ التنزيل بايتات المصدر الأصلية.

الحدود المعيارية للإصدار

نسخ السجلات المسماة وتعديلها

الغرض والتجهيز

المتصفح والمضيف الأصلي، ASPL 0.7.0. يفحص الحقول واستقلال النسخة المتداخلة وحمولة نتيجة سجل. يطبع 3 tokens بالحالة 0.

اقرأ المرجع الحالي. لا تلزم وحدة مصدر أو مكتبة خارجية.

المصدر العربي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر الإنجليزي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر المختلط

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

افحص النتيجة

تعرض بطاقات المصدر مدخلات الفهرس ونتائجه الدقيقة. لا يترجم تغيير اللغة المصدر المورّد. يحفظ التنزيل بايتات المصدر الأصلية.

الحدود المعيارية للإصدار

قراءة ملف ومعالجة غيابه

الغرض والتجهيز

المتصفح والمضيف الأصلي، ASPL 0.7.0. عند غياب missing.txt أرسل هذا الاسم. يطبع File: error: not-found\n ويعيد 0. لا يحتاج هذا الناتج ملفا مستوردا.

اقرأ المرجع الحالي. لا تلزم وحدة مصدر أو مكتبة خارجية.

اقرأ الملفات النصية والإخفاقات القابلة للاسترداد قبل استيراد البيانات أو الكتابة إلى وجهة أصلية. تبدأ مسودات المتصفح الجديدة بملفات تشغيل فارغة.

المصدر العربي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر الإنجليزي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

افحص النتيجة

تعرض بطاقات المصدر مدخلات الفهرس ونتائجه الدقيقة. لا يترجم تغيير اللغة المصدر المورّد. يحفظ التنزيل بايتات المصدر الأصلية.

الحدود المعيارية للإصدار

كتابة بايتات نص دقيقة

الغرض والتجهيز

المتصفح والمضيف الأصلي، ASPL 0.7.0. لا يحتاج إدخالا أو أصلا. ينشئ generated.txt أو يستبدله بالبايتات الدقيقة generated\n ويطبع Output: saved\n ويعيد 0.

اقرأ المرجع الحالي. لا تلزم وحدة مصدر أو مكتبة خارجية.

اقرأ الملفات النصية والإخفاقات القابلة للاسترداد قبل استيراد البيانات أو الكتابة إلى وجهة أصلية. تبدأ مسودات المتصفح الجديدة بملفات تشغيل فارغة.

المصدر العربي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

المصدر الإنجليزي

يفتح هذا المصدر الكامل المورّد مسودة جديدة. جهز المدخلات والملفات المعلنة في تلك المسودة ثم اختر التشغيل صراحة.

افحص النتيجة

تعرض بطاقات المصدر مدخلات الفهرس ونتائجه الدقيقة. لا يترجم تغيير اللغة المصدر المورّد. يحفظ التنزيل بايتات المصدر الأصلية.

الحدود المعيارية للإصدار

استخدام وحدات المصدر الأصلية

جهّز الملفات الأصلية

استخدم أدوات ASPL 0.7.0 الأصلية المختارة. اتبع التثبيت والفحص والتشغيل والبناء قبل هذا الدليل. لا يحمّل المتصفح وحدات مصدر المستخدم. استيراد ملف تشغيل يبدو اسمه كملف مصدر لا يغيّر هذا القيد.

نزّل الملفين من مثال التعريف الخاص. ضع main.ar.aspl وملف helpers.aspl الخاص بهذا المثال في مجلد جديد. يمكن استخدام المصدر الإنجليزي المورّد main.en.aspl بدلا منه. لا توجد ملفات بيانات ولا استيرادات مكتبات مورّدة. افصل مثال الفشل عن المثال المصحح، لأن الملفين المساعدين لهما اسم التنزيل نفسه.

اعثر على التعريف الخاص

شغّل الفحص من مجلد التنزيل:

aspl check main.ar.aspl

يفشل بحالة 1 وprivate-member لأن المدخل يستدعي مكتبة::answer() بينما يعرّف helpers.aspl الدالة fn answer() تعريفا خاصا. يفشل تشغيل المصدر نفسه أثناء الفحص أيضا، دون خرج من البرنامج. يتيح الاستيراد نطاق أسماء ولا يصدّر أعضاءه تلقائيا.

صدّر وأعد المحاولة

أضف share قبل fn answer في ملف helpers.aspl المنزّل:

مقطع توضيحي

share fn answer() -> i64 { return 42; }

أعد الفحص والتشغيل. يعيد المدخل المصحح 42 دون خرج، فترى الصدفة الحالة 42. لفحصها شغّل aspl run main.ar.aspl ثم echo $?. تصدير اسم مستخدم لا يترجمه.

للحصول على تصحيح كامل مفحوص مستقل يطبع خرجا، نزّل الملفين من وحدات المصدر إلى مجلد مختلف. يصدّر هذا الإصدار answer وReply وchoose. يبقي hidden خاصا ويعيد قيمة قابلة للاستدعاء عبر choose.

استخدم قيمة استدعاء معادة

يطبع البرنامج الكامل المصحح 42 ثم LF ويعيد 0. السجل مكتبة::Reply سجل اسمي مصدّر، وتعيد مكتبة::choose() قيمة من نوع دالة(ص64) -> ص64. يصح استدعاء القيمة مع أن تسمية مكتبة::hidden مباشرة تفشل. يستخدم توقيع المساعد الخاص أنواعا عددية عامة فقط. يفشل توقيع مصدّر يتضمن سجلا خاصا بسبب private-type-exposure.

ابن البرنامج الكامل

من مجلد المثال الكامل المصحح:

aspl check main.ar.aspl
aspl run main.ar.aspl
aspl build -o module-program main.ar.aspl
./module-program

كرر باستخدام main.en.aspl للمفردات الإنجليزية المورّدة. احتفظ بالمدخلين بجانب helpers.aspl دون تغيير، فتبقى أسماء المستخدم المصدّرة فيه إنجليزية مع أي مدخل. لا تحتاج أسطر إدخال أو ملفات بيانات. يتضمن الملف التنفيذي الوحدات المترجمة ويعمل دون ملفات مصدرها.

اقرأ قواعد الاستيراد والتصدير الكاملة ومجموعة البرامج الكاملة المتقدمة. لا تتطلب دورة المتصفح ذات الملف الواحد واختبارها للمبتدئين وحدات مصدر.

الحدود المعيارية للإصدار

دالة مساعدة تستدعي نفسها

الغرض والتجهيز

المتصفح والتنفيذ الأصلي، ASPL 0.7.0. لا يحتاج أسطر إدخال أو ملفات بيانات أو وحدات مصدر. يعيد مثال المضروب حالة عملية 120 دون خرج. تعدّ الصدفة الحالة غير الصفرية غير ناجحة مع أن التنفيذ اللغوي ينجح.

المرجع الحالي.

المصدر العربي

افتح مسودة جديدة ثم اختر التشغيل صراحة. يفحص الفتح المصدر دون تنفيذه.

المصدر الإنجليزي

افتح مسودة جديدة ثم اختر التشغيل صراحة. يفحص الفتح المصدر دون تنفيذه.

تحقق من النتيجة

تعرض بطاقات المصدر نتائج الكتالوج الدقيقة. تحتفظ التنزيلات بالبايتات والبصمات ومفردات المصدر المورّدة.

الحدود المعيارية للإصدار

القيم القابلة للاستدعاء المعلنة النوع

الغرض والتجهيز

المتصفح والتنفيذ الأصلي، ASPL 0.7.0. يستخدم الدوال المعلنة النوع والقوائم والسجلات والنتائج. لا يحتاج أسطر إدخال أو ملفات بيانات أو وحدات مصدر. يمرر قيمة قابلة للاستدعاء عبر كل حاوية ويقارن هويتها ويطبع 42 ثم LF ويعيد 0.

المرجع الحالي.

المصدر العربي

افتح مسودة جديدة ثم اختر التشغيل صراحة. يفحص الفتح المصدر دون تنفيذه.

المصدر الإنجليزي

افتح مسودة جديدة ثم اختر التشغيل صراحة. يفحص الفتح المصدر دون تنفيذه.

تحقق من النتيجة

تعرض بطاقات المصدر نتائج الكتالوج الدقيقة. تحتفظ التنزيلات بالبايتات والبصمات ومفردات المصدر المورّدة.

الحدود المعيارية للإصدار

وحدات المصدر المصدّرة

الغرض والتجهيز

أصلي فقط، ASPL 0.7.0. نزّل المدخل وملف helpers.aspl المطلوب إلى مجلد واحد. لا يحتاج أسطر إدخال أو ملفات بيانات. يصدّر المساعد دالة وسجلا ودالة تعيد مساعدا خاصا كقيمة قابلة للاستدعاء. يطبع 42 ثم LF ويعيد 0.

المرجع الحالي.

ثبّت الأدوات الأصلية · اتبع دليل الوحدات العملي.

المصدر العربي

أصلي فقط. هذه ملفات مصدر وليست بيانات تشغيل في المتصفح.

المصدر الإنجليزي

أصلي فقط. هذه ملفات مصدر وليست بيانات تشغيل في المتصفح.

تحقق من النتيجة

تعرض بطاقات المصدر نتائج الكتالوج الدقيقة. تحتفظ التنزيلات بالبايتات والبصمات ومفردات المصدر المورّدة.

aspl check main.ar.aspl
aspl run main.ar.aspl
aspl build -o module-program main.ar.aspl
./module-program
الحدود المعيارية للإصدار

التعريف الخاص وتصحيحه بالتصدير

الغرض والتجهيز

فشل فحص أصلي مقصود، ASPL 0.7.0. نزّل المدخل وملف helpers.aspl الخاص بهذا المثال إلى مجلد مستقل. لا يحتاج أسطر إدخال أو ملفات بيانات. يفشل الفحص والتشغيل بحالة 1 وprivate-member دون خرج لأن answer خاص.

المرجع الحالي.

ثبّت الأدوات الأصلية · اتبع دليل الوحدات العملي.

المصدر العربي

أصلي فقط. هذه ملفات مصدر وليست بيانات تشغيل في المتصفح.

المصدر الإنجليزي

أصلي فقط. هذه ملفات مصدر وليست بيانات تشغيل في المتصفح.

تصدير التصحيح

أضف share قبل fn answer في المساعد المنزّل. أعد الفحص فينجح. يعيد تشغيل المدخل المصحح الحالة 42 دون خرج. احتفظ بالمساعد المعدل في مجلد مثال الفشل. لبرنامج كامل يعيد 0 ويطبع خرجا، استخدم مصادر الوحدات المصححة المنزّلة بصورة مستقلة.

مقطع توضيحي

share fn answer() -> i64 { return 42; }

تحقق من النتيجة

تعرض بطاقات المصدر نتائج الكتالوج الدقيقة. تحتفظ التنزيلات بالبايتات والبصمات ومفردات المصدر المورّدة.

aspl check main.ar.aspl
aspl run main.ar.aspl
الحدود المعيارية للإصدار

اللغة الحسابية المصغرة المتقدمة

التعقيد والإدخال المطلوب

برنامج كامل متقدم، للمتصفح والتنفيذ الأصلي في ASPL 0.7.0. يتضمن محلل رموز ومحللا نحويا ومفسرا ومولّد مصدر ASPL في ملف مصدر واحد. يستخدم السلاسل والقوائم والسجلات والنتائج والملفات النصية والدوال وتدفق التحكم. هذا مثال منفصل عن اختبار المبتدئين. المصدر الإنجليزي وحده مورّد، بما فيه الصفحة العربية.

نزّل demo.txt قبل فتح المصدر. لنتيجة الكتالوج، أرسل السطرين demo.txt وinterpret. الخرج المتوقع File: Operation: 55\n وحالة العملية 0. لا يحتاج وحدات مصدر أو مكتبات خارجية. يفحص فتح المسودة المصدر دون تنفيذه أو استيراد بيانات.

المصدر الإنجليزي المورّد

جهّز مسودة المتصفح

افتح المثال كمسودة جديدة. استورد demo.txt المنزّل عبر عناصر ملفات التشغيل في تلك المسودة، ثم اختر التشغيل. أجب بـdemo.txt وinterpret عند الطلبين. لا يستورد فتح المصدر هذا الملف نيابة عنك. دون الملف، يطبع البرنامج File: Operation: error: not-found\n ويعيد 0، وهو فشل ملف عالجه البرنامج.

للتوليد أرسل demo.txt ثم generate ثم generated.aspl. نزّل الملف المولّد صراحة لحفظه. إنه خرج من ملفات التشغيل ولا يضيف دعم وحدات المصدر للمتصفح. تفقد إعادة التحميل الملفات المؤقتة. استورد demo.txt مجددا قبل إعادة التشغيل.

شغّل أصليا

اتبع التثبيت والأدوات الأصلية. ضع mini-arith.aspl وdemo.txt معا وشغّل من ذلك المجلد. تُحل مسارات البيانات الأصلية من مجلد عمل العملية.

aspl check mini-arith.aspl
printf 'demo.txt\ninterpret\n' | aspl run mini-arith.aspl
printf 'demo.txt\ngenerate\ngenerated.aspl\n' | aspl run mini-arith.aspl
aspl check generated.aspl
aspl run generated.aspl
aspl build -o generated-program generated.aspl
./generated-program

يطبع التفسير File: Operation: 55 ثم LF. يطبع التوليد File: Operation: Output: ويكتب برنامجا يطبع 55 ثم LF. يعيد كلاهما 0.

تابع الشرح الكامل

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

mini-arith-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

// Mini arithmetic language, written in ASPL.
//
// Ticket 15 slice: read one expression program from a file, tokenize it,
// parse it, and interpret integer arithmetic. Ticket 16 slice: extend the
// same program with variables and control flow. Ticket 17 slice: extend
// this same program with ASPL source generation alongside interpretation.
//
// Grammar:
//   program    := expression | var_section? statement+
//   expression := term (("+" | "-") term)*
//   term       := factor (("*" | "/" | "%") factor)*
//   factor     := "-" factor | primary
//   primary    := number | variable | "(" expression ")"
//   var_section:= ("var" name ("," name)* (";" | "."))+
//   statement  := assignment | print_statement | if_statement | while_statement
//   assignment := name "=" expression (";" | ".")
//   print_statement := "print" expression (";" | ".")
//   if_statement   := "if" "(" condition ")" "{" statement* "}"
//                    ("else" "{" statement* "}")?
//   while_statement:= "while" "(" condition ")" "{" statement* "}"
//   condition  := expression ("==" | "!=" | "<" | "<=" | ">" | ">=") expression
//
// A program whose first token is an identifier parses as the statement
// form (with an optional leading "var" section). Anything else parses as
// the ticket 15 bare-expression form, which keeps its original behavior:
// identifiers there are still a syntax error. Reserved words, never usable
// as variable names: "var", "print", "if", "else", "while".
//
// Declarations live only in the initial program-wide section and are
// visible to every later statement; there are no block scopes and no
// declarations inside loop bodies. Every declared variable starts at 0.
// Duplicate declarations and uses of undeclared variables fail with
// "duplicate-variable" and "undeclared-variable" instead of silently
// producing a value.
//
// Precedence, highest first: parentheses, unary minus, "*", "/", "%", then
// "+" and "-". Operators at the same level associate to the left. Integer
// division truncates toward zero and "%" takes the sign of its left side,
// exactly like ASPL. Arithmetic uses ASPL's checked operations, so overflow
// and division by zero trap exactly as they do in an ASPL program.
// Conditions compare two integer expressions with the six comparison
// operators and produce an ASPL boolean for the branch or loop decision.
// Branches run one side only; while bodies repeat until the condition is
// false, using ASPL's own control flow, so a runaway loop stays stoppable
// through the existing execution controls.
//
// Identifier alphabet: the first scalar is an ASCII letter, "_", or an
// Arabic letter from U+0627 through U+064A. Following scalars may also be
// ASCII digits. This documents a small Arabic-letter subset on purpose and
// does not claim ASPL's full Unicode identifier profile.
//
// Token kinds: 0 integer, 1 "+", 2 "-", 3 "*", 4 "/", 5 "%", 6 "(", 7 ")",
// 8 identifier or keyword, 9 end of input, 10 "=", 11 "==", 12 "!=", 13 "<",
// 14 "<=", 15 ">", 16 ">=", 17 "{", 18 "}", 19 ",", 20 ";" or ".".
// Node kinds reuse the token codes for expressions (0 numbers, 1-5 binary
// operators, 6 unary negation) and comparisons (11-16). Variable loads are
// 30 (holding the source spelling in the name field) so that node kinds
// never share a code with a token kind. Statement nodes are
// 40 assignment (name plus value in left), 41 print (value in left),
// 42 if (condition in left, then-branch head in extra, else-branch head in
// number with -1 for none), and 43 while (condition in left, body head in
// extra). Statements chain through right (-1 ends the sequence); a missing
// expression child is -1.
//
// Diagnostics are recoverable values, never unchecked branches. Failures
// carry a stable ASCII code plus a "line:column" position measured in
// Unicode scalar values starting at 1. Variable failures append the
// offending source spelling after the position with its bytes preserved.
// File failures forward the read_text_file code without a position.
//
// Generation maps every declared mini-language name to an indexed ASPL
// name ("m_var_0", "m_var_1", ...) by declaration order. The generated
// source never copies the original spelling, so Arabic names, ASPL
// reserved words, and collisions with generated temporaries cannot
// produce invalid or changed-meaning output. Fragments accumulate in a
// typed list<string> and join once; numbers format through format_i64.

record Token { kind: i64, text: string, line: i64, column: i64 }
record Node { kind: i64, number: i64, left: i64, right: i64, line: i64, column: i64, extra: i64, name: string }
record ParserState { tokens: list<Token>, pos: i64, nodes: list<Node>, declared: list<string>, allow_names: bool }
record ParseStep { state: ParserState, node: i64 }
record Binding { name: string, value: i64 }
record ElseStep { state: ParserState, head: i64 }
record CondBody { state: ParserState, cond: i64, body: i64 }

fn is_digit(codepoint: i64) -> bool {
    return codepoint >= 48 and codepoint <= 57;
}

fn is_name_start(codepoint: i64) -> bool {
    if (codepoint matches 95) { return true; }
    if (codepoint >= 65 and codepoint <= 90) { return true; }
    if (codepoint >= 97 and codepoint <= 122) { return true; }
    if (codepoint >= 1575 and codepoint <= 1610) { return true; }
    return false;
}

fn scan_run(source: string, pos: i64, count: i64, allow_names: bool) -> i64 {
    var end = pos;
    var scanning = true;
    while (scanning) {
        if (end >= count) {
            scanning = false;
        } else {
            let codepoint = codepoint_at(source, end);
            if (is_digit(codepoint)) {
                end = end + 1;
            } else {
                if (allow_names and is_name_start(codepoint)) {
                    end = end + 1;
                } else {
                    scanning = false;
                }
            }
        }
    }
    return end;
}

fn is_operator(codepoint: i64) -> bool {
    if (codepoint matches 43 or codepoint matches 45) { return true; }
    if (codepoint matches 42 or codepoint matches 47) { return true; }
    if (codepoint matches 37 or codepoint matches 40) { return true; }
    if (codepoint matches 41 or codepoint matches 123) { return true; }
    if (codepoint matches 125 or codepoint matches 44) { return true; }
    return codepoint matches 59 or codepoint matches 46;
}

fn operator_kind(codepoint: i64) -> i64 {
    if (codepoint matches 43) { return 1; }
    if (codepoint matches 45) { return 2; }
    if (codepoint matches 42) { return 3; }
    if (codepoint matches 47) { return 4; }
    if (codepoint matches 37) { return 5; }
    if (codepoint matches 40) { return 6; }
    if (codepoint matches 123) { return 17; }
    if (codepoint matches 125) { return 18; }
    if (codepoint matches 44) { return 19; }
    if (codepoint matches 59) { return 20; }
    if (codepoint matches 46) { return 20; }
    return 7;
}

fn double_kind(source: string, pos: i64, count: i64, codepoint: i64) -> i64 {
    var pair = "";
    if (pos + 1 < count) {
        pair = slice(source, pos, pos + 2);
    }
    if (pair matches "==") { return 11; }
    if (pair matches "!=") { return 12; }
    if (pair matches "<=") { return 14; }
    if (pair matches ">=") { return 16; }
    if (codepoint matches 61) { return 10; }
    if (codepoint matches 60) { return 13; }
    if (codepoint matches 62) { return 15; }
    return -1;
}

fn double_width(kind: i64) -> i64 {
    if (kind matches 11 or kind matches 12) { return 2; }
    if (kind matches 14 or kind matches 16) { return 2; }
    return 1;
}

fn is_keyword(text: string) -> bool {
    if (text matches "var") { return true; }
    if (text matches "print") { return true; }
    if (text matches "if") { return true; }
    if (text matches "else") { return true; }
    return text matches "while";
}

fn is_comparison(kind: i64) -> bool {
    if (kind matches 11 or kind matches 12) { return true; }
    if (kind matches 13 or kind matches 14) { return true; }
    return kind matches 15 or kind matches 16;
}

fn is_declared(declared: list<string>, name: string) -> bool {
    var i = 0;
    while (i < length(declared)) {
        if (declared[i] matches name) { return true; }
        i = i + 1;
    }
    return false;
}

fn position_text(line: i64, column: i64) -> string {
    return format_i64(line) + ":" + format_i64(column);
}

fn position_name_text(line: i64, column: i64, name: string) -> string {
    return format_i64(line) + ":" + format_i64(column) + " " + name;
}

fn tokenize_source(source: string) -> result<list<Token>> {
    var tokens: list<Token> = [];
    var pos = 0;
    var line = 1;
    var column = 1;
    let count = length(source);
    while (pos < count) {
        let codepoint = codepoint_at(source, pos);
        if (codepoint matches 32 or codepoint matches 9 or codepoint matches 13) {
            pos = pos + 1;
            column = column + 1;
        } else {
            if (codepoint matches 10) {
                pos = pos + 1;
                line = line + 1;
                column = 1;
            } else {
                if (is_digit(codepoint)) {
                    let end = scan_run(source, pos, count, false);
                    let spelling = slice(source, pos, end);
                    let parsed: result<i64> = parse_i64(spelling);
                    if (parsed::ok or spelling matches "9223372036854775808") {
                        append(tokens, Token { kind: 0, text: spelling, line: line, column: column });
                        column = column + (end - pos);
                        pos = end;
                    } else {
                        return failure(parsed::error::code, position_text(line, column));
                    }
                } else {
                    if (is_name_start(codepoint)) {
                        let end = scan_run(source, pos, count, true);
                        append(tokens, Token { kind: 8, text: slice(source, pos, end), line: line, column: column });
                        column = column + (end - pos);
                        pos = end;
                    } else {
                        if (codepoint matches 61 or codepoint matches 33 or codepoint matches 60 or codepoint matches 62) {
                            let kind = double_kind(source, pos, count, codepoint);
                            if (kind < 0) {
                                return failure("invalid-character", position_text(line, column));
                            }
                            let width = double_width(kind);
                            append(tokens, Token { kind: kind, text: slice(source, pos, pos + width), line: line, column: column });
                            pos = pos + width;
                            column = column + width;
                        } else {
                            if (is_operator(codepoint)) {
                                append(tokens, Token { kind: operator_kind(codepoint), text: char_at(source, pos), line: line, column: column });
                                pos = pos + 1;
                                column = column + 1;
                            } else {
                                return failure("invalid-character", position_text(line, column));
                            }
                        }
                    }
                }
            }
        }
    }
    append(tokens, Token { kind: 9, text: "", line: line, column: column });
    return success(tokens);
}

fn at_end(state: ParserState) -> bool {
    return state::pos >= length(state::tokens);
}

fn current(state: ParserState) -> Token {
    return state::tokens[state::pos];
}

fn append_node(state: ParserState, kind: i64, number: i64, left: i64, right: i64, line: i64, column: i64, extra: i64, name: string) -> ParseStep {
    var moving: ParserState = state;
    append(moving::nodes, Node { kind: kind, number: number, left: left, right: right, line: line, column: column, extra: extra, name: name });
    return ParseStep { state: moving, node: length(moving::nodes) - 1 };
}

fn expect_token(state: ParserState, kind: i64) -> result<ParserState> {
    if (at_end(state)) {
        let last: Token = state::tokens[length(state::tokens) - 1];
        return failure("syntax-error", position_text(last::line, last::column));
    }
    let tok: Token = current(state);
    if (tok::kind matches kind) {
        var moving: ParserState = state;
        moving::pos = moving::pos + 1;
        return success(moving);
    }
    return failure("syntax-error", position_text(tok::line, tok::column));
}

fn parse_expression(state: ParserState) -> result<ParseStep> {
    let first: result<ParseStep> = parse_term(state);
    if (first::ok) {
        var moving: ParserState = first::value::state;
        var root = first::value::node;
        var running = true;
        while (running) {
            if (at_end(moving)) {
                running = false;
            } else {
                let kind = current(moving)::kind;
                if (kind matches 1 or kind matches 2) {
                    let operator_token: Token = current(moving);
                    var next: ParserState = moving;
                    next::pos = next::pos + 1;
                    let rhs: result<ParseStep> = parse_term(next);
                    if (rhs::ok) {
                        let placed: ParseStep = append_node(rhs::value::state, kind, 0, root, rhs::value::node, operator_token::line, operator_token::column, -1, "");
                        moving = placed::state;
                        root = placed::node;
                    } else {
                        return rhs;
                    }
                } else {
                    running = false;
                }
            }
        }
        return success(ParseStep { state: moving, node: root });
    }
    return first;
}

fn parse_term(state: ParserState) -> result<ParseStep> {
    let first: result<ParseStep> = parse_factor(state);
    if (first::ok) {
        var moving: ParserState = first::value::state;
        var root = first::value::node;
        var running = true;
        while (running) {
            if (at_end(moving)) {
                running = false;
            } else {
                let kind = current(moving)::kind;
                if (kind matches 3 or kind matches 4 or kind matches 5) {
                    let operator_token: Token = current(moving);
                    var next: ParserState = moving;
                    next::pos = next::pos + 1;
                    let rhs: result<ParseStep> = parse_factor(next);
                    if (rhs::ok) {
                        let placed: ParseStep = append_node(rhs::value::state, kind, 0, root, rhs::value::node, operator_token::line, operator_token::column, -1, "");
                        moving = placed::state;
                        root = placed::node;
                    } else {
                        return rhs;
                    }
                } else {
                    running = false;
                }
            }
        }
        return success(ParseStep { state: moving, node: root });
    }
    return first;
}

fn parse_factor(state: ParserState) -> result<ParseStep> {
    if (at_end(state)) {
        let last: Token = state::tokens[length(state::tokens) - 1];
        return failure("syntax-error", position_text(last::line, last::column));
    }
    let tok: Token = current(state);
    if (tok::kind matches 0) {
        let parsed: result<i64> = parse_i64(tok::text);
        if (parsed::ok) {
            var moving: ParserState = state;
            moving::pos = moving::pos + 1;
            return success(append_node(moving, 0, parsed::value, -1, -1, tok::line, tok::column, -1, ""));
        }
        return failure(parsed::error::code, position_text(tok::line, tok::column));
    }
    if (tok::kind matches 8) {
        if (state::allow_names) {
            if (is_keyword(tok::text)) {
                return failure("syntax-error", position_text(tok::line, tok::column));
            }
            if (is_declared(state::declared, tok::text)) {
                var moving: ParserState = state;
                moving::pos = moving::pos + 1;
                return success(append_node(moving, 30, 0, -1, -1, tok::line, tok::column, -1, tok::text));
            }
            return failure("undeclared-variable", position_name_text(tok::line, tok::column, tok::text));
        }
        return failure("syntax-error", position_text(tok::line, tok::column));
    }
    if (tok::kind matches 2) {
        var moving: ParserState = state;
        moving::pos = moving::pos + 1;
        if (not at_end(moving)) {
            let magnitude: Token = current(moving);
            if (magnitude::kind matches 0 and magnitude::text matches "9223372036854775808") {
                moving::pos = moving::pos + 1;
                return success(append_node(
                    moving,
                    0,
                    -9223372036854775807 - 1,
                    -1,
                    -1,
                    tok::line,
                    tok::column,
                    -1,
                    ""
                ));
            }
        }
        let inner: result<ParseStep> = parse_factor(moving);
        if (inner::ok) {
            return success(append_node(inner::value::state, 6, 0, inner::value::node, -1, tok::line, tok::column, -1, ""));
        }
        return inner;
    }
    if (tok::kind matches 6) {
        var moving: ParserState = state;
        moving::pos = moving::pos + 1;
        let inner: result<ParseStep> = parse_expression(moving);
        if (inner::ok) {
            var after: ParserState = inner::value::state;
            if (at_end(after)) {
                return failure("syntax-error", position_text(tok::line, tok::column));
            }
            let closing: Token = current(after);
            if (closing::kind matches 7) {
                after::pos = after::pos + 1;
                return success(ParseStep { state: after, node: inner::value::node });
            }
            return failure("syntax-error", position_text(closing::line, closing::column));
        }
        return inner;
    }
    return failure("syntax-error", position_text(tok::line, tok::column));
}

fn expect_end(state: ParserState) -> result<ParserState> {
    if (at_end(state)) {
        return success(state);
    }
    let tok: Token = current(state);
    if (tok::kind matches 9) {
        return success(state);
    }
    return failure("syntax-error", position_text(tok::line, tok::column));
}

fn parse_var_name(state: ParserState) -> result<ParserState> {
    if (at_end(state)) {
        let last: Token = state::tokens[length(state::tokens) - 1];
        return failure("syntax-error", position_text(last::line, last::column));
    }
    let tok: Token = current(state);
    if (tok::kind matches 8) {
        if (is_keyword(tok::text)) {
            return failure("syntax-error", position_text(tok::line, tok::column));
        }
        if (is_declared(state::declared, tok::text)) {
            return failure("duplicate-variable", position_name_text(tok::line, tok::column, tok::text));
        }
        var moving: ParserState = state;
        moving::pos = moving::pos + 1;
        append(moving::declared, tok::text);
        return success(moving);
    }
    return failure("syntax-error", position_text(tok::line, tok::column));
}

fn parse_var_line(state: ParserState) -> result<ParserState> {
    var moving: ParserState = state;
    moving::pos = moving::pos + 1;
    let first: result<ParserState> = parse_var_name(moving);
    if (first::ok) {
        moving = first::value;
    } else {
        return first;
    }
    var running = true;
    while (running) {
        if (at_end(moving)) {
            running = false;
        } else {
            let tok: Token = current(moving);
            if (tok::kind matches 19) {
                moving::pos = moving::pos + 1;
                let named: result<ParserState> = parse_var_name(moving);
                if (named::ok) {
                    moving = named::value;
                } else {
                    return named;
                }
            } else {
                running = false;
            }
        }
    }
    let closed: result<ParserState> = expect_token(moving, 20);
    if (closed::ok) {
        return closed;
    }
    return failure(closed::error::code, closed::error::message);
}

fn parse_var_section(state: ParserState) -> result<ParserState> {
    var moving: ParserState = state;
    var running = true;
    while (running) {
        if (at_end(moving)) {
            running = false;
        } else {
            let tok: Token = current(moving);
            if (tok::kind matches 8 and tok::text matches "var") {
                let lined: result<ParserState> = parse_var_line(moving);
                if (lined::ok) {
                    moving = lined::value;
                } else {
                    return lined;
                }
            } else {
                running = false;
            }
        }
    }
    return success(moving);
}

fn parse_condition(state: ParserState) -> result<ParseStep> {
    let lhs: result<ParseStep> = parse_expression(state);
    if (lhs::ok) {
        var moving: ParserState = lhs::value::state;
        if (at_end(moving)) {
            let last: Token = moving::tokens[length(moving::tokens) - 1];
            return failure("syntax-error", position_text(last::line, last::column));
        }
        let op: Token = current(moving);
        if (is_comparison(op::kind)) {
            moving::pos = moving::pos + 1;
            let rhs: result<ParseStep> = parse_expression(moving);
            if (rhs::ok) {
                return success(append_node(rhs::value::state, op::kind, 0, lhs::value::node, rhs::value::node, op::line, op::column, -1, ""));
            }
            return rhs;
        }
        return failure("syntax-error", position_text(op::line, op::column));
    }
    return lhs;
}

fn parse_print_statement(state: ParserState, tok: Token) -> result<ParseStep> {
    var moving: ParserState = state;
    moving::pos = moving::pos + 1;
    let valued: result<ParseStep> = parse_expression(moving);
    if (valued::ok) {
        let closed: result<ParserState> = expect_token(valued::value::state, 20);
        if (closed::ok) {
            return success(append_node(closed::value, 41, 0, valued::value::node, -1, tok::line, tok::column, -1, ""));
        }
        return failure(closed::error::code, closed::error::message);
    }
    return valued;
}

fn parse_assignment(state: ParserState, tok: Token) -> result<ParseStep> {
    if (is_keyword(tok::text)) {
        return failure("syntax-error", position_text(tok::line, tok::column));
    }
    if (is_declared(state::declared, tok::text)) {
        var moving: ParserState = state;
        moving::pos = moving::pos + 1;
        let assign_op: result<ParserState> = expect_token(moving, 10);
        if (assign_op::ok) {
            let valued: result<ParseStep> = parse_expression(assign_op::value);
            if (valued::ok) {
                let closed: result<ParserState> = expect_token(valued::value::state, 20);
                if (closed::ok) {
                    return success(append_node(closed::value, 40, 0, valued::value::node, -1, tok::line, tok::column, -1, tok::text));
                }
                return failure(closed::error::code, closed::error::message);
            }
            return valued;
        }
        return failure(assign_op::error::code, assign_op::error::message);
    }
    return failure("undeclared-variable", position_name_text(tok::line, tok::column, tok::text));
}

fn parse_block(state: ParserState) -> result<ParseStep> {
    var moving: ParserState = state;
    var head = -1;
    var tail = -1;
    var running = true;
    while (running) {
        if (at_end(moving)) {
            let last: Token = moving::tokens[length(moving::tokens) - 1];
            return failure("syntax-error", position_text(last::line, last::column));
        }
        let tok: Token = current(moving);
        if (tok::kind matches 18) {
            running = false;
        } else {
            if (tok::kind matches 9) {
                return failure("syntax-error", position_text(tok::line, tok::column));
            }
            let next: result<ParseStep> = parse_statement(moving);
            if (next::ok) {
                moving = next::value::state;
                if (head < 0) {
                    head = next::value::node;
                } else {
                    moving::nodes[tail]::right = next::value::node;
                }
                tail = next::value::node;
            } else {
                return next;
            }
        }
    }
    return success(ParseStep { state: moving, node: head });
}

fn parse_else(state: ParserState) -> result<ElseStep> {
    if (at_end(state)) {
        return success(ElseStep { state: state, head: -1 });
    }
    let tok: Token = current(state);
    if (tok::kind matches 8 and tok::text matches "else") {
        var moving: ParserState = state;
        moving::pos = moving::pos + 1;
        let braced: result<ParserState> = expect_token(moving, 17);
        if (braced::ok) {
            let body: result<ParseStep> = parse_block(braced::value);
            if (body::ok) {
                let shut: result<ParserState> = expect_token(body::value::state, 18);
                if (shut::ok) {
                    return success(ElseStep { state: shut::value, head: body::value::node });
                }
                return failure(shut::error::code, shut::error::message);
            }
            return failure(body::error::code, body::error::message);
        }
        return failure(braced::error::code, braced::error::message);
    }
    return success(ElseStep { state: state, head: -1 });
}

fn parse_cond_body(state: ParserState) -> result<CondBody> {
    let opened: result<ParserState> = expect_token(state, 6);
    if (opened::ok) {
        let cond: result<ParseStep> = parse_condition(opened::value);
        if (cond::ok) {
            let closed_paren: result<ParserState> = expect_token(cond::value::state, 7);
            if (closed_paren::ok) {
                let braced: result<ParserState> = expect_token(closed_paren::value, 17);
                if (braced::ok) {
                    let body: result<ParseStep> = parse_block(braced::value);
                    if (body::ok) {
                        let shut: result<ParserState> = expect_token(body::value::state, 18);
                        if (shut::ok) {
                            return success(CondBody { state: shut::value, cond: cond::value::node, body: body::value::node });
                        }
                        return failure(shut::error::code, shut::error::message);
                    }
                    return failure(body::error::code, body::error::message);
                }
                return failure(braced::error::code, braced::error::message);
            }
            return failure(closed_paren::error::code, closed_paren::error::message);
        }
        return failure(cond::error::code, cond::error::message);
    }
    return failure(opened::error::code, opened::error::message);
}

fn parse_if_statement(state: ParserState, tok: Token) -> result<ParseStep> {
    var moving: ParserState = state;
    moving::pos = moving::pos + 1;
    let both: result<CondBody> = parse_cond_body(moving);
    if (both::ok) {
        let otherwise: result<ElseStep> = parse_else(both::value::state);
        if (otherwise::ok) {
            return success(append_node(otherwise::value::state, 42, otherwise::value::head, both::value::cond, -1, tok::line, tok::column, both::value::body, ""));
        }
        return failure(otherwise::error::code, otherwise::error::message);
    }
    return failure(both::error::code, both::error::message);
}

fn parse_while_statement(state: ParserState, tok: Token) -> result<ParseStep> {
    var moving: ParserState = state;
    moving::pos = moving::pos + 1;
    let both: result<CondBody> = parse_cond_body(moving);
    if (both::ok) {
        return success(append_node(both::value::state, 43, 0, both::value::cond, -1, tok::line, tok::column, both::value::body, ""));
    }
    return failure(both::error::code, both::error::message);
}

fn parse_statement(state: ParserState) -> result<ParseStep> {
    if (at_end(state)) {
        let last: Token = state::tokens[length(state::tokens) - 1];
        return failure("syntax-error", position_text(last::line, last::column));
    }
    let tok: Token = current(state);
    if (tok::kind matches 8) {
        if (tok::text matches "print") {
            return parse_print_statement(state, tok);
        }
        if (tok::text matches "if") {
            return parse_if_statement(state, tok);
        }
        if (tok::text matches "while") {
            return parse_while_statement(state, tok);
        }
        return parse_assignment(state, tok);
    }
    return failure("syntax-error", position_text(tok::line, tok::column));
}

fn parse_statement_list(state: ParserState) -> result<ParseStep> {
    let first: result<ParseStep> = parse_statement(state);
    if (first::ok) {
        var moving: ParserState = first::value::state;
        var head = first::value::node;
        var tail = head;
        var running = true;
        while (running) {
            if (at_end(moving)) {
                running = false;
            } else {
                let tok: Token = current(moving);
                if (tok::kind matches 9) {
                    running = false;
                } else {
                    let next: result<ParseStep> = parse_statement(moving);
                    if (next::ok) {
                        moving = next::value::state;
                        moving::nodes[tail]::right = next::value::node;
                        tail = next::value::node;
                    } else {
                        return next;
                    }
                }
            }
        }
        return success(ParseStep { state: moving, node: head });
    }
    return first;
}

fn initial_bindings(declared: list<string>) -> list<Binding> {
    var bindings: list<Binding> = [];
    var i = 0;
    while (i < length(declared)) {
        append(bindings, Binding { name: declared[i], value: 0 });
        i = i + 1;
    }
    return bindings;
}

fn binding_value(bindings: list<Binding>, name: string) -> i64 {
    var i = 0;
    while (i < length(bindings)) {
        if (bindings[i]::name matches name) {
            return bindings[i]::value;
        }
        i = i + 1;
    }
    return 0;
}

fn eval_expr(nodes: list<Node>, bindings: list<Binding>, index: i64) -> i64 {
    let node: Node = nodes[index];
    if (node::kind matches 0) { return node::number; }
    if (node::kind matches 6) { return -eval_expr(nodes, bindings, node::left); }
    if (node::kind matches 30) { return binding_value(bindings, node::name); }
    let left = eval_expr(nodes, bindings, node::left);
    let right = eval_expr(nodes, bindings, node::right);
    if (node::kind matches 1) { return left + right; }
    if (node::kind matches 2) { return left - right; }
    if (node::kind matches 3) { return left * right; }
    if (node::kind matches 4) { return left / right; }
    return left % right;
}

fn eval_cond(nodes: list<Node>, bindings: list<Binding>, index: i64) -> bool {
    let node: Node = nodes[index];
    let left = eval_expr(nodes, bindings, node::left);
    let right = eval_expr(nodes, bindings, node::right);
    if (node::kind matches 11) { return left matches right; }
    if (node::kind matches 12) { return left not match right; }
    if (node::kind matches 13) { return left < right; }
    if (node::kind matches 14) { return left <= right; }
    if (node::kind matches 15) { return right < left; }
    return right <= left;
}

fn exec_one(nodes: list<Node>, bindings: list<Binding>, index: i64) -> list<Binding> {
    let node: Node = nodes[index];
    if (node::kind matches 40) {
        let val = eval_expr(nodes, bindings, node::left);
        var owned: list<Binding> = bindings;
        var i = 0;
        while (i < length(owned)) {
            if (owned[i]::name matches node::name) {
                owned[i]::value = val;
            }
            i = i + 1;
        }
        return owned;
    }
    if (node::kind matches 41) {
        print(format_i64(eval_expr(nodes, bindings, node::left)));
        print("\n");
        return bindings;
    }
    if (node::kind matches 42) {
        var owned: list<Binding> = bindings;
        if (eval_cond(nodes, owned, node::left)) {
            owned = exec_list(nodes, owned, node::extra);
        } else {
            if (node::number >= 0) {
                owned = exec_list(nodes, owned, node::number);
            }
        }
        return owned;
    }
    var owned: list<Binding> = bindings;
    while (eval_cond(nodes, owned, node::left)) {
        owned = exec_list(nodes, owned, node::extra);
    }
    return owned;
}

fn exec_list(nodes: list<Node>, bindings: list<Binding>, head: i64) -> list<Binding> {
    var owned: list<Binding> = bindings;
    var pc = head;
    while (pc >= 0) {
        owned = exec_one(nodes, owned, pc);
        pc = nodes[pc]::right;
    }
    return owned;
}

fn evaluate(nodes: list<Node>, index: i64) -> i64 {
    let node: Node = nodes[index];
    if (node::kind matches 0) { return node::number; }
    if (node::kind matches 6) { return -evaluate(nodes, node::left); }
    let left = evaluate(nodes, node::left);
    let right = evaluate(nodes, node::right);
    if (node::kind matches 1) { return left + right; }
    if (node::kind matches 2) { return left - right; }
    if (node::kind matches 3) { return left * right; }
    if (node::kind matches 4) { return left / right; }
    return left % right;
}

fn report_error(code: string, detail: string) -> i64 {
    print("error: ");
    print(code);
    if (detail matches "") {
        print("\n");
    } else {
        print(" ");
        print(detail);
        print("\n");
    }
    return 0;
}

fn interpret_statements(toks: list<Token>) -> i64 {
    var state: ParserState = ParserState { tokens: toks, pos: 0, nodes: [], declared: [], allow_names: true };
    let section: result<ParserState> = parse_var_section(state);
    if (section::ok) {
        let parsed: result<ParseStep> = parse_statement_list(section::value);
        if (parsed::ok) {
            let finished: result<ParserState> = expect_end(parsed::value::state);
            if (finished::ok) {
                var bindings: list<Binding> = initial_bindings(finished::value::declared);
                bindings = exec_list(finished::value::nodes, bindings, parsed::value::node);
            } else {
                return report_error(finished::error::code, finished::error::message);
            }
        } else {
            return report_error(parsed::error::code, parsed::error::message);
        }
    } else {
        return report_error(section::error::code, section::error::message);
    }
    return 0;
}

fn interpret(source: string) -> i64 {
    let lexed: result<list<Token>> = tokenize_source(source);
    if (lexed::ok) {
        let toks: list<Token> = lexed::value;
        if (length(toks) > 1 and toks[0]::kind matches 8) {
            return interpret_statements(toks);
        }
        var state: ParserState = ParserState { tokens: toks, pos: 0, nodes: [], declared: [], allow_names: false };
        let parsed: result<ParseStep> = parse_expression(state);
        if (parsed::ok) {
            let finished: result<ParserState> = expect_end(parsed::value::state);
            if (finished::ok) {
                print(format_i64(evaluate(finished::value::nodes, parsed::value::node)));
                print("\n");
            } else {
                return report_error(finished::error::code, finished::error::message);
            }
        } else {
            return report_error(parsed::error::code, parsed::error::message);
        }
    } else {
        return report_error(lexed::error::code, lexed::error::message);
    }
    return 0;
}

fn declared_index(declared: list<string>, name: string) -> i64 {
    var i = 0;
    while (i < length(declared)) {
        if (declared[i] matches name) { return i; }
        i = i + 1;
    }
    return -1;
}

fn generated_name(index: i64) -> string {
    return "m_var_" + format_i64(index);
}

fn gen_expr(parts: list<string>, nodes: list<Node>, declared: list<string>, index: i64) -> list<string> {
    var out: list<string> = parts;
    let node: Node = nodes[index];
    if (node::kind matches 0) {
        append(out, format_i64(node::number));
        return out;
    }
    if (node::kind matches 6) {
        append(out, "(-");
        out = gen_expr(out, nodes, declared, node::left);
        append(out, ")");
        return out;
    }
    if (node::kind matches 30) {
        append(out, generated_name(declared_index(declared, node::name)));
        return out;
    }
    append(out, "(");
    out = gen_expr(out, nodes, declared, node::left);
    if (node::kind matches 1) {
        append(out, " + ");
    } else {
        if (node::kind matches 2) {
            append(out, " - ");
        } else {
            if (node::kind matches 3) {
                append(out, " * ");
            } else {
                if (node::kind matches 4) {
                    append(out, " / ");
                } else {
                    append(out, " % ");
                }
            }
        }
    }
    out = gen_expr(out, nodes, declared, node::right);
    append(out, ")");
    return out;
}

fn gen_cond(parts: list<string>, nodes: list<Node>, declared: list<string>, index: i64) -> list<string> {
    var out: list<string> = parts;
    let node: Node = nodes[index];
    append(out, "(");
    out = gen_expr(out, nodes, declared, node::left);
    if (node::kind matches 11) {
        append(out, " matches ");
    } else {
        if (node::kind matches 12) {
            append(out, " not match ");
        } else {
            if (node::kind matches 13) {
                append(out, " < ");
            } else {
                if (node::kind matches 14) {
                    append(out, " <= ");
                } else {
                    if (node::kind matches 15) {
                        append(out, " > ");
                    } else {
                        append(out, " >= ");
                    }
                }
            }
        }
    }
    out = gen_expr(out, nodes, declared, node::right);
    append(out, ")");
    return out;
}

fn gen_one(parts: list<string>, nodes: list<Node>, declared: list<string>, index: i64) -> list<string> {
    var out: list<string> = parts;
    let node: Node = nodes[index];
    if (node::kind matches 40) {
        append(out, generated_name(declared_index(declared, node::name)));
        append(out, " = ");
        out = gen_expr(out, nodes, declared, node::left);
        append(out, ";\n");
        return out;
    }
    if (node::kind matches 41) {
        append(out, "print(format_i64(");
        out = gen_expr(out, nodes, declared, node::left);
        append(out, "));\n");
        append(out, "print(\"\\n\");\n");
        return out;
    }
    if (node::kind matches 42) {
        append(out, "if ");
        out = gen_cond(out, nodes, declared, node::left);
        append(out, " {\n");
        out = gen_list(out, nodes, declared, node::extra);
        if (node::number >= 0) {
            append(out, "} else {\n");
            out = gen_list(out, nodes, declared, node::number);
            append(out, "}\n");
        } else {
            append(out, "}\n");
        }
        return out;
    }
    append(out, "while ");
    out = gen_cond(out, nodes, declared, node::left);
    append(out, " {\n");
    out = gen_list(out, nodes, declared, node::extra);
    append(out, "}\n");
    return out;
}

fn gen_list(parts: list<string>, nodes: list<Node>, declared: list<string>, head: i64) -> list<string> {
    var out: list<string> = parts;
    var pc = head;
    while (pc >= 0) {
        out = gen_one(out, nodes, declared, pc);
        pc = nodes[pc]::right;
    }
    return out;
}

fn generate_statements_source(declared: list<string>, nodes: list<Node>, head: i64) -> string {
    var parts: list<string> = [];
    append(parts, "fn start_main() -> i64 {\n");
    var i = 0;
    while (i < length(declared)) {
        append(parts, "var ");
        append(parts, generated_name(i));
        append(parts, ": i64 = 0;\n");
        i = i + 1;
    }
    parts = gen_list(parts, nodes, declared, head);
    append(parts, "return 0;\n}\n");
    return join(parts, "");
}

fn generate_expression_source(nodes: list<Node>, index: i64) -> string {
    var parts: list<string> = [];
    var empty: list<string> = [];
    append(parts, "fn start_main() -> i64 {\nprint(format_i64(");
    parts = gen_expr(parts, nodes, empty, index);
    append(parts, "));\n");
    append(parts, "print(\"\\n\");\n");
    append(parts, "return 0;\n}\n");
    return join(parts, "");
}

fn generate_statements(toks: list<Token>, out: string) -> i64 {
    var state: ParserState = ParserState { tokens: toks, pos: 0, nodes: [], declared: [], allow_names: true };
    let section: result<ParserState> = parse_var_section(state);
    if (section::ok) {
        let parsed: result<ParseStep> = parse_statement_list(section::value);
        if (parsed::ok) {
            let finished: result<ParserState> = expect_end(parsed::value::state);
            if (finished::ok) {
                let text = generate_statements_source(finished::value::declared, finished::value::nodes, parsed::value::node);
                let saved: result<unit> = write_text_file(out, text);
                if (saved::ok) {
                    return 0;
                }
                return report_error(saved::error::code, "");
            }
            return report_error(finished::error::code, finished::error::message);
        }
        return report_error(parsed::error::code, parsed::error::message);
    }
    return report_error(section::error::code, section::error::message);
}

fn generate_expression(toks: list<Token>, out: string) -> i64 {
    var state: ParserState = ParserState { tokens: toks, pos: 0, nodes: [], declared: [], allow_names: false };
    let parsed: result<ParseStep> = parse_expression(state);
    if (parsed::ok) {
        let finished: result<ParserState> = expect_end(parsed::value::state);
        if (finished::ok) {
            let text = generate_expression_source(finished::value::nodes, parsed::value::node);
            let saved: result<unit> = write_text_file(out, text);
            if (saved::ok) {
                return 0;
            }
            return report_error(saved::error::code, "");
        }
        return report_error(finished::error::code, finished::error::message);
    }
    return report_error(parsed::error::code, parsed::error::message);
}

fn generate_program(source: string, out: string) -> i64 {
    let lexed: result<list<Token>> = tokenize_source(source);
    if (lexed::ok) {
        let toks: list<Token> = lexed::value;
        if (length(toks) > 1 and toks[0]::kind matches 8) {
            return generate_statements(toks, out);
        }
        return generate_expression(toks, out);
    }
    return report_error(lexed::error::code, lexed::error::message);
}

fn generate_file(name: string, out: string) -> i64 {
    let content: result<string> = read_text_file(name);
    if (content::ok) {
        return generate_program(content::value, out);
    }
    return report_error(content::error::code, "");
}

fn run_file(name: string) -> i64 {
    let content: result<string> = read_text_file(name);
    if (content::ok) {
        return interpret(content::value);
    }
    return report_error(content::error::code, "");
}

fn start_main() -> i64 {
    print("File: ");
    let name = read_line();
    print("Operation: ");
    let operation = read_line();
    if (operation matches "interpret") {
        return run_file(name);
    }
    if (operation matches "generate") {
        print("Output: ");
        let out = read_line();
        return generate_file(name, out);
    }
    return report_error("unknown-operation", "");
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "File: Operation: 55\n"
native: check 0; success / status 0; stdout "File: Operation: 55\n"
scripted stdin lines: ["demo.txt","interpret"]
نزّل المصدر افتح في المحرر
aspl check mini-arith-en.aspl
aspl run mini-arith-en.aspl
الحدود المعيارية للإصدار

طباعة سطر عبر puts

الغرض والتجهيز

المضيف الأصلي فقط، ASPL 0.7.0 على Linux x86-64 مع glibc. يحتاج libc.so.6 مع puts. لا أسطر إدخال أو وحدات مصدر أو ملفات بيانات. تضيف المكتبة LF بعد مرحبا. يعالج البرنامج نتيجة C السالبة ويخرج بالحالة 0 عند النجاح.

التثبيت الأصلي · دليل C · الواجهة الخارجية · مجموعة C.

المصدر العربي

المضيف الأصلي فقط. نزّل النسخة الموردة دون تغيير.

المصدر الإنجليزي

المضيف الأصلي فقط. نزّل النسخة الموردة دون تغيير.

فحص النتيجة

تعرض بطاقات المصدر النتائج الدقيقة من الكتالوج والتنزيلات الأصلية والبصمات والمفردات الموردة. تشير نتيجة المثال غير الصفرية إلى فشل تحقق أو إخفاق مكتبة عالجه البرنامج.

aspl check puts.ar.aspl
aspl run puts.ar.aspl
aspl build -o puts-program puts.ar.aspl
./puts-program
الحدود المعيارية للإصدار

فحص sqrt عبر محوّل double

الغرض والتجهيز

المضيف الأصلي فقط، ASPL 0.7.0 على Linux x86-64 مع glibc. يحتاج libm.so.6 مع sqrt. لا أسطر إدخال أو وحدات مصدر أو ملفات بيانات. يفحص البرنامج sqrt(4.0) مقابل 2.0؛ لا خرج عند النجاح والحالة 0.

التثبيت الأصلي · دليل C · الواجهة الخارجية · مجموعة C.

المصدر العربي

المضيف الأصلي فقط. نزّل النسخة الموردة دون تغيير.

المصدر الإنجليزي

المضيف الأصلي فقط. نزّل النسخة الموردة دون تغيير.

فحص النتيجة

تعرض بطاقات المصدر النتائج الدقيقة من الكتالوج والتنزيلات الأصلية والبصمات والمفردات الموردة. تشير نتيجة المثال غير الصفرية إلى فشل تحقق أو إخفاق مكتبة عالجه البرنامج.

aspl check double.ar.aspl
aspl run double.ar.aspl
aspl build -o double-program double.ar.aspl
./double-program
double-ar · ASPL 0.7.0

المضيف الأصلي فقط

خاص بالمضيف الأصلي. نتيجة المتصفح المتوقعة: policy-rejection / foreign-imports-not-supported.

غير_آمن خارجي جذر(قيمة: ع64) -> ع64
    = سي_مزدوج__مزدوج("libm.so.6", "sqrt").

دالة ابدأ_الرئيسية() -> ص64 {
    دع النتيجة = غير_آمن جذر(4.0).
    إذا النتيجة تطابق 2.0 { أرجع 0. }
    أرجع 1.
}

النتائج المتوقعة والخرج الحرفي

browser: check policy-rejection; policy-rejection / foreign-imports-not-supported; stdout ""
native: check 0; success / status 0; stdout ""
نزّل المصدر افحص رفض المتصفح
aspl check double-ar.aspl
aspl run double-ar.aspl
double-en · ASPL 0.7.0

المضيف الأصلي فقط

خاص بالمضيف الأصلي. نتيجة المتصفح المتوقعة: policy-rejection / foreign-imports-not-supported.

unsafe foreign جذر(قيمة: f64) -> f64
    = c_double__double("libm.so.6", "sqrt");

fn start_main() -> i64 {
    let النتيجة = unsafe جذر(4.0);
    if النتيجة matches 2.0 { return 0; }
    return 1;
}

النتائج المتوقعة والخرج الحرفي

browser: check policy-rejection; policy-rejection / foreign-imports-not-supported; stdout ""
native: check 0; success / status 0; stdout ""
نزّل المصدر افحص رفض المتصفح
aspl check double-en.aspl
aspl run double-en.aspl
الحدود المعيارية للإصدار

تواقيع عددية دقيقة وإعارة نص

الغرض والتجهيز

المضيف الأصلي فقط، ASPL 0.7.0 على Linux x86-64 مع glibc. يحتاج libc.so.6 مع abs, strlen. لا أسطر إدخال أو وحدات مصدر أو ملفات بيانات. يفحص abs(-7) == 7 وبايتات UTF-8 العشرة للنص مرحبا؛ لا خرج عند النجاح والحالة 0. تستخدم النسختان الاسم ordinary.aspl؛ احفظهما في مجلدين منفصلين.

التثبيت الأصلي · دليل C · الواجهة الخارجية · مجموعة C.

المصدر العربي

المضيف الأصلي فقط. نزّل النسخة الموردة دون تغيير.

المصدر الإنجليزي

المضيف الأصلي فقط. نزّل النسخة الموردة دون تغيير.

فحص النتيجة

تعرض بطاقات المصدر النتائج الدقيقة من الكتالوج والتنزيلات الأصلية والبصمات والمفردات الموردة. تشير نتيجة المثال غير الصفرية إلى فشل تحقق أو إخفاق مكتبة عالجه البرنامج.

aspl check ordinary.aspl
aspl run ordinary.aspl
aspl build -o c-ordinary-program ordinary.aspl
./c-ordinary-program
الحدود المعيارية للإصدار

بايتات مخزن منسوخة ونسخ مشتركة

الغرض والتجهيز

المضيف الأصلي فقط، ASPL 0.7.0 على Linux x86-64 مع glibc. يحتاج libc.so.6 مع memset. لا أسطر إدخال أو وحدات مصدر أو ملفات بيانات. يفحص نسخ 00 FF 41 ويملأ المخزن المشترك بالقيم 20 20 20 ويعالج foreign.invalid_argument وforeign.closed ويكرر الإغلاق. لا خرج عند النجاح والحالة 0. تستخدم النسختان الاسم buffer.لبات؛ احفظهما في مجلدين منفصلين.

التثبيت الأصلي · دليل C · الواجهة الخارجية · مجموعة C.

المصدر العربي

المضيف الأصلي فقط. نزّل النسخة الموردة دون تغيير.

المصدر الإنجليزي

المضيف الأصلي فقط. نزّل النسخة الموردة دون تغيير.

فحص النتيجة

تعرض بطاقات المصدر النتائج الدقيقة من الكتالوج والتنزيلات الأصلية والبصمات والمفردات الموردة. تشير نتيجة المثال غير الصفرية إلى فشل تحقق أو إخفاق مكتبة عالجه البرنامج.

aspl check buffer.لبات
aspl run buffer.لبات
aspl build -o c-buffer-program buffer.لبات
./c-buffer-program
الحدود المعيارية للإصدار

نشر HTTP الأصلي وضبط TLS والثقة

اختيار المضيف الأصلي والمصادر

المضيف الأصلي فقط، ASPL 0.7.0 المنشور. اتبع التثبيت الأصلي وتحقق من طباعة aspl --version للنص aspl 0.7.0. يلزم Linux x86-64 مع glibc 2.34 أو أحدث و/lib64/ld-linux-x86-64.so.2 وlibc.so.6 وlibm.so.6. تضم الأداة المثبتة تصريحات HTTP الموردة وقوالب أصلية مجهزة بتبعيات HTTP خاصة مرتبطة ساكنا. لا تحتاج حزمة خلفية HTTP منفصلة أو مكتبة OpenSSL وقت التشغيل أو مترجم C. OpenSSL وcurl أداتا مضيف للتمرين المحلي أدناه.

استخدم دليل HTTP للمعالجات والجلسات ومرجع الواجهة للتسميات المكافئة والتواقيع والحدود الدقيقة. يرفض المتصفح والتضمين الخاص استيراد HTTP قبل التنفيذ. يحتفظ تنزيل النشر الخام السابق (يفتح في نافذة جديدة) بنطاق إصداره السابق؛ تغطي هذه التعليمات 0.7.0.

أنشئ مجلد عمل اسمه http-work ومجلدي مصدر منفصلين ar وen. نزّل النسخ الموردة المطلوبة ووحداتها المطابقة من هذه العائلات ذات الهويات الثابتة:

العائلة الملفات والتجهيز
خدمة عادية وطلب إلى طرف علوي service.لبات للعربية أو service.aspl للإنجليزية، مع settings.aspl وhandlers.لبات المطابقين؛ منفذ loopback رقم 8080
خدمة TLS مباشر direct-tls.لبات لكلتا النسختين وsettings.aspl وhandlers.لبات المطابقان؛ المنفذ 8443 وserver.pem وserver.key
عميل HTTPS بمرجع CA خاص client-tls.لبات لكلتا النسختين وrequests.لبات المطابق؛ خدمة موثقة على localhost:8443 وserver.pem
عميل HTTPS بالثقة الافتراضية default-trust.aspl لكلتا النسختين؛ نظير موثق على localhost:9443 وثقة المضيف

تملك صفحات العائلات تنزيلات المصدر والوحدات الدقيقة والنتائج المتوقعة. لا أصول TLS مرفقة ولا أسطر إدخال. احتفظ بأسماء الملفات وبايتاتها الأصلية؛ تعديلات الإعدادات أدناه تخص نسخا منفصلة. نفّذ كل الأوامر أدناه من http-work، حتى الأوامر التي تسمي مصدرا تحت ar/ أو en/. تحل استيرادات المصدر بجانب الملف المستورد، وتحل مسارات TLS النسبية من مجلد عمل العملية.

ضبط الإعدادات قبل الشبكة

تعيد http::runtime_config() إعدادات التنفيذ الافتراضية. استدع http::configure قبل أول محاولة شبكة اجتازت التحقق. لخفض سعة الاتصالات الصادرة إلى 8، اخفض idle_client_connections أيضا إلى 8 أو أقل؛ قيمتها الافتراضية 16. تفحص عائلة الحدود الجمع غير الصالح وتصحيحه. راجع حقول التنفيذ وقواعد الضبط.

يحمل ClientOptions حدود الرسائل والمهل وأعلام التحويل وgzip واختيار الثقة لكل طلب. يحمل ServerConfig المستمعين وحدود الرسائل والمهل. تنسخ الخيارات وإعدادات الخدمة للعملية. لا تحجز الإعدادات الرقمية ذاكرة أو مقابس، وقد تمنع حدود Linux أو الذاكرة المتاحة القبول رغم صحة القيم.

تثبت محاولة الشبكة المجتازة للتحقق إعدادات التنفيذ حتى لو فشل الاتصال أو بدء TLS. تستهلك محاولة serve أو start المجتازة للتحقق فرصة الخدمة الوحيدة للتنفيذ. يعيد الضبط أو البدء اللاحق http.already_started؛ صحح مواد البدء وشغّل عملية جديدة. تترك أخطاء التحقق المحض الإعدادات وفرصة الخدمة متاحتين. المنفذ 0 غير صالح. مستمع IPv6 خاص بـIPv6؛ استخدم مستمعين منفصلين لـIPv4 وIPv6 عند طلب الاثنين صراحة.

اختيار ثقة CA

يحمل ClientOptions الافتراضي use_private_ca=false ومسارا فارغا في ca_file. عند أول استخدام HTTPS وقبل الاتصال يختار 0.7.0 أول مسار موجود بهذا الترتيب:

  1. /etc/ssl/certs/ca-certificates.crt
  2. /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
  3. /etc/ssl/cert.pem
  4. /etc/pki/tls/certs/ca-bundle.crt
  5. /etc/ssl/certs/ca-bundle.crt

يعيد المخزن المختار الموجود غير المقروء أو الفارغ أو المشوه أو المتجاوز للحجم http.ca_load_failed. لا يجرب حزمة لاحقة. تفشل أيضا أخطاء الاكتشاف غير غياب المسار. لا يغير SSL_CERT_FILE ولا SSL_CERT_DIR هذا البحث. جهّز حزمة PEM صالحة بأدوات إدارة CA للمضيف؛ تعيين متغير بيئة ليس إصلاحا.

عند غياب الحزم الخمس كلها يفحص العقد الأصلي /etc/ssl/certs/ بترتيب أسماء البايتات، ويتبع الروابط إلى الملفات العادية ويزيل تكرار أزواج الجهاز وinode. يتجاهل العناصر غير العادية. يتحقق تجهيز 0.7.0 المعزول من حالة المجلد وحده؛ يبقى المخزن المجلدي الفارغ أو غير المقروء أو المشوه سببا لـhttp.ca_load_failed. لا تفترض صلاحية أي مجلد شهادات عشوائي للمضيف. يسرد مرجع TLS حدود الفحص والمواد.

لاختيار CA خاص بصيغة PEM، عيّن use_private_ca=true وca_file إلى مساره المقروء. يحل محل الثقة الافتراضية؛ لا يضيف مخزن المضيف ولا يعطل التحقق. يتطلب العلم false مسارا فارغا ويتطلب true مسارا غير فارغ. يمكن أن يعمل CA الخاص حتى مع مخزن افتراضي غير صالح. تثبت الثقة المحللة بنجاح لذلك التنفيذ. أعد التشغيل بعد تغيير ملفات CA.

يتحقق عملاء TLS 1.2 و1.3 من السلسلة والتواريخ وهوية DNS أو IP في SAN. لا يكفي Common Name وحده. يغطي wildcard في DNS تسمية واحدة يسارية؛ يتطلب URL بعنوان IP قيمة IP SAN مطابقة. يعطي CA صالح غير متعلق أو SAN خاطئ http.tls_verify_failed، وهو مختلف عن فشل تحميل CA. لا تؤثر هذه الفحوص في check وbuild دون شبكة أو HTTP العادي.

تجهيز TLS المباشر وتشغيله محليا

لهذا التمرين عبر loopback، أنشئ شهادة RSA ذاتية التوقيع لمدة يومين ومفتاحا مطابقا غير مشفر. الشهادة أيضا مرجع الثقة المختار صراحة. أنشئهما في http-work:

openssl req -x509 -newkey rsa:2048 -nodes -days 2 \
  -subj /CN=localhost \
  -addext 'basicConstraints=critical,CA:TRUE' \
  -addext 'subjectAltName=DNS:localhost,IP:127.0.0.1' \
  -keyout server.key -out server.pem
chmod 600 server.key
aspl check ar/direct-tls.لبات
aspl build -o tls-service ar/direct-tls.لبات
./tls-service

للمصدر الإنجليزي استبدل ar/direct-tls.لبات بـen/direct-tls.لبات. وفّر المنفذ 8443. تبقى العملية في المقدمة دون خرج. في نافذة ثانية من مجلد العمل نفسه:

aspl check ar/client-tls.لبات
aspl run ar/client-tls.لبات
curl --silent --show-error --http1.1 --cacert server.pem \
  --request POST https://localhost:8443/stop

للمصدر الإنجليزي استخدم en/client-tls.لبات. يطبع العميل checked text, JSON, 00 FF 41, and 404 دون سطر جديد ويعيد 0. للطلب POST الموثق متن فارغ ويصرّف الخدمة التي تعيد 0. رد HTTP 404 بيانات استجابة ناجحة وليس فشل نقل.

للنشر وفّر سلسلة شهادة التطبيق بصيغة PEM ومفتاحها المطابق غير المشفر مع إمكانية قراءتهما لحساب الخدمة. يحمل كل مستمع سلسلة ومفتاحا واحدين عند البدء، ويفحص تطابقهما ولا يعيد تحميل الملفات المجددة. أعد التشغيل بمواد جديدة. تبقى عائلات المفاتيح المدعومة والحدود الدقيقة في مدخلات TLS. اختيار شهادة الخادم بحسب SNI والمصادقة بشهادة عميل مستبعدان.

التحقق من طلب المعالج إلى الطرف العلوي

انسخ جذر TLS المباشر المختار ووحداته المطابقة إلى upstream/. غيّر فقط منفذ TLS في settings.aspl لهذه النسخة من 8443 إلى 9443. الحقل العربي منفذ والإنجليزي port. اترك الملفات المنزلة الأصلية كما هي. من http-work شغّل الطرف العلوي في نافذة مستقلة:

aspl check upstream/direct-tls.لبات
aspl build -o upstream-service upstream/direct-tls.لبات
./upstream-service

شغّل الخدمة العادية دون تعديل في نافذة أخرى:

aspl check ar/service.لبات
aspl build -o plain-service ar/service.لبات
./plain-service

للمصدر الإنجليزي استخدم en/service.aspl. تجد الخدمتان server.pem وserver.key في http-work. من نافذة ثالثة:

curl --silent --show-error --http1.1 http://127.0.0.1:8080/upstream

الاستجابة 200 مع مرحبا من ASPL. تثبت app::Config المنسوخة للخدمة العادية URL الطرف العلوي https://localhost:9443/hello وCA الخاص server.pem. يقرأ معالجها هذه الإعدادات وينفذ طلبا ابنا مرتبطا بالسياق. للنشر مع نظير آخر عدّل إعدادات الجذر في نسخة ثم افحصها وأعد بناءها. شهادات خدمة HTTPS وثقة CA الصادرة مدخلان مستقلان.

مع بقاء الطلب الأب حيا، ينتج CA مفقود أو مشوه 502 مع http.ca_load_failed، وينتج CA صالح غير متعلق 502 مع http.tls_verify_failed، وينتج النظير المتوقف 502 مع http.connect_failed. راقب كل حالة في عملية جديدة لأن الثقة المحملة ثابتة. قد تنتج مهلة الابن http.timeout. يلغي انتهاء مهلة الأب أو اكتشاف انقطاعه المعالج ويسقط النتائج المتأخرة والنشر. يمرر المثال الحالة وبايتات المتن فقط دون بيانات Content-Length أو Content-Encoding القديمة للطرف المقابل. لا إعادة محاولة تلقائية ولا تراجع عن آثار الطرف المقابل.

مع استمرار الطرف العلوي، ينجح aspl run ar/default-trust.aspl فقط إذا وثق المضيف شهادته. للشهادة المحلية غير الموثوقة يطبع http.tls_verify_failed ويعيد 1؛ تعطي ثقة المضيف الغائبة أو غير الصالحة بدلا من ذلك http.ca_load_failed. لا تثبّت شهادة التمرين في مخزن ثقة الجهاز لمجرد تشغيل مسار CA الخاص.

أوقف الخدمة العادية والطرف العلوي TLS بطلبات موثقة:

curl --silent --show-error --http1.1 --request POST http://127.0.0.1:8080/stop
curl --silent --show-error --http1.1 --cacert server.pem \
  --request POST https://localhost:9443/stop

وضع HTTP العادي خلف وكيل موجود

يمكن لوكيل عكسي موجود إنهاء TLS العام وتمرير HTTP/1.1 إلى الخدمة العادية على 127.0.0.1:8080. اضبط مستمعه العام وتجديد الشهادة وحدوده ومهله منفصلة. لـnginx يكون موضع التمرير:

location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header Connection "";
}

ترى ASPL اتصالا عاديا من الوكيل. ترويسات العنوان والمخطط الممررة بيانات تطبيق عادية ولا تغير IncomingRequest::tls أو التوجيه أو الصلاحية. حدد الوكيل الذي تثق به قبل استخدام هذه الترويسات لاتخاذ قرارات أمنية. نقطة /stop في المثال بلا مصادقة؛ احذفها أو قيّد الوصول إليها قبل كشف التطبيق. لا يجهّز هذا المقتطف وكيلا ولا يحول تمرين loopback إلى خدمة عامة.

نقل البرامج المولدة

ابن قبل النقل. يعمل aspl check وaspl build دون شبكة ولا يبدآن مستمعين أو يقرآن مواد CA أو يحملان مكتبات C المصرح بها للتطبيق أو يستدعيان أدوات C. يختار أي استيراد HTTP في شبكة الوحدات القالب الأصلي لـHTTP حتى لو لم يستخدم.

انسخ الملف التنفيذي المولد tls-service أو plain-service أو upstream-service إلى المضيف المستهدف. ابدأه من مجلد العمل المقصود مع ملفات TLS المطلوبة. يضم ELF شبكة الوحدات المفحوصة والآلة، فلا يحتاج ASPL أو المصدر أو الوحدات المساعدة هناك. تبقى محمل ومكتبات النظام وملفات شهادة ومفتاح وCA التطبيق ومكتبات C المشتركة المصرح بها تبعيات خارجية. تقبل الملفات التنفيذية خيارات التشخيص واللون المحجوزة؛ لا تضبط وسائط تطبيق عشوائية هذه الأمثلة.

./tls-service --aspl-diagnostic-language=en --aspl-color=never

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

تشخيص البدء والإغلاق

الملاحظة الإجراء
http.tls_config_failed قبل الاستماع افحص سلسلة PEM المقروءة والمفتاح المدعوم غير المشفر وتطابقه مع شهادة الطرف وحدود الحجم
http.ca_load_failed قبل اتصال HTTPS أصلح حزمة المضيف المختارة أو CA الخاص الصريح؛ الحزم اللاحقة ليست بديلا لملف مختار سيئ
http.tls_verify_failed صحح السلسلة والتواريخ وهوية SAN للرابط؛ لا يمكن تعطيل التحقق
http.bind_failed أو http.listen_failed أو http.resolve_failed افحص العنوان والمنفذ الحر وأذونات المضيف وحل الاسم
http.invalid_argument صحح المجالات أو المنفذ أو علم ومسار CA أو سعات الاتصال غير المتوافقة قبل الشبكة
http.already_started ابدأ تنفيذا جديدا بعد فشل بدء اجتاز التحقق أو تغيير إعدادات ثابتة

البدء كلي أو لا شيء. يحرر فشل مستمع لاحق المستمعين السابقين والتخصيصات قبل إعادة فشل قابل للاسترداد. تطبع جذور الخدمة الرمز المستقر دون سطر جديد وتعيد 1؛ استخدم مرجع الأخطاء الكامل للتمييز.

يطلب POST /stop التصريف والعودة العادية 0. يصرّف SIGINT أو Ctrl+C أو SIGTERM الأول وينهي بالحالة 7؛ تتجاوز الإشارة الثانية التصريف المتبقي. تبقى الفخاخ النهائية بالحالة 5 ولا تتحول تلقائيا إلى 500. قيمة الانتظار والإيقاظ 10 ms هدف استجابة وليست ضمان زمن حقيقي للمضيف. راجع الإغلاق والإلغاء.

الحدود المعيارية للإصدار

خدمة نص وJSON وبايتات مع حالة

تجهيز المضيف الأصلي

استمع على 127.0.0.1:8080 وشغّل العميل في نافذة أخرى. يقرأ /count الحالة ثم يزيدها. يصرّف POST /stop الخدمة. يحتاج /upstream أيضا server.pem ونظيرا موثقا على localhost:9443/hello.

اتبع دليل النشر للشهادات واختيار CA ومجلدات العمل ومسار الطرف العلوي الكامل.

اتبع دليل HTTP ومرجع الواجهة. احتفظ بأسماء الملفات ووحدات نسخة المصدر المختارة. احفظ النسختين العربية والإنجليزية في مجلدين منفصلين. يوفّر القارئ مدخلات TLS؛ لا شهادات أو مفاتيح مضمّنة. لا أصول بيانات أخرى.

المصدر العربي

المصدر الإنجليزي

الأوامر والنتائج

ar:

aspl check ar/service.لبات
aspl run ar/service.لبات
aspl build -o http-service-ar-program ar/service.لبات
./http-service-ar-program

en:

aspl check en/service.aspl
aspl run en/service.aspl
aspl build -o http-service-en-program en/service.aspl
./http-service-en-program

شغّل الأوامر من المجلد الأب لمجلدي ar/en المنفصلين. تبقى الخدمة في المقدمة حتى POST /stop ثم تنتهي بحالة 0 دون خرج. شغّل العميل المطابق منفصلا. تأتي تفاصيل النتائج المعروضة من الكتالوج. راجع مجموعة HTTP.

الحدود المعيارية للإصدار

فحص النص وJSON والبايتات و404

تجهيز المضيف الأصلي

شغّل الخدمة العادية المطابقة على 127.0.0.1:8080 أولا. ضع requests.لبات من نسخة المصدر نفسها بجوار الجذر.

اتبع دليل النشر للشهادات واختيار CA ومجلدات العمل ومسار الطرف العلوي الكامل.

اتبع دليل HTTP ومرجع الواجهة. احتفظ بأسماء الملفات ووحدات نسخة المصدر المختارة. احفظ النسختين العربية والإنجليزية في مجلدين منفصلين. يوفّر القارئ مدخلات TLS؛ لا شهادات أو مفاتيح مضمّنة. لا أصول بيانات أخرى.

المصدر العربي

المصدر الإنجليزي

الأوامر والنتائج

ar:

aspl check ar/client.aspl
aspl run ar/client.aspl
aspl build -o http-client-ar-program ar/client.aspl
./http-client-ar-program

en:

aspl check en/client.aspl
aspl run en/client.aspl
aspl build -o http-client-en-program en/client.aspl
./http-client-en-program

شغّل الأوامر من المجلد الأب لمجلدي ar/en المنفصلين. مع تشغيل الخدمة المطابقة يفحص العميل كل استجابة ويطبع خرج الكتالوج بلا سطر جديد أخير وينتهي بحالة 0. تأتي تفاصيل النتائج المعروضة من الكتالوج. راجع مجموعة HTTP.

الحدود المعيارية للإصدار

خدمة HTTPS محلية موثقة

تجهيز المضيف الأصلي

استمع على 127.0.0.1:8443. وفّر server.pem وserver.key المطابق غير المشفر في مجلد عمل العملية، مع localhost في DNS SAN للشهادة. شغّل عميل HTTPS منفصلا؛ يصرّف POST /stop الخدمة.

اتبع دليل النشر للشهادات واختيار CA ومجلدات العمل ومسار الطرف العلوي الكامل.

اتبع دليل HTTP ومرجع الواجهة. احتفظ بأسماء الملفات ووحدات نسخة المصدر المختارة. احفظ النسختين العربية والإنجليزية في مجلدين منفصلين. يوفّر القارئ مدخلات TLS؛ لا شهادات أو مفاتيح مضمّنة. لا أصول بيانات أخرى.

المصدر العربي

المصدر الإنجليزي

الأوامر والنتائج

ar:

aspl check ar/direct-tls.لبات
aspl run ar/direct-tls.لبات
aspl build -o http-direct-tls-ar-program ar/direct-tls.لبات
./http-direct-tls-ar-program

en:

aspl check en/direct-tls.لبات
aspl run en/direct-tls.لبات
aspl build -o http-direct-tls-en-program en/direct-tls.لبات
./http-direct-tls-en-program

شغّل الأوامر من المجلد الأب لمجلدي ar/en المنفصلين. تبقى خدمة TLS في المقدمة حتى POST /stop موثق ثم تنتهي بحالة 0 دون خرج. شغّل عميل HTTPS المطابق منفصلا. تأتي تفاصيل النتائج المعروضة من الكتالوج. راجع مجموعة HTTP.

الحدود المعيارية للإصدار

توثيق HTTPS عبر CA خاص صريح

تجهيز المضيف الأصلي

شغّل خدمة TLS المطابقة على https://localhost:8443. ضع server.pem الموثوق في مجلد عمل العميل. يحل CA الخاص محل ثقة النظام ولا يعطّل التحقق.

اتبع دليل النشر للشهادات واختيار CA ومجلدات العمل ومسار الطرف العلوي الكامل.

اتبع دليل HTTP ومرجع الواجهة. احتفظ بأسماء الملفات ووحدات نسخة المصدر المختارة. احفظ النسختين العربية والإنجليزية في مجلدين منفصلين. يوفّر القارئ مدخلات TLS؛ لا شهادات أو مفاتيح مضمّنة. لا أصول بيانات أخرى.

المصدر العربي

المصدر الإنجليزي

الأوامر والنتائج

ar:

aspl check ar/client-tls.لبات
aspl run ar/client-tls.لبات
aspl build -o http-client-tls-ar-program ar/client-tls.لبات
./http-client-tls-ar-program

en:

aspl check en/client-tls.لبات
aspl run en/client-tls.لبات
aspl build -o http-client-tls-en-program en/client-tls.لبات
./http-client-tls-en-program

شغّل الأوامر من المجلد الأب لمجلدي ar/en المنفصلين. مع تشغيل خدمة TLS المطابقة وتجهيز CA الخاص يفحص العميل كل استجابة ويطبع خرج الكتالوج بلا سطر جديد أخير وينتهي بحالة 0. تأتي تفاصيل النتائج المعروضة من الكتالوج. راجع مجموعة HTTP.

الحدود المعيارية للإصدار

استخدام ثقة TLS للنظام

تجهيز المضيف الأصلي

يحتاج نظيرا على https://localhost:9443/hello بشهادة يثق بها المضيف. تنتج الشهادة المحلية الخاصة غير الموثوقة http.tls_verify_failed وحالة 1. تنتج الثقة المفقودة أو التالفة http.ca_load_failed.

اتبع دليل النشر للشهادات واختيار CA ومجلدات العمل ومسار الطرف العلوي الكامل.

اتبع دليل HTTP ومرجع الواجهة. احتفظ بأسماء الملفات ووحدات نسخة المصدر المختارة. احفظ النسختين العربية والإنجليزية في مجلدين منفصلين. يوفّر القارئ مدخلات TLS؛ لا شهادات أو مفاتيح مضمّنة. لا أصول بيانات أخرى.

المصدر العربي

المصدر الإنجليزي

الأوامر والنتائج

ar:

aspl check ar/default-trust.aspl
aspl run ar/default-trust.aspl
aspl build -o http-default-trust-ar-program ar/default-trust.aspl
./http-default-trust-ar-program

en:

aspl check en/default-trust.aspl
aspl run en/default-trust.aspl
aspl build -o http-default-trust-en-program en/default-trust.aspl
./http-default-trust-en-program

شغّل الأوامر من المجلد الأب لمجلدي ar/en المنفصلين. مع نظير موثوق يطبع العميل المتن بلا سطر جديد أخير وينتهي بحالة 0. مع شهادة محلية غير موثوقة يطبع رمز الفشل المستقر ويعيد 1. تأتي تفاصيل النتائج المعروضة من الكتالوج. راجع مجموعة HTTP.

مع شهادة محلية غير موثوقة يكون الخرج http.tls_verify_failed وحالة العملية 1. يطبع النجاح مرحبا من ASPL ويعيد 0.

الحدود المعيارية للإصدار

معالجة رفض الاتصال كنتيجة

تجهيز المضيف الأصلي

يشترط عدم وجود مستمع على 127.0.0.1:9. يغيّر وجوده النتيجة المتوقعة. يستخدم الاختبار منفذا محليا مؤقتا مغلقا.

اتبع دليل النشر للشهادات واختيار CA ومجلدات العمل ومسار الطرف العلوي الكامل.

اتبع دليل HTTP ومرجع الواجهة. احتفظ بأسماء الملفات ووحدات نسخة المصدر المختارة. احفظ النسختين العربية والإنجليزية في مجلدين منفصلين. يوفّر القارئ مدخلات TLS؛ لا شهادات أو مفاتيح مضمّنة. لا أصول بيانات أخرى.

المصدر العربي

المصدر الإنجليزي

الأوامر والنتائج

ar:

aspl check ar/refusal.aspl
aspl run ar/refusal.aspl
aspl build -o http-refusal-ar-program ar/refusal.aspl
./http-refusal-ar-program

en:

aspl check en/refusal.aspl
aspl run en/refusal.aspl
aspl build -o http-refusal-en-program en/refusal.aspl
./http-refusal-en-program

شغّل الأوامر من المجلد الأب لمجلدي ar/en المنفصلين. مع إغلاق المنفذ المذكور يفحص البرنامج النتيجة الفاشلة ويطبع http.connect_failed بلا سطر جديد أخير ويعيد 0. لا يبدأ خدمة. تأتي تفاصيل النتائج المعروضة من الكتالوج. راجع مجموعة HTTP.

الحدود المعيارية للإصدار

تصحيح حدود اتصالات غير متوافقة

تجهيز المضيف الأصلي

لا نظير شبكة أو ملفات TLS. يعيد خفض الاتصالات الصادرة إلى 1 دون خفض فتحات الخمول الافتراضية 16 الرمز http.invalid_argument؛ ينجح ضبطهما على 1.

اتبع دليل النشر للشهادات واختيار CA ومجلدات العمل ومسار الطرف العلوي الكامل.

اتبع دليل HTTP ومرجع الواجهة. احتفظ بأسماء الملفات ووحدات نسخة المصدر المختارة. احفظ النسختين العربية والإنجليزية في مجلدين منفصلين. يوفّر القارئ مدخلات TLS؛ لا شهادات أو مفاتيح مضمّنة. لا أصول بيانات أخرى.

المصدر العربي

المصدر الإنجليزي

الأوامر والنتائج

ar:

aspl check ar/limits.aspl
aspl run ar/limits.aspl
aspl build -o http-limits-ar-program ar/limits.aspl
./http-limits-ar-program

en:

aspl check en/limits.aspl
aspl run en/limits.aspl
aspl build -o http-limits-en-program en/limits.aspl
./http-limits-en-program

شغّل الأوامر من المجلد الأب لمجلدي ar/en المنفصلين. يفحص البرنامج رفض الإعدادات غير المتوافقة وتصحيحها دون بدء الشبكة. لا خرج للنجاح وحالته 0. تأتي تفاصيل النتائج المعروضة من الكتالوج. راجع مجموعة HTTP.

الحدود المعيارية للإصدار

تقدم جلسة HTTP ونشرها وإغلاقها

تجهيز المضيف الأصلي

وفّر 127.0.0.1:8081. لا طلبات خارجية أو وحدات مصدر أو أصول TLS. ينسخ البرنامج الحالة وينشر 11 شرطيا ويرفض النشر القديم بنجاح ذي قيمة خطأ ثم يصرّف الجلسة ويغلق نسخها المشتركة.

اتبع دليل النشر للشهادات واختيار CA ومجلدات العمل ومسار الطرف العلوي الكامل.

اتبع دليل HTTP ومرجع الواجهة. احتفظ بأسماء الملفات ووحدات نسخة المصدر المختارة. احفظ النسختين العربية والإنجليزية في مجلدين منفصلين. يوفّر القارئ مدخلات TLS؛ لا شهادات أو مفاتيح مضمّنة. لا أصول بيانات أخرى.

المصدر العربي

المصدر الإنجليزي

الأوامر والنتائج

ar:

aspl check ar/session.aspl
aspl run ar/session.aspl
aspl build -o http-session-ar-program ar/session.aspl
./http-session-ar-program

en:

aspl check en/session.aspl
aspl run en/session.aspl
aspl build -o http-session-en-program en/session.aspl
./http-session-en-program

شغّل الأوامر من المجلد الأب لمجلدي ar/en المنفصلين. يفتح البرنامج مستمعه ويفحص الحالة المنسوخة والحالية والقديمة ثم يصرّفها عبر التقدم ويغلق تلقائيا. لا يحتاج طلبا خارجيا أو POST /stop. لا خرج للنجاح وحالته 0. تأتي تفاصيل النتائج المعروضة من الكتالوج. راجع مجموعة HTTP.

الحدود المعيارية للإصدار

فتح النافذة وإغلاقها وإعادة فتحها

تجهيز المضيف الأصلي

المضيف الأصلي فقط، ASPL 0.7.0 المنشور. اضغط إدخال مرتين في الطرفية التي تشغّل البرنامج. يتغير العنوان وتغلق النافذة الأولى ثم تفتح نافذة جديدة. يعيد النجاح 0.

التثبيت الأصلي · دليل الرسم والإدخال · مرجع الواجهة.

لا يحتاج إلى وحدات مصدر أو ملفات بيانات.

لغة الصفحة مستقلة عن مفردات المصدر. نزّل الصيغ الموردة فقط بأسمائها الأصلية. تحمل البرامج ذات الصيغة المختلطة وحدها هذا الوصف في اللغتين، دون توليد ترجمة للمصدر.

المصدر المختلط

الأوامر والنتائج

شغّل من المجلد الذي يحتوي شجرة docs/ المنزلة. احتفظ بالملف المرافق .THIRD-PARTY-NOTICES عند توزيع برنامج ELF. لا يفتح الفحص والبناء نافذة. يحتاج التشغيل إلى متطلبات الرسوم المذكورة.

mixed:

aspl check docs/examples/raylib-window.mixed.aspl
aspl run docs/examples/raylib-window.mixed.aspl
aspl build -o raylib-window-mixed-program docs/examples/raylib-window.mixed.aspl
./raylib-window-mixed-program

مجموعة Raylib.

النشر ومتطلبات المضيف.

الحدود المعيارية للإصدار

عرض الإطارات وإعادة ضبط التوقيت

تجهيز المضيف الأصلي

المضيف الأصلي فقط، ASPL 0.7.0 المنشور. يعرض كل جيل من جيلي النافذة 30 إطارا بهدف 60 FPS، ويتغير الأزرق السماوي إلى العنابي في المنتصف. يطبع كل جيل الزمن وزمن الإطار وFPS. تعتمد القيم العددية على المضيف. يعيد النجاح 0.

التثبيت الأصلي · دليل الرسم والإدخال · مرجع الواجهة.

لا يحتاج إلى وحدات مصدر أو ملفات بيانات.

لغة الصفحة مستقلة عن مفردات المصدر. نزّل الصيغ الموردة فقط بأسمائها الأصلية. تحمل البرامج ذات الصيغة المختلطة وحدها هذا الوصف في اللغتين، دون توليد ترجمة للمصدر.

المصدر المختلط

الأوامر والنتائج

شغّل من المجلد الذي يحتوي شجرة docs/ المنزلة. احتفظ بالملف المرافق .THIRD-PARTY-NOTICES عند توزيع برنامج ELF. لا يفتح الفحص والبناء نافذة. يحتاج التشغيل إلى متطلبات الرسوم المذكورة.

mixed:

aspl check docs/examples/raylib-frames.mixed.aspl
aspl run docs/examples/raylib-frames.mixed.aspl
aspl build -o raylib-frames-mixed-program docs/examples/raylib-frames.mixed.aspl
./raylib-frames-mixed-program

مجموعة Raylib.

النشر ومتطلبات المضيف.

الحدود المعيارية للإصدار

رسم الأشكال عبر كاميرا2

تجهيز المضيف الأصلي

المضيف الأصلي فقط، ASPL 0.7.0 المنشور. يعرض البرنامج حتى 20 إطارا فيها مستطيل مدور ودائرة وخط سميك ومثلث بإحداثيات الكاميرا. تستخدم نقطة وإطار حدود إحداثيات الشاشة بعد EndMode2D. يطبع النجاح camera shapes complete دون سطر جديد ويعيد 0.

التثبيت الأصلي · دليل الرسم والإدخال · مرجع الواجهة.

لا يحتاج إلى وحدات مصدر أو ملفات بيانات.

لغة الصفحة مستقلة عن مفردات المصدر. نزّل الصيغ الموردة فقط بأسمائها الأصلية. تحمل البرامج ذات الصيغة المختلطة وحدها هذا الوصف في اللغتين، دون توليد ترجمة للمصدر.

المصدر المختلط

الأوامر والنتائج

شغّل من المجلد الذي يحتوي شجرة docs/ المنزلة. احتفظ بالملف المرافق .THIRD-PARTY-NOTICES عند توزيع برنامج ELF. لا يفتح الفحص والبناء نافذة. يحتاج التشغيل إلى متطلبات الرسوم المذكورة.

mixed:

aspl check docs/examples/raylib-shapes.mixed.aspl
aspl run docs/examples/raylib-shapes.mixed.aspl
aspl build -o raylib-shapes-mixed-program docs/examples/raylib-shapes.mixed.aspl
./raylib-shapes-mixed-program

مجموعة Raylib.

النشر ومتطلبات المضيف.

الحدود المعيارية للإصدار

قراءة لوحة المفاتيح والفأرة وتغيير الحجم

تجهيز المضيف الأصلي

المضيف الأصلي فقط، ASPL 0.7.0 المنشور. يختار النقر الأيسر أو التمرير اللون العنابي. يختاره مفتاح المسافة أيضا، لكن يتقدم المحرف المنتظر في الطابور، بما فيه المسافة المكتوبة، ويختار الأخضر الداكن. يطبع كل محرف مستهلك رقم قيمة Unicode له. يطبع الإطار الأول وتغيير الحجم أبعاد الشاشة المنطقية والتصيير الفيزيائية. ينتهي التكرار بمفتاح الهروب أو بعد 180 إطارا بحالة 0. يعتمد الإخراج على المضيف والإدخال.

التثبيت الأصلي · دليل الرسم والإدخال · مرجع الواجهة.

لا يحتاج إلى وحدات مصدر أو ملفات بيانات.

لغة الصفحة مستقلة عن مفردات المصدر. نزّل الصيغ الموردة فقط بأسمائها الأصلية. تحمل البرامج ذات الصيغة المختلطة وحدها هذا الوصف في اللغتين، دون توليد ترجمة للمصدر.

المصدر العربي

المصدر الإنجليزي

المصدر المختلط

الأوامر والنتائج

شغّل من المجلد الذي يحتوي شجرة docs/ المنزلة. احتفظ بالملف المرافق .THIRD-PARTY-NOTICES عند توزيع برنامج ELF. لا يفتح الفحص والبناء نافذة. يحتاج التشغيل إلى متطلبات الرسوم المذكورة.

ar:

aspl check docs/examples/raylib/window-input.ar.aspl
aspl run docs/examples/raylib/window-input.ar.aspl
aspl build -o raylib-window-input-ar-program docs/examples/raylib/window-input.ar.aspl
./raylib-window-input-ar-program

en:

aspl check docs/examples/raylib/window-input.en.aspl
aspl run docs/examples/raylib/window-input.en.aspl
aspl build -o raylib-window-input-en-program docs/examples/raylib/window-input.en.aspl
./raylib-window-input-en-program

mixed:

aspl check docs/examples/raylib/window-input.mixed.aspl
aspl run docs/examples/raylib/window-input.mixed.aspl
aspl build -o raylib-window-input-mixed-program docs/examples/raylib/window-input.mixed.aspl
./raylib-window-input-mixed-program

مجموعة Raylib.

النشر ومتطلبات المضيف.

الحدود المعيارية للإصدار

رسم الصور وتحويل الكاميرا وفحص التصادم

تجهيز المضيف الأصلي

المضيف الأصلي فقط، ASPL 0.7.0 المنشور. تعرض 20 إطارا صور الأطلس الملونة والمدورة والمنعكسة مع تقاطع مستطيل أحمر. يحرر الإطار الأخير نسخة المالك قبل العرض ويتحقق من بطلان الأصل. يطبع النجاح texture sprites complete دون سطر جديد ويعيد 0.

التثبيت الأصلي · دليل الرسم والإدخال · مرجع الواجهة.

نزّل PNG وإشعاره المرخص تحت Apache-2.0 OR MIT. احتفظ بالمسار docs/examples/assets/raylib-sprites.png نسبة إلى مجلد عمل العملية، حتى عند نقل البرنامج الناتج. يتكون الأطلس من 32 في 16 بكسل RGBA.

لغة الصفحة مستقلة عن مفردات المصدر. نزّل الصيغ الموردة فقط بأسمائها الأصلية. تحمل البرامج ذات الصيغة المختلطة وحدها هذا الوصف في اللغتين، دون توليد ترجمة للمصدر.

المصدر العربي

المصدر الإنجليزي

المصدر المختلط

الأوامر والنتائج

شغّل من المجلد الذي يحتوي شجرة docs/ المنزلة. احتفظ بالملف المرافق .THIRD-PARTY-NOTICES عند توزيع برنامج ELF. لا يفتح الفحص والبناء نافذة. يحتاج التشغيل إلى متطلبات الرسوم المذكورة.

ar:

aspl check docs/examples/raylib/sprite-camera.ar.aspl
aspl run docs/examples/raylib/sprite-camera.ar.aspl
aspl build -o raylib-sprite-camera-ar-program docs/examples/raylib/sprite-camera.ar.aspl
./raylib-sprite-camera-ar-program

en:

aspl check docs/examples/raylib/sprite-camera.en.aspl
aspl run docs/examples/raylib/sprite-camera.en.aspl
aspl build -o raylib-sprite-camera-en-program docs/examples/raylib/sprite-camera.en.aspl
./raylib-sprite-camera-en-program

mixed:

aspl check docs/examples/raylib/sprite-camera.mixed.aspl
aspl run docs/examples/raylib/sprite-camera.mixed.aspl
aspl build -o raylib-sprite-camera-mixed-program docs/examples/raylib/sprite-camera.mixed.aspl
./raylib-sprite-camera-mixed-program

مجموعة Raylib.

النشر ومتطلبات المضيف.

الحدود المعيارية للإصدار

قياس النص المشكل ورسمه مع الموسيقى

تجهيز المضيف الأصلي

المضيف الأصلي فقط، ASPL 0.7.0 المنشور.

دليل Raylib · الواجهة · التثبيت · النشر.

ASPL 0.7.0 أصلي على Linux بمعمارية x86_64 وglibc 2.34 أو أحدث.

يحتاج التشغيل إلى شاشة Wayland/EGL أو X11/GLX متاحة وOpenGL 3.3 core. لا يحتاج الفحص والبناء إلى أجهزة أو مترجم C أو Raylib نظامي.

خدمة تشغيل PulseAudio أو PipeWire متوافقة أو جهاز ALSA مباشر متاح. لا تحتاج الخطوط الافتراضية المرخصة المضمنة إلى تنزيل خط.

احفظ docs/examples/assets/raylib-tone.ogg وإشعار CC0 المسمى raylib-tone.NOTICE نسبة إلى مجلد عمل العملية.

لغة الصفحة ومفردات المصدر مستقلتان. احفظ أسماء الملفات الأصلية، ولا يولد مصدر مستخدم مترجم. يعرض كل لوح مصدر سلوكه المتوقع المفحوص.

المصدر العربي

المصدر الإنجليزي

المصدر المختلط

الأوامر والنتائج

لا يحصل الفحص والبناء على جهاز. شغل من المجلد الذي يحتوي شجرة docs/ المجهزة. احتفظ بمرافق .THIRD-PARTY-NOTICES عند توزيع ELF.

ar:

aspl check docs/examples/raylib/shaped-text-audio.ar.aspl
aspl run docs/examples/raylib/shaped-text-audio.ar.aspl
aspl build -o raylib-shaped-text-audio-ar-program docs/examples/raylib/shaped-text-audio.ar.aspl
./raylib-shaped-text-audio-ar-program

en:

aspl check docs/examples/raylib/shaped-text-audio.en.aspl
aspl run docs/examples/raylib/shaped-text-audio.en.aspl
aspl build -o raylib-shaped-text-audio-en-program docs/examples/raylib/shaped-text-audio.en.aspl
./raylib-shaped-text-audio-en-program

mixed:

aspl check docs/examples/raylib/shaped-text-audio.mixed.aspl
aspl run docs/examples/raylib/shaped-text-audio.mixed.aspl
aspl build -o raylib-shaped-text-audio-mixed-program docs/examples/raylib/shaped-text-audio.mixed.aspl
./raylib-shaped-text-audio-mixed-program

تطبع تهيئة الصوت الفاشلة رسالتها الثنائية وتعيد 4. إذا نجح الصوت وغابت الشاشة يطبع فشل النافذة وتكون الحالة 7. يطبع غياب OGG فشل التحميل ويعيد 5. يعيد الإغلاق المبكر 0 عبر التنظيف التلقائي.

مجموعة Raylib.

الحدود المعيارية للإصدار

استمرار الرسم مع تقاسم معالجات HTTP الأدوار

تجهيز المضيف الأصلي

المضيف الأصلي فقط، ASPL 0.7.0 المنشور.

دليل Raylib · الواجهة · التثبيت · النشر.

ASPL 0.7.0 أصلي على Linux بمعمارية x86_64 وglibc 2.34 أو أحدث.

يحتاج التشغيل إلى شاشة Wayland/EGL أو X11/GLX متاحة وOpenGL 3.3 core. لا يحتاج الفحص والبناء إلى أجهزة أو مترجم C أو Raylib نظامي.

منفذا اتصال محلي 8000 و8001 غير مشغولين. شغل الطرف العلوي على 127.0.0.1:8001 قبل البرنامج واطلب /busy و/wait و/fast بالتزامن وبسرعة من المنفذ 8000. يجعل تأخير الطرف العلوي تقادم اللقطة قابلا للتكرار. لا تلزم وحدات مصدر أو أصول ملفات.

شغل الطرف العلوي المجهز محليا في طرفية أخرى. Python 3 وcurl أداتا تجهيز وليستا اعتمادين لتشغيل ASPL. يؤخر الردود 200 ms ولا يحتاج إلى ملف مساعد عام.

python3 - <<'UPSTREAM'
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import time
class Upstream(BaseHTTPRequestHandler):
    def do_GET(self):
        time.sleep(0.2)
        self.send_response(200)
        self.send_header("Content-Length", "4")
        self.end_headers()
        self.wfile.write(b"done")
ThreadingHTTPServer(("127.0.0.1", 8001), Upstream).serve_forever()
UPSTREAM

بعد ظهور ready نفذ هؤلاء العملاء المستقلين بسرعة من طرفية أخرى. يبقى /busy دون انتهاء حتى إغلاق الجلسة الفوري. يطبع العميلان الآخران conflict وfast بحالة 200. يعيد فشل الطرف العلوي /wait بحالة 502 ورمز خطأ HTTP.

curl --max-time 6 -i http://127.0.0.1:8000/busy &
curl --max-time 6 -i http://127.0.0.1:8000/wait &
curl --max-time 6 -i http://127.0.0.1:8000/fast &
wait

لغة الصفحة ومفردات المصدر مستقلتان. احفظ أسماء الملفات الأصلية، ولا يولد مصدر مستخدم مترجم. يعرض كل لوح مصدر سلوكه المتوقع المفحوص.

المصدر العربي

المصدر الإنجليزي

المصدر المختلط

الأوامر والنتائج

لا يحصل الفحص والبناء على جهاز. شغل من المجلد الذي يحتوي شجرة docs/ المجهزة. احتفظ بمرافق .THIRD-PARTY-NOTICES عند توزيع ELF.

ar:

aspl check docs/examples/raylib/concurrent-http.ar.aspl
aspl run docs/examples/raylib/concurrent-http.ar.aspl
aspl build -o raylib-concurrent-http-ar-program docs/examples/raylib/concurrent-http.ar.aspl
./raylib-concurrent-http-ar-program

en:

aspl check docs/examples/raylib/concurrent-http.en.aspl
aspl run docs/examples/raylib/concurrent-http.en.aspl
aspl build -o raylib-concurrent-http-en-program docs/examples/raylib/concurrent-http.en.aspl
./raylib-concurrent-http-en-program

mixed:

aspl check docs/examples/raylib/concurrent-http.mixed.aspl
aspl run docs/examples/raylib/concurrent-http.mixed.aspl
aspl build -o raylib-concurrent-http-mixed-program docs/examples/raylib/concurrent-http.mixed.aspl
./raylib-concurrent-http-mixed-program

تطبع الشاشة الغائبة raylib.host_unavailable ويعيد البرنامج 1 قبل بدء المستمع. يطبع منفذ المستمع المشغول خطأ بدء HTTP ويعيد 2. يعيد النجاح دون عملاء 0 ويطبع ready فقط.

مجموعة Raylib.

الحدود المعيارية للإصدار

فحص الأسماء المكافئة والهوية والبايتات النصية

تجهيز المضيف الأصلي

المضيف الأصلي فقط، ASPL 0.7.0 المنشور.

دليل Raylib · الواجهة · التثبيت · النشر.

ASPL 0.7.0 أصلي على Linux بمعمارية x86_64 وglibc 2.34 أو أحدث.

لا تلزم شاشة أو جهاز صوت أو طرف علوي أو أصول ملفات أو وحدات مصدر. يستخدم القياس المشكل الخطوط المرخصة المضمنة، ويستخدم استدعاء abs غير الآمن libc.so.6 الأساسي.

لغة الصفحة ومفردات المصدر مستقلتان. احفظ أسماء الملفات الأصلية، ولا يولد مصدر مستخدم مترجم. يعرض كل لوح مصدر سلوكه المتوقع المفحوص.

المصدر العربي

المصدر الإنجليزي

المصدر المختلط

الأوامر والنتائج

لا يحصل الفحص والبناء على جهاز. شغل من المجلد الذي يحتوي شجرة docs/ المجهزة. احتفظ بمرافق .THIRD-PARTY-NOTICES عند توزيع ELF.

ar:

aspl check docs/examples/raylib/identity-literals.ar.aspl
aspl run docs/examples/raylib/identity-literals.ar.aspl
aspl build -o raylib-identity-literals-ar-program docs/examples/raylib/identity-literals.ar.aspl
./raylib-identity-literals-ar-program

en:

aspl check docs/examples/raylib/identity-literals.en.aspl
aspl run docs/examples/raylib/identity-literals.en.aspl
aspl build -o raylib-identity-literals-en-program docs/examples/raylib/identity-literals.en.aspl
./raylib-identity-literals-en-program

mixed:

aspl check docs/examples/raylib/identity-literals.mixed.aspl
aspl run docs/examples/raylib/identity-literals.mixed.aspl
aspl build -o raylib-identity-literals-mixed-program docs/examples/raylib/identity-literals.mixed.aspl
./raylib-identity-literals-mixed-program

مجموعة Raylib.

الحدود المعيارية للإصدار

إدخال النص

ما ستتعلمه

اطبع سؤالا، واقرأ اسما دون تغيير نصه، وتوقع الرد الفارغ. ميز انتظار الإدخال ونفاده وإلغاء التنفيذ بوصفها نتائج منفصلة.

قبل أن تبدأ

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

اسأل عن الاسم

تكتب print / اطبع السؤال Name: ، بما فيه المسافة الأخيرة. لا تضيف سطرا جديدا. لا تأخذ read_line() / اقرأ_سطر() معاملات، وترجع string / نص. لا تطبع سؤالا بنفسها. ينتظر الاستدعاء حتى ترسل سطرا، ثم يحذف نهاية السطر ويحفظ سائر المحارف. تربط let name النص المرجع باسم غير قابل للتغيير.

يجمع العامل النصي + بين "Hello, " وname و"!\n" بهذا الترتيب. تنهي \n الصريحة سطر التحية. أرسل سلمى ليكون خرج البرنامج بالضبط Name: Hello, سلمى!\n. صدى الإدخال منفصل عن خرج البرنامج. تنتهي دالة الدخول المحجوزة start_main() -> i64 / ابدأ_الرئيسية() -> ص64 بـ return 0 / أرجع 0، وهي حالة عملية طبيعية وليست نصا مطبوعا.

اكتب الرد في حقل إدخال البرنامج الجاري، لا في محرر المصدر. لا يحتاج إلى علامات اقتباس. يحتفظ الاسم بالمسافات والنص العربي كما أدخلتها. إدخال وقت التشغيل ليس كتابة مصدر. تحويل الأرقام في محرر المصدر خارج النصوص والتعليقات لا يحول إدخال وقت التشغيل. تغيير لغة القراءة أو مفردات المصدر المقدمة لا يترجم السؤال أو ردك أو مسودة موجودة.

توقع الرد الفارغ

شغل البرنامج واختر إرسال السطر والحقل فارغ. ما النص الذي يحمله name؟ إنه السلسلة الفارغة ""، ولذلك يكون الخرج بالضبط Name: Hello, !\n وحالة العملية الطبيعية 0. السطر الفارغ المرسل يظل سطرا، ويختلف عن إغلاق الإدخال. أما إرسال سلمى فينتج Name: Hello, سلمى !\n. لا يحذف البرنامج المسافات.

الانتظار وإغلاق الإدخال والإيقاف

ابدأ تشغيلا صريحا جديدا لكل تجربة.

  1. اترك حقل الإدخال دون إرسال. يبقى السؤال ظاهرا وينتظر التنفيذ عند read_line. لم ينته البرنامج وليس له حالة عملية بعد. أرسل سطرا للمتابعة.
  2. شغل مرة أخرى، واكتب unsent في الحقل، ثم اختر إغلاق الإدخال دون إرسال السطر. يوفر إغلاق الإدخال نهاية الإدخال EOF ولا يرسل المحارف غير المرسلة. تتوقف القراءة المنتظرة بمصيدة input-exhausted. يبقى الخرج بالضبط Name: . لا تظهر تحية ولا عودة طبيعية من دالة الدخول. القراءة بعد نفاد الإدخال مصيدة لا يمكن التقاطها، وليست نتيجة قابلة للاسترداد أو سلسلة فارغة.
  3. شغل مرة أخرى واختر إيقاف أثناء الانتظار. يلغى التنفيذ ويبقى السؤال ظاهرا. الإلغاء منفصل عن EOF والإكمال الطبيعي، ولا يرجع الحالة 0.

يعرض المتصفح المصيدة والإلغاء في نتيجة التنفيذ، منفصلين عن الخرج. راجع إدخال المتصفح للأزرار وإدخال السطر للعقد الكامل.

غير التحية

غير Hello, فقط إلى Welcome, . أرسل سلمى. الخرج المتوقع بالضبط Name: Welcome, سلمى!\n وحالة العملية الطبيعية 0؛ والرد الفارغ ينتج Name: Welcome, !\n.

غير التحية إلى Welcome, مع حفظ الاسم كما أدخلته. توقع خرج السطر الفارغ أيضا.

تلميح: غير النص الأول في تعبير التحية. احتفظ بالسؤال واستدعاء read_line والاسم ونهاية السطر.

اعرض الإجابة المشروحة

تتغير بداية التحية فقط. تظل read_line ترجع الاسم المرسل دون تغيير، ويجمعه + بين البداية الجديدة والنهاية. مع سلمى يكون الخرج Name: Welcome, سلمى! ثم سطر جديد. مع السطر الفارغ لا يضيف الاسم محارف، فيبقى Name: Welcome, ! ثم سطر جديد. ترجع الحالتان اللتان أرسلتا سطرا الحالة 0.

تحقق من فهمك

اشرح أي استدعاء يطبع السؤال، وما الذي تحذفه القراءة، ولماذا ينجح السطر الفارغ المرسل بينما يسبب EOF مصيدة. قارن الانتظار وإغلاق الإدخال والإيقاف في تشغيلات منفصلة. لا تحفظ درجة أو تقدما، ويبقى التنقل مفتوحا. عد إلى مسار الدروس.

lesson-input-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    اطبع("Name: ").
    دع name: نص = اقرأ_سطر().
    اطبع("Hello, " + name + "!\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Name: Hello, سلمى!\n"
native: check 0; success / status 0; stdout "Name: Hello, سلمى!\n"
scripted stdin lines: ["سلمى"]
نزّل المصدر افتح في المحرر
aspl check lesson-input-ar.aspl
aspl run lesson-input-ar.aspl
lesson-input-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    print("Name: ");
    let name: string = read_line();
    print("Hello, " + name + "!\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Name: Hello, سلمى!\n"
native: check 0; success / status 0; stdout "Name: Hello, سلمى!\n"
scripted stdin lines: ["سلمى"]
نزّل المصدر افتح في المحرر
aspl check lesson-input-en.aspl
aspl run lesson-input-en.aspl
lesson-input-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    اطبع("Name: ").
    دع name: نص = اقرأ_سطر().
    اطبع("Welcome, " + name + "!\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Name: Welcome, سلمى!\n"
native: check 0; success / status 0; stdout "Name: Welcome, سلمى!\n"
scripted stdin lines: ["سلمى"]
نزّل المصدر افتح في المحرر
aspl check lesson-input-solution-ar.aspl
aspl run lesson-input-solution-ar.aspl
lesson-input-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    print("Name: ");
    let name: string = read_line();
    print("Welcome, " + name + "!\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Name: Welcome, سلمى!\n"
native: check 0; success / status 0; stdout "Name: Welcome, سلمى!\n"
scripted stdin lines: ["سلمى"]
نزّل المصدر افتح في المحرر
aspl check lesson-input-solution-en.aspl
aspl run lesson-input-solution-en.aspl
الحدود المعيارية للإصدار

تحليل الأعداد

ما ستتعلمه

حلل نصا صحيحا بقواعد صارمة، واقرأ فرع النتيجة المناسب، وأعد المحاولة بعد إدخال غير صالح. اشرح لماذا يفشل 12x بينما يطبع الرد التالي 41 العدد 42.

قبل أن تبدأ

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

نتيجة وحلقة إعادة المحاولة

تأخذ parse_i64 / حلل_ص64 سلسلة نصية وترجع result<i64> / نتيجة<ص64>. تحمل النتيجة إما قيمة عدد صحيح أو معلومات خطأ. تسمي الأقواس الزاوية نوع قيمة النجاح. تربط let parsed نتيجة جديدة في كل دورة. تظل read_line / اقرأ_سطر ترجع نصا؛ لا تحوله إلى عدد.

تبدأ var pending: bool = true / متغير pending: منطقي = صواب بعلامة منطقية قابلة للتغيير. تكرر while / طالما ما دامت العلامة صحيحة. تطبع كل دورة Number: وتقرأ سطرا واحدا. يصل العامل اللاحق :: إلى حقل في النتيجة. تمثل parsed::ok / parsed::نجاح اختبار النجاح المنطقي الذي تستخدمه if / إذا.

يقرأ فرع النجاح وحده parsed::value / parsed::قيمة، ويضيف 1، وينسق العدد الصحيح باستخدام format_i64 / نسق_ص64، ويطبعه مع \n صريحة. ثم يضع pending = false / pending = خطأ، فينهي الاختبار التالي الحلقة. يقرأ فرع الفشل else / وإلا وحده parsed::error::code / parsed::الخطأ::الرمز. يطبع الرمز المستقر وسطره الجديد، ويترك pending صحيحة لقراءة رد آخر.

لا تقرأ value عند الفشل أو error عند النجاح. تؤدي قراءة أي قيمة من الفرع الخطأ في المتصفح إلى مصيدة wrong-result-branch تنهي التنفيذ. في ASPL 0.7.0 الأصلي خلل تشخيص عند تعمد الوصول إلى الفرع الخطأ بأسماء حقول النتيجة العربية؛ تنتهي أداة سطر الأوامر بالحالة 8 دون تشخيص بدلا من عرض المصيدة. هذا ليس فشل تحليل عولج. يتجنب القالب الوصول الخطأ باختبار ok أولا. فشل التحليل نتيجة قابلة للاسترداد؛ لا ينتج تشخيصا وقت التشغيل ويسمح بإعادة المحاولة. تظل القراءة عند EOF تسبب مصيدة input-exhausted، ويظل الإيقاف يلغي التنفيذ. لا يتحول أي منهما إلى فشل تحليل.

ترجع دالة الدخول المحجوزة start_main() -> i64 / ابدأ_الرئيسية() -> ص64 القيمة 0 بعد الحلقة. حالة العملية الطبيعية منفصلة عن الجواب ورمز الخطأ المطبوعين.

توقع ردين

قبل التشغيل توقع خرج 12x ثم 41. بعد الرد الأول يكون الخرج Number: invalid-number\nNumber: وينتظر التنفيذ من جديد. يجعل الحرف السلسلة الأولى كلها غير صالحة؛ لا يقبل المحلل بداية عددية ويهمل الباقي. يوفر الرد الثاني العدد الصحيح 41، فيصبح الخرج بالضبط Number: invalid-number\nNumber: 42\n وحالة العملية 0. تقرأ الدورة الثانية وحدها القيمة العددية. لا تحدث قراءة ثالثة.

ما النص العددي المقبول؟

استخدم إشارة ASCII اختيارية + أو - تتبعها خانة عشرية واحدة أو أكثر من ASCII، من 0 إلى 9. تقبل الأصفار البادئة. يجب أن تقع القيمة في مجال i64 من -9223372036854775808 إلى 9223372036854775807، شاملا الحدين.

النص المرسل نتيجة التحليل
41 و+41 و041 و-1 نجاح بالقيم 41 و41 و41 و-1
سطر فارغ invalid-number
41 أو 41 أو سطر من المسافات فقط invalid-number
12x و1.5 و0x29 و+ و- invalid-number
الأرقام العربية الهندية ١٢ أو العربية الهندية الممتدة ۱۲ invalid-number
9223372036854775808 أو -9223372036854775809 number-out-of-range

لا يحذف المحلل المسافات ولا يحول الأرقام إلى صيغة أخرى. نص الأعداد وقت التشغيل منفصل عن كتابة المصدر وعن تحويل أرقام محرر المصدر خارج النصوص والتعليقات. احفظ النص المرسل دون تغيير في هذا الدرس. لا يترجم تغيير لغة القراءة أو مفردات المصدر الإدخال أو مسودة موجودة.

للتحليل والحساب فحوص حدود منفصلة. ينجح تحليل حدي i64، لكن إضافة 1 إلى الحد الأعلى تسبب مصيدة integer-overflow. استخدم المدخلات الصغيرة للتدرب على برنامج إعادة المحاولة. راجع النص العددي لقواعد التحويل الكاملة.

أضف اثنين بدلا من واحد

غير الجمع في فرع النجاح فقط من + 1 إلى + 2. أرسل 12x ثم 41. الخرج المتوقع بالضبط Number: invalid-number\nNumber: 43\n وحالة العملية 0. يظل الفشل الأول يعيد المحاولة ولا يقرأ القيمة العددية أبدا.

احتفظ بقالب إعادة المحاولة وأضف 2 إلى العدد الصحيح الناجح بدلا من 1. توقع الردين.

تلميح: غير العدد بعد + في فرع النجاح فقط. احتفظ باختبار ok وفرع الفشل وقيمتي العلامة.

اعرض الإجابة المشروحة

يظل الرد الأول 12x يرجع invalid-number. يطبع فرع الفشل رمز الخطأ ويترك pending صحيحة، فتسأل الحلقة من جديد. ينجح الرد 41؛ يقرأ هذا الفرع وحده value ويحسب 41 + 2 = 43. ينتج التنسيق النص 43، وتنهي نهاية السطر الصريحة السطر، وتصبح pending خطأ. ترجع دالة الدخول الحالة 0 دون قراءة أخرى.

تحقق من فهمك

اشرح لماذا يستطيع فرع الفشل المتابعة دون استخدام القيمة العددية. توقع نتيجة الرد الفارغ والمسافات المحيطة والأرقام غير ASCII قبل تجربتها. اشرح اختلاف النص الخارج عن المجال عن النص المخالف للقواعد. لا تحفظ درجة أو تقدما، ويبقى التنقل مفتوحا. عد إلى مسار الدروس أو اقرأ مرجع النتائج.

lesson-numeric-parsing-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    متغير pending: منطقي = صواب.
    طالما pending {
        اطبع("Number: ").
        دع parsed: نتيجة<ص64> = حلل_ص64(اقرأ_سطر()).
        إذا (parsed::نجاح) {
            اطبع(نسق_ص64(parsed::قيمة + 1) + "\n").
            pending = خطأ.
        } وإلا {
            اطبع(parsed::الخطأ::الرمز + "\n").
        }
    }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Number: invalid-number\nNumber: 42\n"
native: check 0; success / status 0; stdout "Number: invalid-number\nNumber: 42\n"
scripted stdin lines: ["12x","41"]
نزّل المصدر افتح في المحرر
aspl check lesson-numeric-parsing-ar.aspl
aspl run lesson-numeric-parsing-ar.aspl
lesson-numeric-parsing-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    var pending: bool = true;
    while pending {
        print("Number: ");
        let parsed: result<i64> = parse_i64(read_line());
        if (parsed::ok) {
            print(format_i64(parsed::value + 1) + "\n");
            pending = false;
        } else {
            print(parsed::error::code + "\n");
        }
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Number: invalid-number\nNumber: 42\n"
native: check 0; success / status 0; stdout "Number: invalid-number\nNumber: 42\n"
scripted stdin lines: ["12x","41"]
نزّل المصدر افتح في المحرر
aspl check lesson-numeric-parsing-en.aspl
aspl run lesson-numeric-parsing-en.aspl
lesson-numeric-parsing-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    متغير pending: منطقي = صواب.
    طالما pending {
        اطبع("Number: ").
        دع parsed: نتيجة<ص64> = حلل_ص64(اقرأ_سطر()).
        إذا (parsed::نجاح) {
            اطبع(نسق_ص64(parsed::قيمة + 2) + "\n").
            pending = خطأ.
        } وإلا {
            اطبع(parsed::الخطأ::الرمز + "\n").
        }
    }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Number: invalid-number\nNumber: 43\n"
native: check 0; success / status 0; stdout "Number: invalid-number\nNumber: 43\n"
scripted stdin lines: ["12x","41"]
نزّل المصدر افتح في المحرر
aspl check lesson-numeric-parsing-solution-ar.aspl
aspl run lesson-numeric-parsing-solution-ar.aspl
lesson-numeric-parsing-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    var pending: bool = true;
    while pending {
        print("Number: ");
        let parsed: result<i64> = parse_i64(read_line());
        if (parsed::ok) {
            print(format_i64(parsed::value + 2) + "\n");
            pending = false;
        } else {
            print(parsed::error::code + "\n");
        }
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Number: invalid-number\nNumber: 43\n"
native: check 0; success / status 0; stdout "Number: invalid-number\nNumber: 43\n"
scripted stdin lines: ["12x","41"]
نزّل المصدر افتح في المحرر
aspl check lesson-numeric-parsing-solution-en.aspl
aspl run lesson-numeric-parsing-solution-en.aspl
الحدود المعيارية للإصدار

السلاسل النصية

ما ستتعلمه

اجمع تحية واسما مرسلا، وأضف عددا صحيحا بتنسيق صريح، وتوقع طول سلسلة عربية قصيرة ومقطعا منها باستخدام مواضع قيم يونيكود العددية.

قبل أن تبدأ

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

اجمع النص ونسق العدد

string / نص نص ثابت مخزن بترميز UTF-8. تربط let / دع الاسم المرسل name والعدد الصحيح next والسلسلة greeting. تكتب print / اطبع السؤال Name: قبل أن تقرأ read_line / اقرأ_سطر الرد دون نهاية سطره. يجمع العامل النصي + النصوص بالترتيب المكتوب؛ ويحفظ المسافات ولا يترجم المحتوى أو يغير تطبيعه.

41 + 1 حساب أعداد صحيحة يعطي next القيمة 42. تحول format_i64(next) / نسق_ص64(next) هذا العدد صراحة إلى سلسلة ASCII هي "42". يجمع تعبير التحية سلاسل نصية. لا يمكن جمع سلسلة مباشرة مع عدد صحيح؛ احتفظ باستدعاء التنسيق. يحتاج كل print إلى \n الصريحة لإنهاء سطره.

تستخدم الطباعة في السطرين الأخيرين length / طول وslice / اقتطع. يرجع الطول عدد القيم العددية بنوع i64، ولذلك يحتاج أيضا إلى تنسيق للخرج. يأخذ الاقتطاع النص وموضع بداية مشمولا وموضع نهاية مستبعدا، ويرجع سلسلة نصية. تنتهي دالة الدخول المحجوزة start_main() -> i64 / ابدأ_الرئيسية() -> ص64 بـ return 0 / أرجع 0، منفصلا عن البيانات المطبوعة.

توقع طول النص العربي ومقطعه

قبل التشغيل توقع length("مرحبا") وslice("مرحبا", 1, 3). تبدأ المواضع من الصفر وتعد قيم يونيكود العددية، لا بايتات UTF-8 أو مواضع الشاشة. اقرأ الترتيب المنطقي المخزن أدناه حتى إن عرض المصدر باتجاه آخر.

موضع القيمة العددية القيمة المخزنة
0 م
1 ر
2 ح
3 ب
4 ا

الطول 5. يشمل المقطع الموضعين 1 و2 ويتوقف قبل 3، ولذلك يكون "رح". تشغل القيم العربية الخمس 10 بايتات UTF-8، لكن معاملات الاقتطاع مواضع قيم عددية. تعد علامة التشكيل منفصلة؛ وقد يتكون محرف ظاهر أو تسلسل رموز تعبيرية من عدة قيم عددية. لا يحتوي هذا المثال على علامات تشكيل.

أرسل سلمى. الخرج الدقيق Name: Hello, سلمى! Next: 42\n5\nرح\n وحالة العملية الطبيعية 0. يترك الرد الفارغ الاسم فارغا بينما يبقى العدد والطول والمقطع كما هي. لا يترجم تغيير لغة التوثيق أو مفردات المصدر المقدمة "مرحبا" أو التحية أو إدخال وقت التشغيل أو الأسماء أو مسودة موجودة.

أضف قيمة عددية أخرى إلى المقطع

غير نهاية المقطع فقط من 3 إلى 4. توقع أي قيمة تضاف. مع الاسم نفسه يكون الخرج المتوقع بالضبط Name: Hello, سلمى! Next: 42\n5\nرحب\n وحالة العملية 0.

احتفظ بالتحية والطول. غير نهاية المقطع المستبعدة إلى 4 وتوقع السطر الأخير الجديد.

تلميح: احتفظ بالبداية عند 1. موضع النهاية مستبعد، ولذلك تشمل النهاية 4 المواضع 1 و2 و3.

اعرض الإجابة المشروحة

يحفظ المقطع الآن ر وح وب في مواضع القيم العددية 1 و2 و3. يتوقف قبل ا في الموضع 4، فينتج رحب. تظل التحية دون تغيير وتنسق العدد الصحيح 42 صراحة، ويظل الطول يطبع 5. ينتهي كل سطر خرج بنهاية سطره الصريحة. ترجع دالة الدخول الحالة الطبيعية 0.

تحقق من فهمك

اشرح الفرق بين + للأعداد الصحيحة و+ للنصوص، ولماذا التنسيق صريح، ولماذا نهاية المقطع مستبعدة. تحقق المقاطع الصالحة 0 <= start <= end <= length(text). يسبب المقطع غير الصالح مصيدة string-slice-out-of-bounds؛ لا تحل إزاحات البايتات محل مواضع القيم العددية. لا تحفظ درجة أو تقدما، ويبقى التنقل مفتوحا. عد إلى مسار الدروس أو اقرأ مرجع النصوص.

lesson-strings-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    اطبع("Name: ").
    دع name: نص = اقرأ_سطر().
    دع next: ص64 = 41 + 1.
    دع greeting: نص = "Hello, " + name + "! Next: " + نسق_ص64(next).
    اطبع(greeting + "\n").
    دع text: نص = "مرحبا".
    اطبع(نسق_ص64(طول(text)) + "\n").
    اطبع(اقتطع(text, 1, 3) + "\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Name: Hello, سلمى! Next: 42\n5\nرح\n"
native: check 0; success / status 0; stdout "Name: Hello, سلمى! Next: 42\n5\nرح\n"
scripted stdin lines: ["سلمى"]
نزّل المصدر افتح في المحرر
aspl check lesson-strings-ar.aspl
aspl run lesson-strings-ar.aspl
lesson-strings-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    print("Name: ");
    let name: string = read_line();
    let next: i64 = 41 + 1;
    let greeting: string = "Hello, " + name + "! Next: " + format_i64(next);
    print(greeting + "\n");
    let text: string = "مرحبا";
    print(format_i64(length(text)) + "\n");
    print(slice(text, 1, 3) + "\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Name: Hello, سلمى! Next: 42\n5\nرح\n"
native: check 0; success / status 0; stdout "Name: Hello, سلمى! Next: 42\n5\nرح\n"
scripted stdin lines: ["سلمى"]
نزّل المصدر افتح في المحرر
aspl check lesson-strings-en.aspl
aspl run lesson-strings-en.aspl
lesson-strings-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    اطبع("Name: ").
    دع name: نص = اقرأ_سطر().
    دع next: ص64 = 41 + 1.
    دع greeting: نص = "Hello, " + name + "! Next: " + نسق_ص64(next).
    اطبع(greeting + "\n").
    دع text: نص = "مرحبا".
    اطبع(نسق_ص64(طول(text)) + "\n").
    اطبع(اقتطع(text, 1, 4) + "\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Name: Hello, سلمى! Next: 42\n5\nرحب\n"
native: check 0; success / status 0; stdout "Name: Hello, سلمى! Next: 42\n5\nرحب\n"
scripted stdin lines: ["سلمى"]
نزّل المصدر افتح في المحرر
aspl check lesson-strings-solution-ar.aspl
aspl run lesson-strings-solution-ar.aspl
lesson-strings-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    print("Name: ");
    let name: string = read_line();
    let next: i64 = 41 + 1;
    let greeting: string = "Hello, " + name + "! Next: " + format_i64(next);
    print(greeting + "\n");
    let text: string = "مرحبا";
    print(format_i64(length(text)) + "\n");
    print(slice(text, 1, 4) + "\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Name: Hello, سلمى! Next: 42\n5\nرحب\n"
native: check 0; success / status 0; stdout "Name: Hello, سلمى! Next: 42\n5\nرحب\n"
scripted stdin lines: ["سلمى"]
نزّل المصدر افتح في المحرر
aspl check lesson-strings-solution-en.aspl
aspl run lesson-strings-solution-en.aspl
الحدود المعيارية للإصدار

القوائم

ما الذي ستتعلمه

أنشئ قائمة ذات عناصر من نوع محدد، وأضف عبر جذر قابل للتغيير، واجمع العناصر ضمن الحدود، واشرح لماذا تحتفظ النسخة بمحتواها القديم.

قبل أن تبدأ

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

أضف واجمع

يسمي قائمة<ص64> / list<i64> قائمة كل عناصرها من نوع ص64 / i64. تنشئ الأقواس المربعة [2, 4, 6]. يجعل متغير / var الاسم numbers جذرا قابلا للتغيير. ينسخ دع copied = numbers / let copied = numbers القيمة الحالية قبل الإضافة.

يضيف أضف(numbers, 8) / append(numbers, 8) عددا صحيحا إلى النهاية. تغير الإضافة موضعا قابلا للتغيير وتعيد وحدة / unit دون قيمة للطباعة. لا يمكن الإضافة عبر جذر دع. يستبدل الإسناد بعنصر مفهرس عنصرا موجودا؛ ولا يزيد طول القائمة.

يعيد طول(numbers) / length(numbers) عدد العناصر. تبدأ حلقة طالما / while بالفهرس 0، وتقرأ numbers[index]، وتضيفه إلى total، وتزيد الفهرس بمقدار 1. تمنع المقارنة الصارمة < length(numbers) تجاوز النهاية. تنسق كل اطبع / print عددها باستخدام نسق_ص64 / format_i64 وتضيف \n صراحة. تعيد دالة الدخول الحالة الطبيعية 0 بعد الطباعة.

توقع المجموع والنسخة

بعد الإضافة تحتوي numbers على أربعة عناصر بفهرسة 0 و1 و2 و3. المجموع 2 + 4 + 6 + 8 = 20. توقع طول النسخة وعنصرها عند الفهرس 2 قبل التشغيل. الخرج الدقيق 20\n3\n6\n والحالة 0. ما زالت copied تحتوي [2, 4, 6]: ينسخ الإسناد قيمة، ولا ينشئ التغيير اللاحق مرجعا مشتركا قابلا للتغيير. ينطبق ذلك أيضا على القوائم المتداخلة.

تلتزم القراءة الصحيحة بـ 0 <= index < length(list). يقرأ المثال المنفصل التالي، وهو فشل مقصود، الفهرس 3 من القائمة الأصلية ذات العناصر الثلاثة. ينجح الفحص ثم تحدث مصيدة list-index-out-of-bounds دون طباعة أو حالة دخول طبيعية. تؤدي الفهارس السالبة إلى مصيدة أيضا. تنهي المصيدة التشغيل وليست نتيجة قابلة للاسترداد.

أضف عددا آخر

أبق النسخة قبل الإضافتين. أضف أضف(numbers, 10) بعد الإضافة الموجودة. الخرج المتوقع بالضبط 30\n3\n6\n والحالة الطبيعية 0.

أضف 10 بعد 8، ثم توقع المجموع والسطرين المتعلقين بالنسخة.

تلميح: أضف استدعاء ثانيا للإضافة إلى numbers قبل الحلقة. أبق copied وحد الحلقة الصارم كما هما.

اعرض الإجابة المشروحة

تزور الحلقة خمسة أعداد صحيحة وتجمع 2 + 4 + 6 + 8 + 10 إلى 30. أنشئت copied قبل الإضافتين، فيبقى طولها 3 وعنصرها عند الفهرس 2 هو 6. تتغير numbers وحدها. ينتج التنسيق ومحارف السطر الجديد الصريحة ثلاثة أسطر، وتعيد دالة الدخول الحالة 0.

تحقق من فهمك

اشرح لماذا يقل الفهرس الأخير عن الطول بواحد ولماذا تتطلب الإضافة متغير. توقع ما يحدث إذا استخدمت الحلقة <= بدلا من <. لا تحفظ درجة أو تقدم، ويبقى التنقل مفتوحا. عد إلى مسار التعلم أو اقرأ مرجع القوائم.

lesson-lists-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    متغير numbers: قائمة<ص64> = [2, 4, 6].
    دع copied: قائمة<ص64> = numbers.
    أضف(numbers, 8).
    متغير index: ص64 = 0.
    متغير total: ص64 = 0.
    طالما (index < طول(numbers)) {
        total = total + numbers[index].
        index = index + 1.
    }
    اطبع(نسق_ص64(total) + "\n").
    اطبع(نسق_ص64(طول(copied)) + "\n").
    اطبع(نسق_ص64(copied[2]) + "\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "20\n3\n6\n"
native: check 0; success / status 0; stdout "20\n3\n6\n"
نزّل المصدر افتح في المحرر
aspl check lesson-lists-ar.aspl
aspl run lesson-lists-ar.aspl
lesson-lists-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    var numbers: list<i64> = [2, 4, 6];
    let copied: list<i64> = numbers;
    append(numbers, 8);
    var index: i64 = 0;
    var total: i64 = 0;
    while (index < length(numbers)) {
        total = total + numbers[index];
        index = index + 1;
    }
    print(format_i64(total) + "\n");
    print(format_i64(length(copied)) + "\n");
    print(format_i64(copied[2]) + "\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "20\n3\n6\n"
native: check 0; success / status 0; stdout "20\n3\n6\n"
نزّل المصدر افتح في المحرر
aspl check lesson-lists-en.aspl
aspl run lesson-lists-en.aspl
lesson-lists-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    متغير numbers: قائمة<ص64> = [2, 4, 6].
    دع copied: قائمة<ص64> = numbers.
    أضف(numbers, 8).
    أضف(numbers, 10).
    متغير index: ص64 = 0.
    متغير total: ص64 = 0.
    طالما (index < طول(numbers)) {
        total = total + numbers[index].
        index = index + 1.
    }
    اطبع(نسق_ص64(total) + "\n").
    اطبع(نسق_ص64(طول(copied)) + "\n").
    اطبع(نسق_ص64(copied[2]) + "\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "30\n3\n6\n"
native: check 0; success / status 0; stdout "30\n3\n6\n"
نزّل المصدر افتح في المحرر
aspl check lesson-lists-solution-ar.aspl
aspl run lesson-lists-solution-ar.aspl
lesson-lists-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    var numbers: list<i64> = [2, 4, 6];
    let copied: list<i64> = numbers;
    append(numbers, 8);
    append(numbers, 10);
    var index: i64 = 0;
    var total: i64 = 0;
    while (index < length(numbers)) {
        total = total + numbers[index];
        index = index + 1;
    }
    print(format_i64(total) + "\n");
    print(format_i64(length(copied)) + "\n");
    print(format_i64(copied[2]) + "\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "30\n3\n6\n"
native: check 0; success / status 0; stdout "30\n3\n6\n"
نزّل المصدر افتح في المحرر
aspl check lesson-lists-solution-en.aspl
aspl run lesson-lists-solution-en.aspl
lesson-list-bounds-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع numbers: قائمة<ص64> = [2, 4, 6].
    اطبع(نسق_ص64(numbers[3])).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; trap / list-index-out-of-bounds; stdout ""
native: check 0; success / status 5 / list-index-out-of-bounds; stdout ""
نزّل المصدر افتح في المحرر
aspl check lesson-list-bounds-ar.aspl
aspl run lesson-list-bounds-ar.aspl
lesson-list-bounds-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let numbers: list<i64> = [2, 4, 6];
    print(format_i64(numbers[3]));
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; trap / list-index-out-of-bounds; stdout ""
native: check 0; success / status 5 / list-index-out-of-bounds; stdout ""
نزّل المصدر افتح في المحرر
aspl check lesson-list-bounds-en.aspl
aspl run lesson-list-bounds-en.aspl
الحدود المعيارية للإصدار

السجلات

ما الذي ستتعلمه

عرف سجل سؤال بنص وجواب صحيح، وأنشئ قيمتين من هذا النوع، وضعهما في قائمة ذات نوع محدد، وغير نسخة مستقلة.

قبل أن تبدأ

اقرأ الدوال والسلاسل النصية والقوائم. يتضمن المثال المستقل دالة الدخول. افتحه كمسودة جديدة في الرئيسية، ثم اختر تشغيل صراحة. تبقى المسودات السابقة متاحة.

أعط السؤال حقولا مسماة

يعرف تصريح سجل / record على مستوى الملف النوع المسمى Question. حقلاه prompt: نص / prompt: string وanswer: ص64 / answer: i64، وتفصل بينهما فاصلة. نص السؤال سلسلة نصية؛ والجواب عدد صحيح. الأسماء Question وprompt وanswer أسماء مستخدم تبقى كتابتها نفسها في مفردات المصدر الموردة.

ينشئ Question { prompt: "2 + 3?", answer: 5 } قيمة بإعطاء كل حقل مرة واحدة بالضبط. تشترك first وsecond في النوع مع اختلاف نص السؤال والجواب. تضع قائمة<Question> / list<Question> القيمتين في questions. يختار الفهرسان 0 و1 السؤال الأول والثاني. تقرأ :: اللاحقة حقلا مسمى، لذا questions[0]::prompt نص وquestions[0]::answer عدد صحيح.

تقبل اطبع / print نصا. اطبع السؤال مباشرة، لكن استخدم نسق_ص64 / format_i64 صراحة للجواب؛ ويضيف كل سطر \n. ينسخ متغير copied: Question = questions[0] / var copied: Question = questions[0] السؤال المختار إلى جذر قابل للتغيير. يغير الإسناد copied::answer = 99 تلك النسخة وحدها. لا يمكن تغيير المعاملات أو جذور دع أو القيم المؤقتة. تعيد دالة الدخول الحالة الطبيعية 0 مستقلة عن قيم الأجوبة.

توقع القيم المستقلة

توقع first::answer بعد تغيير حقل النسخة وقبل التشغيل. الخرج الدقيق 2 + 3?\n5\n3 * 4?\n12\n5\n99\n والحالة 0. يبقى جواب السؤال الأول الأصلي 5 وجواب الثاني 12، أما النسخة فجوابها 99. ينسخ إنشاء القائمة وقراءة عنصر منها القيم أيضا. تغيير قائمة أو سجل متداخل في نسخة يترك الأصل دون تغيير كذلك.

يبقى تصريحا سجل منفصلان نوعين مختلفين حتى إن تطابقت حقولهما. الحقول الناقصة أو المكررة أو المجهولة والحقل من نوع خاطئ أخطاء مصدر تمنع التنفيذ؛ ولا تعيد نتيجة إخفاق. راجع مرجع السجلات.

غير جواب النسخة

غير فقط copied::answer = 99 إلى copied::answer = 42. الخرج المتوقع بالضبط 2 + 3?\n5\n3 * 4?\n12\n5\n42\n والحالة الطبيعية 0.

اجعل جواب النسخة 42. توقع أسطر الخرج التي تتغير.

تلميح: غير العدد المسند عبر copied. أبق المنشئين وquestions دون تغيير.

اعرض الإجابة المشروحة

يتغير السطر الأخير وحده إلى 42. يحتفظ السؤالان في القائمة بحقلي النص والجواب الأصليين، ويبقى جواب first هو 5. تشترك copied معهما في نوع Question لكنها تحمل قيمة مستقلة. يطبع النص مباشرة؛ وما زال كل حقل عددي يحتاج إلى تنسيق صريح. تعيد دالة الدخول الحالة الطبيعية 0.

تحقق من فهمك

اشرح الفرق بين نوع السجل وقيمة السجل. حدد الحقول التي تحتاج إلى تنسيق ولماذا لا يغير تعديل النسخة القائمة. لا تحفظ درجة أو تقدم، ويبقى التنقل مفتوحا. عد إلى مسار التعلم أو تابع إلى مرجع النتائج القابلة للاسترداد.

lesson-records-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

سجل Question { prompt: نص, answer: ص64 }
دالة ابدأ_الرئيسية() -> ص64 {
    دع first: Question = Question { prompt: "2 + 3?", answer: 5 }.
    دع second: Question = Question { prompt: "3 * 4?", answer: 12 }.
    دع questions: قائمة<Question> = [first, second].
    متغير copied: Question = questions[0].
    copied::answer = 99.
    اطبع(questions[0]::prompt + "\n").
    اطبع(نسق_ص64(questions[0]::answer) + "\n").
    اطبع(questions[1]::prompt + "\n").
    اطبع(نسق_ص64(questions[1]::answer) + "\n").
    اطبع(نسق_ص64(first::answer) + "\n").
    اطبع(نسق_ص64(copied::answer) + "\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "2 + 3?\n5\n3 * 4?\n12\n5\n99\n"
native: check 0; success / status 0; stdout "2 + 3?\n5\n3 * 4?\n12\n5\n99\n"
نزّل المصدر افتح في المحرر
aspl check lesson-records-ar.aspl
aspl run lesson-records-ar.aspl
lesson-records-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

record Question { prompt: string, answer: i64 }
fn start_main() -> i64 {
    let first: Question = Question { prompt: "2 + 3?", answer: 5 };
    let second: Question = Question { prompt: "3 * 4?", answer: 12 };
    let questions: list<Question> = [first, second];
    var copied: Question = questions[0];
    copied::answer = 99;
    print(questions[0]::prompt + "\n");
    print(format_i64(questions[0]::answer) + "\n");
    print(questions[1]::prompt + "\n");
    print(format_i64(questions[1]::answer) + "\n");
    print(format_i64(first::answer) + "\n");
    print(format_i64(copied::answer) + "\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "2 + 3?\n5\n3 * 4?\n12\n5\n99\n"
native: check 0; success / status 0; stdout "2 + 3?\n5\n3 * 4?\n12\n5\n99\n"
نزّل المصدر افتح في المحرر
aspl check lesson-records-en.aspl
aspl run lesson-records-en.aspl
lesson-records-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

سجل Question { prompt: نص, answer: ص64 }
دالة ابدأ_الرئيسية() -> ص64 {
    دع first: Question = Question { prompt: "2 + 3?", answer: 5 }.
    دع second: Question = Question { prompt: "3 * 4?", answer: 12 }.
    دع questions: قائمة<Question> = [first, second].
    متغير copied: Question = questions[0].
    copied::answer = 42.
    اطبع(questions[0]::prompt + "\n").
    اطبع(نسق_ص64(questions[0]::answer) + "\n").
    اطبع(questions[1]::prompt + "\n").
    اطبع(نسق_ص64(questions[1]::answer) + "\n").
    اطبع(نسق_ص64(first::answer) + "\n").
    اطبع(نسق_ص64(copied::answer) + "\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "2 + 3?\n5\n3 * 4?\n12\n5\n42\n"
native: check 0; success / status 0; stdout "2 + 3?\n5\n3 * 4?\n12\n5\n42\n"
نزّل المصدر افتح في المحرر
aspl check lesson-records-solution-ar.aspl
aspl run lesson-records-solution-ar.aspl
lesson-records-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

record Question { prompt: string, answer: i64 }
fn start_main() -> i64 {
    let first: Question = Question { prompt: "2 + 3?", answer: 5 };
    let second: Question = Question { prompt: "3 * 4?", answer: 12 };
    let questions: list<Question> = [first, second];
    var copied: Question = questions[0];
    copied::answer = 42;
    print(questions[0]::prompt + "\n");
    print(format_i64(questions[0]::answer) + "\n");
    print(questions[1]::prompt + "\n");
    print(format_i64(questions[1]::answer) + "\n");
    print(format_i64(first::answer) + "\n");
    print(format_i64(copied::answer) + "\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "2 + 3?\n5\n3 * 4?\n12\n5\n42\n"
native: check 0; success / status 0; stdout "2 + 3?\n5\n3 * 4?\n12\n5\n42\n"
نزّل المصدر افتح في المحرر
aspl check lesson-records-solution-en.aspl
aspl run lesson-records-solution-en.aspl
الحدود المعيارية للإصدار

النتائج القابلة للاسترداد

ما الذي ستتعلمه

أعد تحية ناجحة للاسم غير الفارغ أو إخفاق empty-name للنص الفارغ. عالج النتيجتين بقراءة حمولة الفرع المناسب وحدها، وميز النتائج من المصائد وأخطاء المصدر.

قبل أن تبدأ

اقرأ الدوال والشروط وتحليل الأعداد لفهم قالب النتائج السابق. يتضمن البرنامج المستقل الدالة المساعدة ودالة الدخول. افتح مسودة جديدة في الرئيسية واختر تشغيل صراحة؛ تبقى المسودات السابقة متاحة.

أعد قيمة أو معلومات خطأ

يصرح دالة greet(name: نص) -> نتيجة<نص> / fn greet(name: string) -> result<string> بدالة مساعدة حمولة نجاحها نص. تقارن name يطابق "" / name matches "" محتوى النص. يعيد الاسم الفارغ إخفاق("empty-name", "name is empty") / failure(...). يوفر نوع الإرجاع النوع المتوقع نتيجة<نص> للإخفاق، الذي لا يحمل حمولة نجاح. يعيد النص غير الفارغ نجاح("Hello, " + name + "!") / success(...). يعيد كلا المسارين نتيجة.

يستدعي البرنامج الدالة أولا بالاسم "سلمى" ثم بالنص "". تختبر ::نجاح / ::ok فرع النتيجة بقيمة منطقية. يطبع فرع النجاح وحده ::قيمة / ::value؛ ويقرأ فرع الإخفاق وحده ::الخطأ::الرمز / ::error::code. يضيف كل سطر \n صراحة. تحتوي معلومات_خطأ / error_info على الرمز / code ثابت والرسالة / message وصفية. اتخذ القرارات بالرموز لا بصياغة الرسالة. تختار الدالة المساعدة رمزها ورسالتها.

نتيجة الإخفاق بيانات عادية لا تصدر تشخيصا وتسمح بتنفيذ لاحق. تختلف عن خطأ المصدر الذي يمنع التنفيذ، وعن مصيدة لا يمكن التقاطها وتنهي التشغيل. أرجع 0 / return 0 في دالة الدخول حالة العملية الطبيعية بعد معالجة النتيجتين، وليست حمولة تحية أو رمز خطأ. الإيقاف وحدود الموارد نتيجتان منفصلتان أيضا.

توقع الفرعين

حدد قبل التشغيل الحمولة التي يمكن لكل استدعاء قراءتها. الخرج الدقيق Hello, سلمى!\nempty-name\n والحالة 0. لا يوفر الاستدعاء الثاني المخفق نص نجاح. النص الذي يحتوي مسافات غير فارغ؛ لا تزيل الدالة المسافات.

يقرأ الفشل المقصود المنفصل التالي value من نتيجة إخفاق. ينجح الفحص، لكن تحدث مصيدة wrong-result-branch دون طباعة أو حالة دخول طبيعية. قراءة error عند النجاح خاطئة أيضا. يستخدم مصدر الفشل العربي الاسم البديل الإنجليزي المدمج ::value، وهو صحيح في اللغة نفسها. يتجنب ذلك عيب التشخيص في الإصدار الأصلي المنشور 0.7.0 عند تعمد قراءة الفرع الخاطئ بأسماء حقول النتائج العربية، كما يشرح تحليل الأعداد. تستخدم مصادر الدرس المحروسة الفرع الصحيح على المضيفين.

غير التحية الناجحة

غير فقط بادئة النجاح في الدالة من "Hello, " إلى "Welcome, ". أبق إخفاق الاسم الفارغ وفرعي المستدعي. الخرج المتوقع بالضبط Welcome, سلمى!\nempty-name\n والحالة الطبيعية 0.

غير التحية الناجحة إلى Welcome, وتوقع الاستدعاءين.

تلميح: عدل النص داخل نجاح. أبق اختبار الاسم الفارغ والإخفاق وحراس نجاح دون تغيير.

اعرض الإجابة المشروحة

يصل الاسم غير الفارغ إلى نجاح، فيطبع فرع النجاح لدى المستدعي Welcome, سلمى! وسطره الجديد. ما زال النص الفارغ يعيد empty-name دون حمولة نجاح. يقرأ فرع الإخفاق وحده رمز الخطأ ويطبعه. تسمح معالجة نتيجة الإخفاق لدالة الدخول بالاستمرار وإرجاع الحالة الطبيعية 0.

تحقق من فهمك

اشرح من أين يحصل الإخفاق على نوع حمولته ولماذا لا تكون قراءة أي حمولة خاطئة آمنة. قارن empty-name وwrong-result-branch ونوع إرجاع خاطئا. لا تحفظ درجة أو تقدم، ويبقى التنقل مفتوحا. عد إلى مسار التعلم أو اقرأ مرجع النتائج.

lesson-results-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة greet(name: نص) -> نتيجة<نص> {
    إذا (name يطابق "") {
        أرجع إخفاق("empty-name", "name is empty").
    }
    أرجع نجاح("Hello, " + name + "!").
}
دالة ابدأ_الرئيسية() -> ص64 {
    دع greeting: نتيجة<نص> = greet("سلمى").
    إذا (greeting::نجاح) {
        اطبع(greeting::قيمة + "\n").
    } وإلا {
        اطبع(greeting::الخطأ::الرمز + "\n").
    }
    دع empty: نتيجة<نص> = greet("").
    إذا (empty::نجاح) {
        اطبع(empty::قيمة + "\n").
    } وإلا {
        اطبع(empty::الخطأ::الرمز + "\n").
    }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Hello, سلمى!\nempty-name\n"
native: check 0; success / status 0; stdout "Hello, سلمى!\nempty-name\n"
نزّل المصدر افتح في المحرر
aspl check lesson-results-ar.aspl
aspl run lesson-results-ar.aspl
lesson-results-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn greet(name: string) -> result<string> {
    if (name matches "") {
        return failure("empty-name", "name is empty");
    }
    return success("Hello, " + name + "!");
}
fn start_main() -> i64 {
    let greeting: result<string> = greet("سلمى");
    if (greeting::ok) {
        print(greeting::value + "\n");
    } else {
        print(greeting::error::code + "\n");
    }
    let empty: result<string> = greet("");
    if (empty::ok) {
        print(empty::value + "\n");
    } else {
        print(empty::error::code + "\n");
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Hello, سلمى!\nempty-name\n"
native: check 0; success / status 0; stdout "Hello, سلمى!\nempty-name\n"
نزّل المصدر افتح في المحرر
aspl check lesson-results-en.aspl
aspl run lesson-results-en.aspl
lesson-results-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة greet(name: نص) -> نتيجة<نص> {
    إذا (name يطابق "") {
        أرجع إخفاق("empty-name", "name is empty").
    }
    أرجع نجاح("Welcome, " + name + "!").
}
دالة ابدأ_الرئيسية() -> ص64 {
    دع greeting: نتيجة<نص> = greet("سلمى").
    إذا (greeting::نجاح) {
        اطبع(greeting::قيمة + "\n").
    } وإلا {
        اطبع(greeting::الخطأ::الرمز + "\n").
    }
    دع empty: نتيجة<نص> = greet("").
    إذا (empty::نجاح) {
        اطبع(empty::قيمة + "\n").
    } وإلا {
        اطبع(empty::الخطأ::الرمز + "\n").
    }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Welcome, سلمى!\nempty-name\n"
native: check 0; success / status 0; stdout "Welcome, سلمى!\nempty-name\n"
نزّل المصدر افتح في المحرر
aspl check lesson-results-solution-ar.aspl
aspl run lesson-results-solution-ar.aspl
lesson-results-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn greet(name: string) -> result<string> {
    if (name matches "") {
        return failure("empty-name", "name is empty");
    }
    return success("Welcome, " + name + "!");
}
fn start_main() -> i64 {
    let greeting: result<string> = greet("سلمى");
    if (greeting::ok) {
        print(greeting::value + "\n");
    } else {
        print(greeting::error::code + "\n");
    }
    let empty: result<string> = greet("");
    if (empty::ok) {
        print(empty::value + "\n");
    } else {
        print(empty::error::code + "\n");
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Welcome, سلمى!\nempty-name\n"
native: check 0; success / status 0; stdout "Welcome, سلمى!\nempty-name\n"
نزّل المصدر افتح في المحرر
aspl check lesson-results-solution-en.aspl
aspl run lesson-results-solution-en.aspl
lesson-result-wrong-payload-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع reply: نتيجة<نص> = إخفاق("empty-name", "name is empty").
    اطبع(reply::value).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; trap / wrong-result-branch; stdout ""
native: check 0; success / status 5 / wrong-result-branch; stdout ""
نزّل المصدر افتح في المحرر
aspl check lesson-result-wrong-payload-ar.aspl
aspl run lesson-result-wrong-payload-ar.aspl
lesson-result-wrong-payload-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let reply: result<string> = failure("empty-name", "name is empty");
    print(reply::value);
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; trap / wrong-result-branch; stdout ""
native: check 0; success / status 5 / wrong-result-branch; stdout ""
نزّل المصدر افتح في المحرر
aspl check lesson-result-wrong-payload-en.aspl
aspl run lesson-result-wrong-payload-en.aspl
الحدود المعيارية للإصدار

ملفات المتصفح الافتراضية

ما الذي ستتعلمه

عالج ملفا مفقودا، واكتب hello يتبعه سطر جديد إلى lesson.txt، واقرأه مجددا. اشرح متى تبقى ملفات تشغيل المتصفح المؤقتة وكيف تحفظ بايتاتها الدقيقة.

قبل أن تبدأ

اقرأ السلاسل النصية والنتائج القابلة للاسترداد. افتح هذا البرنامج المستقل كمسودة جديدة في الرئيسية واختر تشغيل صراحة. ابدأ بمجموعة ملفات تشغيل فارغة في المسودة المقصودة حتى يغيب missing.txt. يجهز فتح المثال المصدر وحده ولا يستورد ملفات أو يشغله. تبقى المسودات السابقة متاحة.

اقرأ وعالج الإخفاق واكتب واقرأ مجددا

تعيد اقرأ_ملف_نصي("missing.txt") / read_text_file(...) نوع نتيجة<نص> / result<string>. اختبر ::نجاح / ::ok أولا. عند الغياب يقرأ فرع الإخفاق وحده ::الخطأ::الرمز / ::error::code ويطبع not-found مع \n. إن وجد الملف يقرأ فرع النجاح وحده ::قيمة / ::value. يبقى المصدر محروسا في الحالتين.

تنشئ اكتب_ملف_نصي("lesson.txt", "hello\n") / write_text_file(...) الملف أو تستبدله بنص UTF-8. تعيد نتيجة<وحدة> / result<unit>: لا تحمل الكتابة الناجحة قيمة قابلة للقراءة، لذا اختبر النجاح بدلا من قراءة saved::value. يوفر الإخفاق وحده معلومات خطأ. داخل معالجة نجاح الكتابة تعيد قراءة أخرى نصا؛ ويطبعه فرع النجاح مباشرة. يحتوي النص سطره الجديد بالفعل فلا تضيف الطباعة محرفا آخر. تبقى إخفاقات القراءة والكتابة نتائج قابلة للاسترداد. تنهي المصيدة التنفيذ. تعيد دالة الدخول الحالة الطبيعية 0 بعد الفروع، مستقلة عن الخرج ومحتوى الملف.

توقع الخرج والبايتات

مع مجموعة فارغة يكون الخرج الدقيق not-found\nhello\n والحالة 0. يحتوي lesson.txt على ستة بايتات بالضبط، بالنظام الست عشري 68 65 6c 6c 6f 0a. يوجد محرف LF واحد دون سطر إضافي أو علامة ترتيب بايتات. افحص ملفات التشغيل بعد التنفيذ ونزل lesson.txt صراحة لحفظ تلك البايتات خارج الصفحة.

يمكن أن تبقى الملفات لتشغيل آخر في المستند الحالي للمسودة نفسها. يعالج التشغيل الثاني غياب missing.txt مجددا ويستبدل lesson.txt بالبايتات نفسها. يمسح التحديث كل ملفات التشغيل والخرج وسجل الإدخال وحالة العامل، بينما يبقى المصدر المحفوظ. لا يحفظ حفظ المصدر ملفات التشغيل. نزل البيانات قبل التحديث إن احتجتها. لا يترجم تغيير لغة القراءة المصدر أو البايتات.

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

غير النص المحفوظ

غير النص المكتوب وحده إلى "hello again\n". ابدأ دون missing.txt. الخرج المتوقع بالضبط not-found\nhello again\n والحالة 0؛ يحتوي lesson.txt الآن اثني عشر بايتا بنص UTF-8 يمثل hello again يتبعه LF.

اكتب hello again يتبعه سطر جديد واحد، ثم توقع القراءة والتنزيل.

تلميح: عدل المعامل الثاني وحده لدالة الكتابة. أبق اسم الملف وكل حراس النتائج وطباعة النص المقروء مباشرة.

اعرض الإجابة المشروحة

ما زال missing.txt الغائب يعيد not-found ويستمر التنفيذ. تستبدل الكتابة lesson.txt بنص hello again ومحرف LF واحد. يقرأ فرع نجاحها الملف نفسه ويطبع البايتات الدقيقة دون إضافة سطر جديد ثان. يحفظ التنزيل البايتات الاثني عشر؛ ويمسح التحديث نسخة المتصفح مع استعادة المصدر المحفوظ. تعيد دالة الدخول الحالة الطبيعية 0.

تحقق من فهمك

اشرح لماذا تستمر القراءة المخفقة ولماذا لا تحمل الكتابة الناجحة حمولة قيمة وما الذي يستعيده التحديث. توقع الفرع الأول إن استوردت missing.txt بنص قبل التشغيل. لا تحفظ درجة أو تقدم، ويبقى التنقل مفتوحا. وصلت إلى الدرس 12 من مسار المتصفح. عد إلى مسار التعلم أو اقرأ واجهة الملفات النصية.

lesson-virtual-files-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع missing: نتيجة<نص> = اقرأ_ملف_نصي("missing.txt").
    إذا (missing::نجاح) {
        اطبع(missing::قيمة).
    } وإلا {
        اطبع(missing::الخطأ::الرمز + "\n").
    }
    دع saved: نتيجة<وحدة> = اكتب_ملف_نصي("lesson.txt", "hello\n").
    إذا (saved::نجاح) {
        دع loaded: نتيجة<نص> = اقرأ_ملف_نصي("lesson.txt").
        إذا (loaded::نجاح) {
            اطبع(loaded::قيمة).
        } وإلا {
            اطبع(loaded::الخطأ::الرمز + "\n").
        }
    } وإلا {
        اطبع(saved::الخطأ::الرمز + "\n").
    }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "not-found\nhello\n"
native: check 0; success / status 0; stdout "not-found\nhello\n"
نزّل المصدر افتح في المحرر
aspl check lesson-virtual-files-ar.aspl
aspl run lesson-virtual-files-ar.aspl
lesson-virtual-files-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let missing: result<string> = read_text_file("missing.txt");
    if (missing::ok) {
        print(missing::value);
    } else {
        print(missing::error::code + "\n");
    }
    let saved: result<unit> = write_text_file("lesson.txt", "hello\n");
    if (saved::ok) {
        let loaded: result<string> = read_text_file("lesson.txt");
        if (loaded::ok) {
            print(loaded::value);
        } else {
            print(loaded::error::code + "\n");
        }
    } else {
        print(saved::error::code + "\n");
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "not-found\nhello\n"
native: check 0; success / status 0; stdout "not-found\nhello\n"
نزّل المصدر افتح في المحرر
aspl check lesson-virtual-files-en.aspl
aspl run lesson-virtual-files-en.aspl
lesson-virtual-files-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

دالة ابدأ_الرئيسية() -> ص64 {
    دع missing: نتيجة<نص> = اقرأ_ملف_نصي("missing.txt").
    إذا (missing::نجاح) {
        اطبع(missing::قيمة).
    } وإلا {
        اطبع(missing::الخطأ::الرمز + "\n").
    }
    دع saved: نتيجة<وحدة> = اكتب_ملف_نصي("lesson.txt", "hello again\n").
    إذا (saved::نجاح) {
        دع loaded: نتيجة<نص> = اقرأ_ملف_نصي("lesson.txt").
        إذا (loaded::نجاح) {
            اطبع(loaded::قيمة).
        } وإلا {
            اطبع(loaded::الخطأ::الرمز + "\n").
        }
    } وإلا {
        اطبع(saved::الخطأ::الرمز + "\n").
    }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "not-found\nhello again\n"
native: check 0; success / status 0; stdout "not-found\nhello again\n"
نزّل المصدر افتح في المحرر
aspl check lesson-virtual-files-solution-ar.aspl
aspl run lesson-virtual-files-solution-ar.aspl
lesson-virtual-files-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

fn start_main() -> i64 {
    let missing: result<string> = read_text_file("missing.txt");
    if (missing::ok) {
        print(missing::value);
    } else {
        print(missing::error::code + "\n");
    }
    let saved: result<unit> = write_text_file("lesson.txt", "hello again\n");
    if (saved::ok) {
        let loaded: result<string> = read_text_file("lesson.txt");
        if (loaded::ok) {
            print(loaded::value);
        } else {
            print(loaded::error::code + "\n");
        }
    } else {
        print(saved::error::code + "\n");
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "not-found\nhello again\n"
native: check 0; success / status 0; stdout "not-found\nhello again\n"
نزّل المصدر افتح في المحرر
aspl check lesson-virtual-files-solution-en.aspl
aspl run lesson-virtual-files-solution-en.aspl
الحدود المعيارية للإصدار

اختبار في ملف واحد

ما الذي ستتعلمه

اجمع سجلات الأسئلة وقائمة ذات نوع محدد ودالة مساعدة وإدخالا صارما في اختبار حسابي بملف واحد. ابنه في أربع مراحل صغيرة واشرح سبب نهاية كل تشغيل.

قبل أن تبدأ

اقرأ الحلقات والدوال والإدخال النصي وتحليل الأعداد والسلاسل النصية والقوائم والسجلات والنتائج القابلة للاسترداد. تقود الدروس الأساسية الاثنا عشر إلى هنا؛ ولا يحتاج الاختبار إلى ملفات افتراضية.

كل مصدر أدناه ملف مستقل كامل. افتحه كمسودة جديدة في الرئيسية، ثم اختر تشغيل صراحة. تبقى تعديلاتك السابقة متاحة. لغة القراءة ومفردات المصدر لا تترجمان مسودتك أو ردود الإدخال وقت التشغيل.

المرحلة 1: بيانات الأسئلة ونصوصها

يطبع المصدر الابتدائي 2 + 3?\n وحده، ويعيد الحالة 0 ولا يقرأ إدخالا. يتضمن سجلات Question الخمسة كاملة. لكل سجل prompt: نص وanswer: ص64؛ وتحفظ قائمة<Question> ترتيبها الثابت. الأجوبة المتوقعة 5 و5 و12 و4 و15.

توقع نصوص الأسئلة الخمسة بالترتيب. استبدل الطباعة الواحدة بحلقة تطبع كل نص. يطبع الحل بالضبط 2 + 3?\n9 - 4?\n3 * 4?\n12 / 3?\n7 + 8?\n، ويعيد 0 دون قراءة إدخال. يعرض البيانات دون فحص الأجوبة أو حساب درجة.

اطبع نصوص الأسئلة الخمسة بترتيبها المورد.

تلميح: ابدأ فهرسا قابلا للتغيير عند 0. طالما هو أصغر من طول(questions)، اطبع questions[index]::prompt وسطرا جديدا، ثم أضف 1 إلى index.

اعرض الإجابة المشروحة

يزور الفهرس المواضع من 0 إلى 4. يمنع شرط الأصغر الصارم الوصول خارج الحدود عند 5. يقدم كل سجل نص السؤال، فتقبله اطبع مباشرة. تؤدي زيادة الفهرس إلى انتهاء الحلقة. تعيد دالة الدخول الحالة الطبيعية 0؛ ولم يقرأ أو يحسب أي جواب.

المرحلة 2: الدالة المساعدة والتغذية الراجعة

يستدعي المصدر الابتدائي feedback بالعدد 5 ثم 6 للسؤال الأول. تعيد دالته is_correct عمدا خطأ لكل جواب. يطبع Wrong. Expected 5.\nWrong. Expected 5.\n، ويعيد 0 ولا يقرأ إدخالا. هذا عرض للتغذية الراجعة بمقارنة لم تكتمل بعد.

تأخذ is_correct(question: Question, answer: ص64) -> منطقي قيمة سؤال وجوابا عدديا، ثم تعيد قيمة منطقية. تعيد feedback النوع وحدة، لذا يستخدم استدعاؤها كتعليمة. تختار إذا التغذية الراجعة الفورية؛ وينسق فرع الجواب الخاطئ العدد المتوقع من السجل. كل الدوال المساعدة على مستوى الملف نفسه. توقع السطر الذي يتغير حين تعمل المقارنة.

استبدل خطأ الثابتة في الدالة المساعدة بمقارنة مع الجواب المتوقع للسؤال.

تلميح: أعد answer يطابق question::answer. أبق فرعي التغذية الراجعة والاستدعاءين بالعددين 5 و6.

اعرض الإجابة المشروحة

يقارن الاستدعاء الأول 5 مع 5 ويطبع Correct. . يقارن الثاني 6 مع 5 ويطبع Wrong. Expected 5. . يعيد الحل الكامل الحالة 0 دون قراءة أو حساب درجة. تعيد الدالة المساعدة قيمة منطقية؛ وهي مستقلة عن حالة العملية الصحيحة التي تعيدها دالة الدخول.

المرحلة 3: الإدخال والتوقف والتحليل المتحقق

يسأل المصدر الابتدائي السؤال الأول مرة واحدة. يفحص q الصغيرة المطابقة تماما قبل حلل_ص64، ويطبع ملخص توقف مبكر بعدادات صفرية عند q، أو Parsed: 5\n عند 5، أو Invalid: invalid-number\n عند 12x. ثم يعيد 0 حتى بعد إدخال غير صالح. لا يعيد المحاولة ولا يفحص الجواب ولا يحسب درجة بعد. إذا جهزت 12x ثم 5، يستهلك السطر الأول وحده.

أضف حلقة بعلم منطقي pending حول فروع الإدخال الموردة. يجعل نجاح التحليل وحده العلم خطأ. توقع نص السؤال بعد 12x. يكرر الحل 2 + 3? ، ويطبع Parsed: 5\n بعد الرد التالي 5، ويعيد 0. خرجه الدقيق 2 + 3? Retry: invalid-number\n2 + 3? Parsed: 5\n. يبقى هذا ملف تدريب على تحليل سؤال واحد دون تغذية راجعة أو درجة. تبقى عدادات توقفه المبكر صفرا لأن هذه المرحلة لا تحسب أجوبة.

أعد السؤال الأول نفسه بعد إخفاق التحليل. أنه حلقة التدريب بعد عدد واحد محلل.

تلميح: ابدأ pending بصواب. أبق q قبل التحليل، واقرأ قيمة عند نجاح فقط، واترك pending دون تغيير في فرع الخطأ. غير تسمية الخطأ من Invalid إلى Retry.

اعرض الإجابة المشروحة

تحمل نتيجة الإخفاق معلومات خطأ ولا تحمل حمولة عددية قابلة للقراءة. تترك طباعة رمزها pending صواب، فيطلب السؤال نفسه مجددا. تطبع نتيجة النجاح قيمتها وتجعل pending خطأ. تعيد q المطابقة تماما من الدالة قبل التحليل. تعيد دالة الدخول 0 بعد عدد أو q، أما EOF فيوقع فخا وإيقاف فيلغي التشغيل. لا يضيف أي جواب عددي درجة في هذه المرحلة.

تزيل اقرأ_سطر / read_line نهاية السطر وتحفظ بقية النص. استخدم line يطابق "q" / line matches "q" قبل التحليل. لا تحذف المسافات ولا تحول الأرقام إلى صيغة أخرى ولا توحد حالة الأحرف. تقبل حلل_ص64 / parse_i64 علامة ASCII اختيارية + أو -، ثم أرقام ASCII من 0 إلى 9، ضمن مجال ص64. يحلل +05 و005 إلى 5؛ ويحلل -1 إلى جواب خاطئ صالح في الاختبار الكامل. الإدخال الفارغ و12x و5 والرقم العربي الهندي ٥ والعربي الهندي الممتد ۵ والحرف الكبير Q كلها invalid-number. العدد 9223372036854775808 هو number-out-of-range. يعيد الحل المحاولة بعد كلا الإخفاقين دون تغيير النص. راجع جدول النص العددي.

يقرأ فرع النجاح وحده parsed::قيمة / parsed::value؛ ويقرأ فرع الإخفاق وحده parsed::الخطأ::الرمز / parsed::error::code. إخفاق التحليل قابل للاسترداد. يقدم إغلاق الإدخال أثناء الانتظار EOF ويوقع فخ input-exhausted مع إبقاء الخرج السابق. يبلغ إيقاف عن إلغاء ويحفظ الخرج السابق. لا يعد أي منهما بملخص درجة لطيف أو إكمال طبيعي.

المرحلة 4: الدرجة والانتقال والملخص

يسأل المصدر الابتدائي الآن الأسئلة الخمسة، ويعيد محاولة الإدخال غير الصالح، ويفحص الأجوبة وينتقل بعد كل عدد محلل. يزيد answered وindex مرة واحدة، لكنه يترك correct صفرا عمدا. تطبع خمسة ردود صحيحة خمسة أسطر Correct. ثم Completed. Correct: 0; answered: 5; total: 5.\n. يعرض هذا المصدر درجة لم تكتمل بعد، وليس نتيجة دقيقة. يدعم التوقف المبكر ويعيد 0 عند الإكمال أو q.

تأتي total = طول(questions) من القائمة. تبدأ دالة الدخول index وanswered وcorrect من الصفر مع كل تشغيل صريح. تفحص الحلقة index < total قبل اختيار questions[index]. تعرض index + 1 للقارئ بينما يبدأ الفهرس من الصفر. يزيد الجواب العددي الخاطئ answered وينتقل أيضا؛ ولا يزيد correct أبدا. لا يغير إخفاق التحليل أيا من هذه المتغيرات الثلاثة. تستدعي q المطابقة تماما summary قبل حساب السؤال المعلق.

توقع ملخص 5 و5 و0 ثم q قبل إصلاح الدرجة. يبلغ المصدر الابتدائي عن صفر صحيح وثلاثة أجوبة. أضف التحديث الناقص في فرع الجواب المطابق وحده. يبلغ الحل الكامل عن جوابين صحيحين وثلاثة أجوبة ومجموع خمسة. تنسق summary العدادات المطبوعة؛ وتعيد وحدة ولا تحدد حالة العملية. يعيد مسارا الخروج الطبيعي 0 صراحة.

أضف 1 إلى correct فقط حين تقول الدالة المساعدة إن العدد المحلل يطابق الجواب. تتبع answered وindex عبر رد غير صالح وجواب خاطئ ثم q.

تلميح: استبدل التعليق المورد بعد Correct بالتعليمة correct = correct + 1. أبق تحديثي answered وindex بعد فرعي التغذية الراجعة داخل parsed::نجاح. اترك فرع الإخفاق وإعادة q دون تغيير.

اعرض الإجابة المشروحة

يزيد فرع الجواب المطابق وحده correct. يشترك الفرعان العدديان بعد ذلك في زيادة واحدة لكل من answered وindex. لا يدخل إخفاق التحليل أيا منهما، فيكرر السؤال المعلق بعدادات ثابتة. يعيد فرع q قبل التحليل أو تلك الزيادات. تنتهي خمسة ردود صحيحة عند correct يساوي 5 وanswered يساوي 5 وtotal يساوي 5. يصبح index بعد الرد الخامس 5، فيكون اختبار الحلقة خطأ ويطبع الملخص دون قراءة إضافية. يعيد الحل الكامل بملف واحد الحالة 0.

جرب النهايات المختلفة

يحفظ المصدر سلاسل الخرج الإنجليزية في المفردات الموردة كلتيهما، فتطبق هذه الفحوص الدقيقة على صفحتي القراءة. Correct عدد الأجوبة الصحيحة، وanswered عدد الردود العددية الصالحة، وtotal طول قائمة الأسئلة. الدرجة المطبوعة مستقلة عن حالة العملية الطبيعية. لا توجد عتبة نجاح.

الردود أو التحكم سلوك الحل الكامل
5 و5 و12 و4 و15 خمسة أسطر تغذية راجعة صحيحة، ثم Completed. Correct: 5; answered: 5; total: 5. والحالة 0. لا سؤال أو قراءة سادسة.
12x ثم 6 ثم q يعيد السؤال الأول المحاولة مع invalid-number؛ ويطبع 6 الرسالة Wrong. Expected 5. وينتقل للسؤال الثاني؛ وتبلغ q عن Stopped early. Correct: 0; answered: 1; total: 5. بالحالة 0.
9223372036854775808 ثم q يعيد السؤال الأول المحاولة مع number-out-of-range؛ ويبلغ التوقف المبكر عن صفر صحيح وصفر مجاب ومجموع خمسة والحالة 0.
الرد الأول q Stopped early. Correct: 0; answered: 0; total: 5. والحالة 0.
5 و5 و0 ثم q يطبع الرد الثالث Wrong. Expected 12.؛ ويبلغ التوقف المبكر عن جوابين صحيحين وثلاثة أجوبة ومجموع خمسة والحالة 0.
إغلاق الإدخال أثناء الانتظار فخ input-exhausted. تبقى نصوص الأسئلة والتغذية الراجعة السابقة؛ ولا يضمن ملخص لطيف عند EOF.
إيقاف أثناء الانتظار إلغاء. يبقى الخرج السابق؛ وهذه ليست EOF أو إكمالا طبيعيا.

بعد الإكمال، اختر تشغيل مجددا لتبدأ من السؤال الأول بعدادات صفرية. يحفظ حفظ المسودة الشفرة، ولا يحفظ درجة أو تشغيلا معلقا. لا يستخدم الاختبار وحدات أو مكتبات أصلية أو ملفات درجات أو عشوائية أو مؤقتات.

سؤال سادس اختياري

أضف Question { prompt: "10 - 3?", answer: 7 } عنصرا سادسا إلى قائمة الحل الكامل. توقع تغير المجموع قبل التشغيل. أرسل 5 و5 و12 و4 و15 و7؛ وتوقع Question 6/6: 10 - 3? Correct.\n ثم Completed. Correct: 6; answered: 6; total: 6.\n بالحالة 0 ودون قراءة سابعة. توفر طول(questions) المجموع، فتتبع الحلقة ومقامات أرقام الأسئلة والملخصان القائمة. هناك تحد منفصل اختياري هو إعادة بناء الاختبار بملف واحد من مسودة فارغة.

تحقق من فهمك

اشرح لماذا ينتقل الجواب العددي الخاطئ بينما تعيد Q المحاولة، ولماذا لا تحسب q السؤال المعلق، ولماذا لا يمكن لإغلاق الإدخال أن يعد بملخص درجة. تتبع العدادات بعد 12x و6 و5 ثم q. يكون عدد الصحيح صفرا بعد 6، ثم يصبح واحدا مع جوابين حين تنهي q التشغيل. لا تحفظ درجة أو تقدم، ويبقى التنقل مفتوحا. عد إلى مسار التعلم.

اختر إلى أين تتجه بعد ذلك للدروس الأصلية الاختيارية والأدلة العملية.

quiz-data-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

سجل Question { prompt: نص, answer: ص64 }
دالة ابدأ_الرئيسية() -> ص64 {
    دع questions: قائمة<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ].
    اطبع(questions[0]::prompt + "\n").
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "2 + 3?\n"
native: check 0; success / status 0; stdout "2 + 3?\n"
نزّل المصدر افتح في المحرر
aspl check quiz-data-ar.aspl
aspl run quiz-data-ar.aspl
quiz-data-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

record Question { prompt: string, answer: i64 }
fn start_main() -> i64 {
    let questions: list<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ];
    print(questions[0]::prompt + "\n");
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "2 + 3?\n"
native: check 0; success / status 0; stdout "2 + 3?\n"
نزّل المصدر افتح في المحرر
aspl check quiz-data-en.aspl
aspl run quiz-data-en.aspl
quiz-data-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

سجل Question { prompt: نص, answer: ص64 }
دالة ابدأ_الرئيسية() -> ص64 {
    دع questions: قائمة<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ].
    متغير index: ص64 = 0.
    طالما (index < طول(questions)) {
        اطبع(questions[index]::prompt + "\n").
        index = index + 1.
    }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "2 + 3?\n9 - 4?\n3 * 4?\n12 / 3?\n7 + 8?\n"
native: check 0; success / status 0; stdout "2 + 3?\n9 - 4?\n3 * 4?\n12 / 3?\n7 + 8?\n"
نزّل المصدر افتح في المحرر
aspl check quiz-data-solution-ar.aspl
aspl run quiz-data-solution-ar.aspl
quiz-data-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

record Question { prompt: string, answer: i64 }
fn start_main() -> i64 {
    let questions: list<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ];
    var index: i64 = 0;
    while (index < length(questions)) {
        print(questions[index]::prompt + "\n");
        index = index + 1;
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "2 + 3?\n9 - 4?\n3 * 4?\n12 / 3?\n7 + 8?\n"
native: check 0; success / status 0; stdout "2 + 3?\n9 - 4?\n3 * 4?\n12 / 3?\n7 + 8?\n"
نزّل المصدر افتح في المحرر
aspl check quiz-data-solution-en.aspl
aspl run quiz-data-solution-en.aspl
quiz-helper-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

سجل Question { prompt: نص, answer: ص64 }
دالة is_correct(question: Question, answer: ص64) -> منطقي {
    أرجع خطأ.
}
دالة feedback(question: Question, answer: ص64) -> وحدة {
    إذا (is_correct(question, answer)) {
        اطبع("Correct.\n").
    } وإلا {
        اطبع("Wrong. Expected " + نسق_ص64(question::answer) + ".\n").
    }
}
دالة ابدأ_الرئيسية() -> ص64 {
    دع questions: قائمة<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ].
    feedback(questions[0], 5).
    feedback(questions[0], 6).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Wrong. Expected 5.\nWrong. Expected 5.\n"
native: check 0; success / status 0; stdout "Wrong. Expected 5.\nWrong. Expected 5.\n"
نزّل المصدر افتح في المحرر
aspl check quiz-helper-ar.aspl
aspl run quiz-helper-ar.aspl
quiz-helper-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

record Question { prompt: string, answer: i64 }
fn is_correct(question: Question, answer: i64) -> bool {
    return false;
}
fn feedback(question: Question, answer: i64) -> unit {
    if (is_correct(question, answer)) {
        print("Correct.\n");
    } else {
        print("Wrong. Expected " + format_i64(question::answer) + ".\n");
    }
}
fn start_main() -> i64 {
    let questions: list<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ];
    feedback(questions[0], 5);
    feedback(questions[0], 6);
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Wrong. Expected 5.\nWrong. Expected 5.\n"
native: check 0; success / status 0; stdout "Wrong. Expected 5.\nWrong. Expected 5.\n"
نزّل المصدر افتح في المحرر
aspl check quiz-helper-en.aspl
aspl run quiz-helper-en.aspl
quiz-helper-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

سجل Question { prompt: نص, answer: ص64 }
دالة is_correct(question: Question, answer: ص64) -> منطقي {
    أرجع answer يطابق question::answer.
}
دالة feedback(question: Question, answer: ص64) -> وحدة {
    إذا (is_correct(question, answer)) {
        اطبع("Correct.\n").
    } وإلا {
        اطبع("Wrong. Expected " + نسق_ص64(question::answer) + ".\n").
    }
}
دالة ابدأ_الرئيسية() -> ص64 {
    دع questions: قائمة<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ].
    feedback(questions[0], 5).
    feedback(questions[0], 6).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Correct.\nWrong. Expected 5.\n"
native: check 0; success / status 0; stdout "Correct.\nWrong. Expected 5.\n"
نزّل المصدر افتح في المحرر
aspl check quiz-helper-solution-ar.aspl
aspl run quiz-helper-solution-ar.aspl
quiz-helper-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

record Question { prompt: string, answer: i64 }
fn is_correct(question: Question, answer: i64) -> bool {
    return answer matches question::answer;
}
fn feedback(question: Question, answer: i64) -> unit {
    if (is_correct(question, answer)) {
        print("Correct.\n");
    } else {
        print("Wrong. Expected " + format_i64(question::answer) + ".\n");
    }
}
fn start_main() -> i64 {
    let questions: list<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ];
    feedback(questions[0], 5);
    feedback(questions[0], 6);
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Correct.\nWrong. Expected 5.\n"
native: check 0; success / status 0; stdout "Correct.\nWrong. Expected 5.\n"
نزّل المصدر افتح في المحرر
aspl check quiz-helper-solution-en.aspl
aspl run quiz-helper-solution-en.aspl
quiz-input-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

سجل Question { prompt: نص, answer: ص64 }
دالة ابدأ_الرئيسية() -> ص64 {
    دع questions: قائمة<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ].
        اطبع(questions[0]::prompt + " ").
        دع line: نص = اقرأ_سطر().
        إذا (line يطابق "q") {
            اطبع("Stopped early. Correct: 0; answered: 0; total: " + نسق_ص64(طول(questions)) + ".\n").
            أرجع 0.
        }
        دع parsed: نتيجة<ص64> = حلل_ص64(line).
        إذا (parsed::نجاح) {
            اطبع("Parsed: " + نسق_ص64(parsed::قيمة) + "\n").
        } وإلا {
            اطبع("Invalid: " + parsed::الخطأ::الرمز + "\n").
        }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "2 + 3? Invalid: invalid-number\n"
native: check 0; success / status 0; stdout "2 + 3? Invalid: invalid-number\n"
scripted stdin lines: ["12x"]
نزّل المصدر افتح في المحرر
aspl check quiz-input-ar.aspl
aspl run quiz-input-ar.aspl
quiz-input-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

record Question { prompt: string, answer: i64 }
fn start_main() -> i64 {
    let questions: list<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ];
        print(questions[0]::prompt + " ");
        let line: string = read_line();
        if (line matches "q") {
            print("Stopped early. Correct: 0; answered: 0; total: " + format_i64(length(questions)) + ".\n");
            return 0;
        }
        let parsed: result<i64> = parse_i64(line);
        if (parsed::ok) {
            print("Parsed: " + format_i64(parsed::value) + "\n");
        } else {
            print("Invalid: " + parsed::error::code + "\n");
        }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "2 + 3? Invalid: invalid-number\n"
native: check 0; success / status 0; stdout "2 + 3? Invalid: invalid-number\n"
scripted stdin lines: ["12x"]
نزّل المصدر افتح في المحرر
aspl check quiz-input-en.aspl
aspl run quiz-input-en.aspl
quiz-input-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

سجل Question { prompt: نص, answer: ص64 }
دالة ابدأ_الرئيسية() -> ص64 {
    دع questions: قائمة<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ].
    متغير pending: منطقي = صواب.
    طالما (pending) {
        اطبع(questions[0]::prompt + " ").
        دع line: نص = اقرأ_سطر().
        إذا (line يطابق "q") {
            اطبع("Stopped early. Correct: 0; answered: 0; total: " + نسق_ص64(طول(questions)) + ".\n").
            أرجع 0.
        }
        دع parsed: نتيجة<ص64> = حلل_ص64(line).
        إذا (parsed::نجاح) {
            اطبع("Parsed: " + نسق_ص64(parsed::قيمة) + "\n").
            pending = خطأ.
        } وإلا {
            اطبع("Retry: " + parsed::الخطأ::الرمز + "\n").
        }
    }
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "2 + 3? Retry: invalid-number\n2 + 3? Parsed: 5\n"
native: check 0; success / status 0; stdout "2 + 3? Retry: invalid-number\n2 + 3? Parsed: 5\n"
scripted stdin lines: ["12x","5"]
نزّل المصدر افتح في المحرر
aspl check quiz-input-solution-ar.aspl
aspl run quiz-input-solution-ar.aspl
quiz-input-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

record Question { prompt: string, answer: i64 }
fn start_main() -> i64 {
    let questions: list<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ];
    var pending: bool = true;
    while (pending) {
        print(questions[0]::prompt + " ");
        let line: string = read_line();
        if (line matches "q") {
            print("Stopped early. Correct: 0; answered: 0; total: " + format_i64(length(questions)) + ".\n");
            return 0;
        }
        let parsed: result<i64> = parse_i64(line);
        if (parsed::ok) {
            print("Parsed: " + format_i64(parsed::value) + "\n");
            pending = false;
        } else {
            print("Retry: " + parsed::error::code + "\n");
        }
    }
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "2 + 3? Retry: invalid-number\n2 + 3? Parsed: 5\n"
native: check 0; success / status 0; stdout "2 + 3? Retry: invalid-number\n2 + 3? Parsed: 5\n"
scripted stdin lines: ["12x","5"]
نزّل المصدر افتح في المحرر
aspl check quiz-input-solution-en.aspl
aspl run quiz-input-solution-en.aspl
quiz-score-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

سجل Question { prompt: نص, answer: ص64 }
دالة is_correct(question: Question, answer: ص64) -> منطقي {
    أرجع answer يطابق question::answer.
}
دالة summary(label: نص, correct: ص64, answered: ص64, total: ص64) -> وحدة {
    اطبع(label + ". Correct: " + نسق_ص64(correct) + "; answered: " + نسق_ص64(answered) + "; total: " + نسق_ص64(total) + ".\n").
}
دالة ابدأ_الرئيسية() -> ص64 {
    دع questions: قائمة<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ].
    دع total: ص64 = طول(questions).
    متغير index: ص64 = 0.
    متغير answered: ص64 = 0.
    متغير correct: ص64 = 0.
    اطبع("Quiz: " + نسق_ص64(total) + " questions. Type q to stop.\n").
    طالما (index < total) {
        دع question: Question = questions[index].
        اطبع("Question " + نسق_ص64(index + 1) + "/" + نسق_ص64(total) + ": " + question::prompt + " ").
        دع line: نص = اقرأ_سطر().
        إذا (line يطابق "q") {
            summary("Stopped early", correct, answered, total).
            أرجع 0.
        }
        دع parsed: نتيجة<ص64> = حلل_ص64(line).
        إذا (parsed::نجاح) {
            إذا (is_correct(question, parsed::قيمة)) {
                اطبع("Correct.\n").
                // Add one to correct here.
            } وإلا {
                اطبع("Wrong. Expected " + نسق_ص64(question::answer) + ".\n").
            }
            answered = answered + 1.
            index = index + 1.
        } وإلا {
            اطبع("Retry: " + parsed::الخطأ::الرمز + ". Use ASCII digits, for example 5, or q.\n").
        }
    }
    summary("Completed", correct, answered, total).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 0; answered: 5; total: 5.\n"
native: check 0; success / status 0; stdout "Quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 0; answered: 5; total: 5.\n"
scripted stdin lines: ["5","5","12","4","15"]
نزّل المصدر افتح في المحرر
aspl check quiz-score-ar.aspl
aspl run quiz-score-ar.aspl
quiz-score-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

record Question { prompt: string, answer: i64 }
fn is_correct(question: Question, answer: i64) -> bool {
    return answer matches question::answer;
}
fn summary(label: string, correct: i64, answered: i64, total: i64) -> unit {
    print(label + ". Correct: " + format_i64(correct) + "; answered: " + format_i64(answered) + "; total: " + format_i64(total) + ".\n");
}
fn start_main() -> i64 {
    let questions: list<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ];
    let total: i64 = length(questions);
    var index: i64 = 0;
    var answered: i64 = 0;
    var correct: i64 = 0;
    print("Quiz: " + format_i64(total) + " questions. Type q to stop.\n");
    while (index < total) {
        let question: Question = questions[index];
        print("Question " + format_i64(index + 1) + "/" + format_i64(total) + ": " + question::prompt + " ");
        let line: string = read_line();
        if (line matches "q") {
            summary("Stopped early", correct, answered, total);
            return 0;
        }
        let parsed: result<i64> = parse_i64(line);
        if (parsed::ok) {
            if (is_correct(question, parsed::value)) {
                print("Correct.\n");
                // Add one to correct here.
            } else {
                print("Wrong. Expected " + format_i64(question::answer) + ".\n");
            }
            answered = answered + 1;
            index = index + 1;
        } else {
            print("Retry: " + parsed::error::code + ". Use ASCII digits, for example 5, or q.\n");
        }
    }
    summary("Completed", correct, answered, total);
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 0; answered: 5; total: 5.\n"
native: check 0; success / status 0; stdout "Quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 0; answered: 5; total: 5.\n"
scripted stdin lines: ["5","5","12","4","15"]
نزّل المصدر افتح في المحرر
aspl check quiz-score-en.aspl
aspl run quiz-score-en.aspl
quiz-score-solution-ar · ASPL 0.7.0

المتصفح والمضيف الأصلي

سجل Question { prompt: نص, answer: ص64 }
دالة is_correct(question: Question, answer: ص64) -> منطقي {
    أرجع answer يطابق question::answer.
}
دالة summary(label: نص, correct: ص64, answered: ص64, total: ص64) -> وحدة {
    اطبع(label + ". Correct: " + نسق_ص64(correct) + "; answered: " + نسق_ص64(answered) + "; total: " + نسق_ص64(total) + ".\n").
}
دالة ابدأ_الرئيسية() -> ص64 {
    دع questions: قائمة<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ].
    دع total: ص64 = طول(questions).
    متغير index: ص64 = 0.
    متغير answered: ص64 = 0.
    متغير correct: ص64 = 0.
    اطبع("Quiz: " + نسق_ص64(total) + " questions. Type q to stop.\n").
    طالما (index < total) {
        دع question: Question = questions[index].
        اطبع("Question " + نسق_ص64(index + 1) + "/" + نسق_ص64(total) + ": " + question::prompt + " ").
        دع line: نص = اقرأ_سطر().
        إذا (line يطابق "q") {
            summary("Stopped early", correct, answered, total).
            أرجع 0.
        }
        دع parsed: نتيجة<ص64> = حلل_ص64(line).
        إذا (parsed::نجاح) {
            إذا (is_correct(question, parsed::قيمة)) {
                اطبع("Correct.\n").
                correct = correct + 1.
            } وإلا {
                اطبع("Wrong. Expected " + نسق_ص64(question::answer) + ".\n").
            }
            answered = answered + 1.
            index = index + 1.
        } وإلا {
            اطبع("Retry: " + parsed::الخطأ::الرمز + ". Use ASCII digits, for example 5, or q.\n").
        }
    }
    summary("Completed", correct, answered, total).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 5; answered: 5; total: 5.\n"
native: check 0; success / status 0; stdout "Quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 5; answered: 5; total: 5.\n"
scripted stdin lines: ["5","5","12","4","15"]
نزّل المصدر افتح في المحرر
aspl check quiz-score-solution-ar.aspl
aspl run quiz-score-solution-ar.aspl
quiz-score-solution-en · ASPL 0.7.0

المتصفح والمضيف الأصلي

record Question { prompt: string, answer: i64 }
fn is_correct(question: Question, answer: i64) -> bool {
    return answer matches question::answer;
}
fn summary(label: string, correct: i64, answered: i64, total: i64) -> unit {
    print(label + ". Correct: " + format_i64(correct) + "; answered: " + format_i64(answered) + "; total: " + format_i64(total) + ".\n");
}
fn start_main() -> i64 {
    let questions: list<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ];
    let total: i64 = length(questions);
    var index: i64 = 0;
    var answered: i64 = 0;
    var correct: i64 = 0;
    print("Quiz: " + format_i64(total) + " questions. Type q to stop.\n");
    while (index < total) {
        let question: Question = questions[index];
        print("Question " + format_i64(index + 1) + "/" + format_i64(total) + ": " + question::prompt + " ");
        let line: string = read_line();
        if (line matches "q") {
            summary("Stopped early", correct, answered, total);
            return 0;
        }
        let parsed: result<i64> = parse_i64(line);
        if (parsed::ok) {
            if (is_correct(question, parsed::value)) {
                print("Correct.\n");
                correct = correct + 1;
            } else {
                print("Wrong. Expected " + format_i64(question::answer) + ".\n");
            }
            answered = answered + 1;
            index = index + 1;
        } else {
            print("Retry: " + parsed::error::code + ". Use ASCII digits, for example 5, or q.\n");
        }
    }
    summary("Completed", correct, answered, total);
    return 0;
}

النتائج المتوقعة والخرج الحرفي

browser: check success; success / start_main 0; stdout "Quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 5; answered: 5; total: 5.\n"
native: check 0; success / status 0; stdout "Quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 5; answered: 5; total: 5.\n"
scripted stdin lines: ["5","5","12","4","15"]
نزّل المصدر افتح في المحرر
aspl check quiz-score-solution-en.aspl
aspl run quiz-score-solution-en.aspl
الحدود المعيارية للإصدار

إلى أين تتجه بعد ذلك

اختر خطوتك التالية

يكمل اختبار المتصفح في ملف واحد دورة المبتدئين. التثبيت اختياري. احتفظ بنسخة المتصفح ومسوداتك وأنت تختار ما ستبنيه. لا درجة ولا سجل إكمال ولا درس منته مطلوب لفتح هذه الصفحات.

يمكن للقارئ المتمرس دخول أي دليل عملي أو مرجع اللغة مباشرة. استخدم المتطلبات التالية لاختيار بداية مناسبة.

دروس أصلية اختيارية

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

يأتي نقل الدالة المساعدة إلى وحدة مصدر بعد الدرس المحلي والاختبار المكتمل. يستخدم ملفي مصدر وتصديرا صريحا واستدعاء باسم الوحدة. هذه المصادر للمضيف الأصلي فقط؛ ملفات المتصفح الافتراضية لا تحمل وحدات المصدر.

الأدلة العملية والمرجع

ما الذي تريد بناءه البداية والمتطلبات التنفيذ
تقسيم برنامج إلى ملفات مصدر دليل وحدات المصدر ومرجع الاستيراد والتصدير. افهم الدوال واختر الأدوات الأصلية. المضيف الأصلي فقط.
قراءة النص وكتابته ومعالجة الإخفاق القابل للتعافي دليل الملفات النصية وواجهة الملفات ومرجع النتائج. افهم النصوص وفروع النتائج المتحققة. لملفات المتصفح الافتراضية ومسارات نظام الملفات الأصلي قواعد مختلفة للتجهيز والعمر.
استدعاء مكتبة C متوافقة دليل C ومرجع واجهتها. افهم الدوال والأنواع وثبت ASPL ووفر مكتبة Linux المشتركة المتوافقة المسماة. المضيف الأصلي فقط؛ تصريحات غير آمنة صريحة وتواقيع مدعومة.
بناء عميل HTTP أو خدمة دليل HTTP ومرجع الواجهة والنشر والثقة. افهم السجلات والنتائج والدوال؛ جهز الوحدات الأصلية والنظير أو الشهادات أو مدخلات الثقة التي يطلبها المثال. المضيف الأصلي فقط.
الرسم ومعالجة الإدخال وتشغيل الصوت دليل Raylib ومرجع الواجهة. افهم الحلقات والدوال والسجلات؛ جهز التثبيت الأصلي وسطح مكتب مدعوما وأصول المثال. المضيف الأصلي فقط؛ أمثلة الرسوم والصوت تحتاج أجهزة مناسبة.

يغير تبديل لغة القراءة التوثيق. لا يترجم أسماء المستخدم ولا يتيح مكتبة أصلية في المتصفح ولا يحول ملفات التشغيل إلى وحدات مصدر.

واصل التجربة

عد إلى مسار الدروس عندما تريد تمرينا أصغر، أو تصفح البرامج الكاملة مع تسميات المضيف والتنزيلات المطلوبة. لا تستبدل الدروس الأصلية الاختيارية اختبار المتصفح المكتمل في ملف واحد.

الحدود المعيارية للإصدار

اختياري: التثبيت والتشغيل محليا

ما الذي ستتعلمه

يحفظ هذا الدرس الأصلي الاختياري الاختبار المكتمل في ملف واحد ويفحصه ويشغله محليا باستخدام ASPL 0.7.0. تعرف على الإدخال والإخراج وحالة العملية نفسها مع الاحتفاظ باختبار المتصفح.

قبل أن تبدأ

أكمل اختبار المتصفح أو افهمه، واعرف كيف تفتح الطرفية وتغير المجلد. لا تحتاج دورة المتصفح إلى تثبيت. يمكنك تجاوز هذه الصفحة واختيار خطوات أخرى.

اتبع التثبيت المعتمد

استخدم تنزيلات ابدأ ومتطلبات النظام والتثبيت الأصلي واختيار النسخة. تلك الصفحات هي المرجع للتحقق من الأرشيف والتثبيت واختيار PATH وفحص الإصدار. اختر تنفيذ ASPL 0.7.0 المنشور قبل المتابعة. Console اختياري؛ يستخدم هذا الدرس أداة الطرفية. راجع الفحص والتشغيل والبناء لتفاصيل الأوامر.

احفظ المصدر الكامل

صدّر مسودة اختبارك المكتمل من الرئيسية عبر تصدير المصدر، أو نزّل نسخة مطابقة مما هو متاح أدناه. يحفظ التصدير تعديلاتك الحالية كمصدر UTF-8؛ أما التنزيل المقدم فهو نسخة الفهرس. احفظه باسم quiz.aspl في مجلد محلي جديد واحتفظ بمسودة المتصفح الأصلية. لا تحتاج هذه النسخة ذات الملف الواحد إلى مساعد أو ملف بيانات أو مكتبة أصلية. تحافظ نسختا الكلمات العربية والإنجليزية على أسماء المستخدم نفسها ونصوص الإخراج الإنجليزية. لا تترجم لغة التوثيق ملفك المصدّر.

يعرّف المصدر الكامل سجلات Question الخمسة في قائمة محددة النوع، والدالتين is_correct وsummary والمدخل الجذري. يقرأ سطرا ويتحقق من q الحرفية قبل التحليل ويعيد المحاولة عند خطأ التحليل ويعد كل إجابة رقمية مرة واحدة. يبدأ كل تشغيل بعدادات جديدة؛ لا يحفظ المصدر درجة.

افحص وشغل محليا

افتح الطرفية في المجلد الذي يحتوي quiz.aspl أو انتقل إليه أولا. نفذ هذه الأوامر بالترتيب:

aspl check quiz.aspl
aspl run quiz.aspl
echo $?

لا يطبع الفحص الناجح إخراج الاختبار ويرجع 0 ولا يقرأ الإدخال. يطبع التشغيل المطالبات ويقرأ أسطر الطرفية. أدخل 5 و5 و12 و4 و15 مع Enter بعد كل منها. توقع خمسة أسطر Correct. ثم Completed. Correct: 5; answered: 5; total: 5. وسطر نهاية. تنهي الإجابة الخامسة التشغيل دون قراءة أخرى. يطبع echo $? مباشرة بعد التشغيل 0. هذه حالة العملية وليست الدرجة المطبوعة. تستخدم التشخيصات لغة الأداة المختارة؛ لا تتغير نصوص الإخراج.

توقع المطالبة الأولى والملخص الأخير قبل التشغيل. يتقدم العدد الخاطئ الصالح أيضا؛ يعيد 12x المحاولة؛ وتنهي q الصغيرة الحرفية التشغيل مبكرا بحالة 0. ينهي EOF أثناء الانتظار التنفيذ بفخ input-exhausted مع إبقاء الإخراج السابق، دون ملخص مضمون. قطع العملية المحلية عبر Ctrl+C في الطرفية مقاطعة من المضيف وليس رجوعا عاديا للاختبار؛ يبلغ زر إيقاف المتصفح عن الإلغاء. كلاهما ليس إكمالا للاختبار. يشرح مرجع الإدخال الأصلي stdin وEOF.

مجلد العمل والمسارات

quiz.aspl في الأمر مسار أصلي نسبي إلى مجلد عمل الطرفية الحالي. يعرض pwd ذلك المجلد. تحل عمليات الملفات النصية الأصلية مسارات البيانات النسبية انطلاقا من مجلد عمل العملية أيضا؛ أما استيراد وحدة مصدر فيحل نسبة إلى ملف المصدر المستورِد. يشير المسار الأصلي المطلق إلى موضع في نظام الملفات المحلي.

تسمي أسماء ملفات المتصفح الافتراضية بيانات تشغيل مؤقتة مسطحة في مسودة واحدة. ليست نظام ملفات Linux ولا ملفات المصدر المصدرة ولا محملا لوحدات المصدر. لا ينشئ استيراد ملفات تشغيل المتصفح ملفات محلية؛ يحفظ تنزيل ملف تشغيل أو تصدير المصدر نسخة بطلب صريح. يستخدم الاختبار stdin وstdout ولا يحتاج بيانات ملفات. راجع دليل الملفات النصية قبل إضافة عمليات ملفات أصلية.

عدل رسالة البداية وجرب توقفا مبكرا

في نسخة محفوظة من quiz.aspl، غير نص الإخراج الأول Quiz: فقط إلى Local quiz: . أبق المسافة الأخيرة والعدادات والمساعد وقيم الرجوع. افحص المصدر المعدل ثم شغله. توقع Local quiz: 5 questions. Type q to stop. كأول سطر مع سطر نهاية. يغير تعديل الرسالة النص المطبوع دون العد أو حالة العملية.

في هذا التشغيل المحلي الجديد، أدخل 5 و5 و0 ثم q. توقع إجابتين صحيحتين وثلاث إجابات معدودة. توقع Wrong. Expected 12. بعد العدد الثالث وStopped early. Correct: 2; answered: 3; total: 5. بعد q بحالة 0.

غير رسالة البداية إلى Local quiz: في نسخة من quiz.aspl وافحصها ثم شغل بالأسطر 5 و5 و0 وq. اشرح لماذا لا يغير النص المعدل ولا الدرجة المطبوعة حالة العملية الصفرية.

تلميح: عدل النص في استدعاء print / اطبع الأول مع إبقاء المسافة الأخيرة. نفذ الفحص قبل التشغيل. تتبع correct وanswered منفصلين؛ ترجع q قبل عد السؤال الرابع.

اعرض الإجابة المشروحة

يغير المصدر المعدل الكامل أدناه رسالة البداية فقط إلى Local quiz: 5 questions. Type q to stop. مع سطر نهاية. تزيد الإجابتان الأوليان العدادين. تزيد الثالثة answered فقط وتتقدم. تطبع q Stopped early. Correct: 2; answered: 3; total: 5. وترجع 0. لا الرسالة ولا الدرجة تضبط حالة العملية. لا يطبع الفحص شيئا ويرجع 0؛ ويطبع echo $? مباشرة بعد التشغيل 0 أيضا. ابدأ تشغيلا آخر لتصفير كل العدادات واحتفظ باختبار المتصفح الأصلي دون تغيير.

تحقق من فهمك

اشرح لماذا لا يطبع الفحص مطالبات الاختبار ولماذا لا يحفظ التصدير درجة ولماذا لا يكون اسم ملف المتصفح الافتراضي مسارا أصليا. لا درجة ولا تقدم مخزنا، والتنقل مفتوح. تابع اختياريا إلى وحدات المصدر أو عد إلى اختبار المتصفح في ملف واحد.

quiz-native-ar · ASPL 0.7.0

المضيف الأصلي فقط

سجل Question { prompt: نص, answer: ص64 }
دالة is_correct(question: Question, answer: ص64) -> منطقي {
    أرجع answer يطابق question::answer.
}
دالة summary(label: نص, correct: ص64, answered: ص64, total: ص64) -> وحدة {
    اطبع(label + ". Correct: " + نسق_ص64(correct) + "; answered: " + نسق_ص64(answered) + "; total: " + نسق_ص64(total) + ".\n").
}
دالة ابدأ_الرئيسية() -> ص64 {
    دع questions: قائمة<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ].
    دع total: ص64 = طول(questions).
    متغير index: ص64 = 0.
    متغير answered: ص64 = 0.
    متغير correct: ص64 = 0.
    اطبع("Quiz: " + نسق_ص64(total) + " questions. Type q to stop.\n").
    طالما (index < total) {
        دع question: Question = questions[index].
        اطبع("Question " + نسق_ص64(index + 1) + "/" + نسق_ص64(total) + ": " + question::prompt + " ").
        دع line: نص = اقرأ_سطر().
        إذا (line يطابق "q") {
            summary("Stopped early", correct, answered, total).
            أرجع 0.
        }
        دع parsed: نتيجة<ص64> = حلل_ص64(line).
        إذا (parsed::نجاح) {
            إذا (is_correct(question, parsed::قيمة)) {
                اطبع("Correct.\n").
                correct = correct + 1.
            } وإلا {
                اطبع("Wrong. Expected " + نسق_ص64(question::answer) + ".\n").
            }
            answered = answered + 1.
            index = index + 1.
        } وإلا {
            اطبع("Retry: " + parsed::الخطأ::الرمز + ". Use ASCII digits, for example 5, or q.\n").
        }
    }
    summary("Completed", correct, answered, total).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "Quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 5; answered: 5; total: 5.\n"
scripted stdin lines: ["5","5","12","4","15"]
نزّل المصدر
aspl check quiz-native-ar.aspl
aspl run quiz-native-ar.aspl
quiz-native-en · ASPL 0.7.0

المضيف الأصلي فقط

record Question { prompt: string, answer: i64 }
fn is_correct(question: Question, answer: i64) -> bool {
    return answer matches question::answer;
}
fn summary(label: string, correct: i64, answered: i64, total: i64) -> unit {
    print(label + ". Correct: " + format_i64(correct) + "; answered: " + format_i64(answered) + "; total: " + format_i64(total) + ".\n");
}
fn start_main() -> i64 {
    let questions: list<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ];
    let total: i64 = length(questions);
    var index: i64 = 0;
    var answered: i64 = 0;
    var correct: i64 = 0;
    print("Quiz: " + format_i64(total) + " questions. Type q to stop.\n");
    while (index < total) {
        let question: Question = questions[index];
        print("Question " + format_i64(index + 1) + "/" + format_i64(total) + ": " + question::prompt + " ");
        let line: string = read_line();
        if (line matches "q") {
            summary("Stopped early", correct, answered, total);
            return 0;
        }
        let parsed: result<i64> = parse_i64(line);
        if (parsed::ok) {
            if (is_correct(question, parsed::value)) {
                print("Correct.\n");
                correct = correct + 1;
            } else {
                print("Wrong. Expected " + format_i64(question::answer) + ".\n");
            }
            answered = answered + 1;
            index = index + 1;
        } else {
            print("Retry: " + parsed::error::code + ". Use ASCII digits, for example 5, or q.\n");
        }
    }
    summary("Completed", correct, answered, total);
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "Quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 5; answered: 5; total: 5.\n"
scripted stdin lines: ["5","5","12","4","15"]
نزّل المصدر
aspl check quiz-native-en.aspl
aspl run quiz-native-en.aspl
quiz-native-solution-ar · ASPL 0.7.0

المضيف الأصلي فقط

سجل Question { prompt: نص, answer: ص64 }
دالة is_correct(question: Question, answer: ص64) -> منطقي {
    أرجع answer يطابق question::answer.
}
دالة summary(label: نص, correct: ص64, answered: ص64, total: ص64) -> وحدة {
    اطبع(label + ". Correct: " + نسق_ص64(correct) + "; answered: " + نسق_ص64(answered) + "; total: " + نسق_ص64(total) + ".\n").
}
دالة ابدأ_الرئيسية() -> ص64 {
    دع questions: قائمة<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ].
    دع total: ص64 = طول(questions).
    متغير index: ص64 = 0.
    متغير answered: ص64 = 0.
    متغير correct: ص64 = 0.
    اطبع("Local quiz: " + نسق_ص64(total) + " questions. Type q to stop.\n").
    طالما (index < total) {
        دع question: Question = questions[index].
        اطبع("Question " + نسق_ص64(index + 1) + "/" + نسق_ص64(total) + ": " + question::prompt + " ").
        دع line: نص = اقرأ_سطر().
        إذا (line يطابق "q") {
            summary("Stopped early", correct, answered, total).
            أرجع 0.
        }
        دع parsed: نتيجة<ص64> = حلل_ص64(line).
        إذا (parsed::نجاح) {
            إذا (is_correct(question, parsed::قيمة)) {
                اطبع("Correct.\n").
                correct = correct + 1.
            } وإلا {
                اطبع("Wrong. Expected " + نسق_ص64(question::answer) + ".\n").
            }
            answered = answered + 1.
            index = index + 1.
        } وإلا {
            اطبع("Retry: " + parsed::الخطأ::الرمز + ". Use ASCII digits, for example 5, or q.\n").
        }
    }
    summary("Completed", correct, answered, total).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "Local quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 5; answered: 5; total: 5.\n"
scripted stdin lines: ["5","5","12","4","15"]
نزّل المصدر
aspl check quiz-native-solution-ar.aspl
aspl run quiz-native-solution-ar.aspl
quiz-native-solution-en · ASPL 0.7.0

المضيف الأصلي فقط

record Question { prompt: string, answer: i64 }
fn is_correct(question: Question, answer: i64) -> bool {
    return answer matches question::answer;
}
fn summary(label: string, correct: i64, answered: i64, total: i64) -> unit {
    print(label + ". Correct: " + format_i64(correct) + "; answered: " + format_i64(answered) + "; total: " + format_i64(total) + ".\n");
}
fn start_main() -> i64 {
    let questions: list<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ];
    let total: i64 = length(questions);
    var index: i64 = 0;
    var answered: i64 = 0;
    var correct: i64 = 0;
    print("Local quiz: " + format_i64(total) + " questions. Type q to stop.\n");
    while (index < total) {
        let question: Question = questions[index];
        print("Question " + format_i64(index + 1) + "/" + format_i64(total) + ": " + question::prompt + " ");
        let line: string = read_line();
        if (line matches "q") {
            summary("Stopped early", correct, answered, total);
            return 0;
        }
        let parsed: result<i64> = parse_i64(line);
        if (parsed::ok) {
            if (is_correct(question, parsed::value)) {
                print("Correct.\n");
                correct = correct + 1;
            } else {
                print("Wrong. Expected " + format_i64(question::answer) + ".\n");
            }
            answered = answered + 1;
            index = index + 1;
        } else {
            print("Retry: " + parsed::error::code + ". Use ASCII digits, for example 5, or q.\n");
        }
    }
    summary("Completed", correct, answered, total);
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "Local quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 5; answered: 5; total: 5.\n"
scripted stdin lines: ["5","5","12","4","15"]
نزّل المصدر
aspl check quiz-native-solution-en.aspl
aspl run quiz-native-solution-en.aspl
الحدود المعيارية للإصدار

اختياري: نقل مساعد الاختبار إلى وحدة

ما الذي ستتعلمه

ينقل هذا الدرس الاختياري للمضيف الأصلي فقط دالة فحص الإجابة إلى answers.aspl ويصدرها صراحة ويستدعيها باسم الوحدة answers. احتفظ باختبار المتصفح المكتمل في ملف واحد ومسودته الأصلية.

قبل أن تبدأ

افهم الاختبار المكتمل وأنهِ التثبيت والتشغيل محليا. اختر ASPL 0.7.0 الأصلي. لا يحمل المتصفح وحدات مصدر المستخدم؛ لا تتيح إضافة answers.aspl كملف تشغيل افتراضي الاستيراد. تجد القواعد الأوسع في دليل وحدات المصدر والمرجع.

انقل الدالة المساعدة وصدرها

أبق Question وقائمتها والعدادات والتحليل وsummary في الجذر. عدل is_correct لتأخذ العدد المتوقع بدلا من Question، فلا يحتاج توقيعها العام إلا إلى أنواع قياسية. يمرر الجذر question::answer. احذف الدالة القديمة من الجذر واحفظ هذا المساعد الإنجليزي الكامل باسم answers.aspl:

مقطع توضيحي

share fn is_correct(expected: i64, answer: i64) -> bool {
    return answer matches expected;
}

يقدم المساعد ذو الكلمات العربية العملية نفسها:

مقطع توضيحي

شارك دالة is_correct(expected: ص64, answer: ص64) -> منطقي {
    أرجع answer يطابق expected.
}

التصريحات خاصة افتراضيا. تجعل share / شارك هذه الدالة متاحة للجذر المستورد. تبقى أسماء المستخدم is_correct وexpected وanswer وQuestion وanswers دون تغيير بين لغتي القراءة ونسختي الكلمات المقدمتين.

استورد واستدع من الجذر

في أعلى الجذر، يحمل import answers.aspl as answers; / استورد answers.aspl بسم answers. ملف المصدر نسبة إلى ملف الجذر ويربط نطاق الأسماء answers. استبدل الاستدعاء السابق بـ answers::is_correct(question::answer, parsed::value) / answers::is_correct(question::answer, parsed::قيمة) داخل فرع نجاح التحليل.

لا ينفذ استيراد المصدر أي كود. تعمل الدالة المساعدة فقط عندما يستدعيها الجذر. للجذر وحده start_main / ابدأ_الرئيسية؛ لا مدخل في ملف المساعد. وحدة المصدر ملف مصدر محلي، تختلف عن مكتبة مقدمة مثل core::http وعن بيانات تشغيل المتصفح.

نزّل الجذر وanswers.aspl المطابق أدناه إلى مجلد جديد. افصل النسختين العربية والإنجليزية في مجلدين لأن مساعديهما يحملان الاسم نفسه. يعرض الفهرس هاتين النسختين المقدمتين فقط مع البايتات الدقيقة وهوية المصدر ومرجع الإصدار. لا أصول بيانات. يحافظ الجذر الكامل على الأسئلة الخمسة وسلوك الإدخال والعد في الملف الواحد.

توقع وافحص وشغل

من مجلد الزوج الإنجليزي:

aspl check main.en.aspl
aspl run main.en.aspl
echo $?

للزوج العربي استخدم أوامر الجذر الدقيقة التالية في مجلده المنفصل:

aspl check main.ar.aspl
aspl run main.ar.aspl
echo $?

توقع الإخراج للأسطر 5 و5 و12 و4 و15. ينجح الفحص بحالة 0 دون إخراج؛ يطبع التشغيل خمسة أسطر Correct. ثم Completed. Correct: 5; answered: 5; total: 5. وسطر نهاية بحالة 0، دون قراءة سادسة. مع 12x و6 وq يعيد السؤال الأول المحاولة ويتقدم العدد الخاطئ ويبلغ التوقف المبكر عن صفر صحيح وإجابة معدودة واحدة ومجموع خمسة. يبقى EOF فخ input-exhausted؛ ويبقى إيقاف المتصفح إلغاء في نسخة الملف الواحد. لا يغير نقل المساعد العد ولا مفاهيم الإدخال والإخراج وحالة العملية.

شاهد فشل مرجع خاص

توقع ما يحدث دون share. للزوج الكامل الفاشل المنفصل أدناه الجذر نفسه وis_correct خاصة. احفظه في مجلد مستقل عن الزوج المصدّر. تظهر الملفات المطلوبة قبل مصدر الجذر. يفشل فحصه وتشغيله بحالة 1 وتشخيص private-member دون إخراج للاختبار أو قراءة إدخال.

من مجلد الزوج الإنجليزي الفاشل نفذ aspl check main.en.aspl أو aspl run main.en.aspl؛ ولزوجه العربي استخدم main.ar.aspl. يوجد نطاق الاستيراد لكن answers::is_correct لا يستطيع تسمية عضو خاص. لا يصلح تبديل لغة القراءة الإتاحة.

صدر وأعد المحاولة

أضف share قبل fn is_correct في answers.aspl الفاشل، أو شارك قبل دالة is_correct في مساعده العربي. أبق مرجع الجذر answers::is_correct والوسيطين الرقميين. افحص الجذر مجددا ثم شغل وأدخل 5 و5 و12 و4 و15. توقع الإكمال بخمس إجابات صحيحة وحالة 0 كما في الزوج المصدّر.

أصلح تصدير المساعد الخاص دون تغيير استدعاء الجذر المؤهل باسم الوحدة. اشرح متى تعمل الدالة فعلا.

تلميح: لا يجعل اسم الوحدة التصريحات عامة. أضف share / شارك إلى تصريح المساعد وأبق answers::is_correct ثم افحص الجذر.

اعرض الإجابة المشروحة

يصدر المساعد المصحح is_correct بمعاملين من i64 ونتيجة bool. يمرر الجذر الإجابة المتوقعة في السجل والعدد المحلل عبر answers::is_correct. يفحص الاستيراد التصريح ويتيحه دون استدعاء أو قراءة إدخال. ينفذ الاستدعاء الصريح في فرع نجاح التحليل الدالة المساعدة. ينجح فحص الزوج المصدّر الكامل أدناه ويحافظ على إخراج الاختبار وحالته.

تحقق من فهمك

اشرح لماذا يبقى السجل خاصا في الجذر ولماذا يستخدم المساعد عددين ولماذا لا يتيح اسم الوحدة وحده تصريحا خاصا ولماذا لا يشغل الاستيراد الاختبار. لا درجة ولا تقدم مخزنا، والتنقل مفتوح. عد إلى الخطوات التالية أو نسخة المتصفح في ملف واحد.

quiz-modules-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد answers.aspl بسم answers.
سجل Question { prompt: نص, answer: ص64 }
دالة summary(label: نص, correct: ص64, answered: ص64, total: ص64) -> وحدة {
    اطبع(label + ". Correct: " + نسق_ص64(correct) + "; answered: " + نسق_ص64(answered) + "; total: " + نسق_ص64(total) + ".\n").
}
دالة ابدأ_الرئيسية() -> ص64 {
    دع questions: قائمة<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ].
    دع total: ص64 = طول(questions).
    متغير index: ص64 = 0.
    متغير answered: ص64 = 0.
    متغير correct: ص64 = 0.
    اطبع("Quiz: " + نسق_ص64(total) + " questions. Type q to stop.\n").
    طالما (index < total) {
        دع question: Question = questions[index].
        اطبع("Question " + نسق_ص64(index + 1) + "/" + نسق_ص64(total) + ": " + question::prompt + " ").
        دع line: نص = اقرأ_سطر().
        إذا (line يطابق "q") {
            summary("Stopped early", correct, answered, total).
            أرجع 0.
        }
        دع parsed: نتيجة<ص64> = حلل_ص64(line).
        إذا (parsed::نجاح) {
            إذا (answers::is_correct(question::answer, parsed::قيمة)) {
                اطبع("Correct.\n").
                correct = correct + 1.
            } وإلا {
                اطبع("Wrong. Expected " + نسق_ص64(question::answer) + ".\n").
            }
            answered = answered + 1.
            index = index + 1.
        } وإلا {
            اطبع("Retry: " + parsed::الخطأ::الرمز + ". Use ASCII digits, for example 5, or q.\n").
        }
    }
    summary("Completed", correct, answered, total).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "Quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 5; answered: 5; total: 5.\n"
scripted stdin lines: ["5","5","12","4","15"]
نزّل المصدر
aspl check quiz-modules-ar.aspl
aspl run quiz-modules-ar.aspl
quiz-modules-en · ASPL 0.7.0

المضيف الأصلي فقط

import answers.aspl as answers;
record Question { prompt: string, answer: i64 }
fn summary(label: string, correct: i64, answered: i64, total: i64) -> unit {
    print(label + ". Correct: " + format_i64(correct) + "; answered: " + format_i64(answered) + "; total: " + format_i64(total) + ".\n");
}
fn start_main() -> i64 {
    let questions: list<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ];
    let total: i64 = length(questions);
    var index: i64 = 0;
    var answered: i64 = 0;
    var correct: i64 = 0;
    print("Quiz: " + format_i64(total) + " questions. Type q to stop.\n");
    while (index < total) {
        let question: Question = questions[index];
        print("Question " + format_i64(index + 1) + "/" + format_i64(total) + ": " + question::prompt + " ");
        let line: string = read_line();
        if (line matches "q") {
            summary("Stopped early", correct, answered, total);
            return 0;
        }
        let parsed: result<i64> = parse_i64(line);
        if (parsed::ok) {
            if (answers::is_correct(question::answer, parsed::value)) {
                print("Correct.\n");
                correct = correct + 1;
            } else {
                print("Wrong. Expected " + format_i64(question::answer) + ".\n");
            }
            answered = answered + 1;
            index = index + 1;
        } else {
            print("Retry: " + parsed::error::code + ". Use ASCII digits, for example 5, or q.\n");
        }
    }
    summary("Completed", correct, answered, total);
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 0; success / status 0; stdout "Quiz: 5 questions. Type q to stop.\nQuestion 1/5: 2 + 3? Correct.\nQuestion 2/5: 9 - 4? Correct.\nQuestion 3/5: 3 * 4? Correct.\nQuestion 4/5: 12 / 3? Correct.\nQuestion 5/5: 7 + 8? Correct.\nCompleted. Correct: 5; answered: 5; total: 5.\n"
scripted stdin lines: ["5","5","12","4","15"]
نزّل المصدر
aspl check quiz-modules-en.aspl
aspl run quiz-modules-en.aspl
quiz-modules-private-ar · ASPL 0.7.0

المضيف الأصلي فقط

استورد answers.aspl بسم answers.
سجل Question { prompt: نص, answer: ص64 }
دالة summary(label: نص, correct: ص64, answered: ص64, total: ص64) -> وحدة {
    اطبع(label + ". Correct: " + نسق_ص64(correct) + "; answered: " + نسق_ص64(answered) + "; total: " + نسق_ص64(total) + ".\n").
}
دالة ابدأ_الرئيسية() -> ص64 {
    دع questions: قائمة<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ].
    دع total: ص64 = طول(questions).
    متغير index: ص64 = 0.
    متغير answered: ص64 = 0.
    متغير correct: ص64 = 0.
    اطبع("Quiz: " + نسق_ص64(total) + " questions. Type q to stop.\n").
    طالما (index < total) {
        دع question: Question = questions[index].
        اطبع("Question " + نسق_ص64(index + 1) + "/" + نسق_ص64(total) + ": " + question::prompt + " ").
        دع line: نص = اقرأ_سطر().
        إذا (line يطابق "q") {
            summary("Stopped early", correct, answered, total).
            أرجع 0.
        }
        دع parsed: نتيجة<ص64> = حلل_ص64(line).
        إذا (parsed::نجاح) {
            إذا (answers::is_correct(question::answer, parsed::قيمة)) {
                اطبع("Correct.\n").
                correct = correct + 1.
            } وإلا {
                اطبع("Wrong. Expected " + نسق_ص64(question::answer) + ".\n").
            }
            answered = answered + 1.
            index = index + 1.
        } وإلا {
            اطبع("Retry: " + parsed::الخطأ::الرمز + ". Use ASCII digits, for example 5, or q.\n").
        }
    }
    summary("Completed", correct, answered, total).
    أرجع 0.
}

النتائج المتوقعة والخرج الحرفي

native: check 1; source-error / status 1 / private-member; stdout ""
نزّل المصدر
aspl check quiz-modules-private-ar.aspl
quiz-modules-private-en · ASPL 0.7.0

المضيف الأصلي فقط

import answers.aspl as answers;
record Question { prompt: string, answer: i64 }
fn summary(label: string, correct: i64, answered: i64, total: i64) -> unit {
    print(label + ". Correct: " + format_i64(correct) + "; answered: " + format_i64(answered) + "; total: " + format_i64(total) + ".\n");
}
fn start_main() -> i64 {
    let questions: list<Question> = [
        Question { prompt: "2 + 3?", answer: 5 },
        Question { prompt: "9 - 4?", answer: 5 },
        Question { prompt: "3 * 4?", answer: 12 },
        Question { prompt: "12 / 3?", answer: 4 },
        Question { prompt: "7 + 8?", answer: 15 }
    ];
    let total: i64 = length(questions);
    var index: i64 = 0;
    var answered: i64 = 0;
    var correct: i64 = 0;
    print("Quiz: " + format_i64(total) + " questions. Type q to stop.\n");
    while (index < total) {
        let question: Question = questions[index];
        print("Question " + format_i64(index + 1) + "/" + format_i64(total) + ": " + question::prompt + " ");
        let line: string = read_line();
        if (line matches "q") {
            summary("Stopped early", correct, answered, total);
            return 0;
        }
        let parsed: result<i64> = parse_i64(line);
        if (parsed::ok) {
            if (answers::is_correct(question::answer, parsed::value)) {
                print("Correct.\n");
                correct = correct + 1;
            } else {
                print("Wrong. Expected " + format_i64(question::answer) + ".\n");
            }
            answered = answered + 1;
            index = index + 1;
        } else {
            print("Retry: " + parsed::error::code + ". Use ASCII digits, for example 5, or q.\n");
        }
    }
    summary("Completed", correct, answered, total);
    return 0;
}

النتائج المتوقعة والخرج الحرفي

native: check 1; source-error / status 1 / private-member; stdout ""
نزّل المصدر
aspl check quiz-modules-private-en.aspl
الحدود المعيارية للإصدار

أمثلة إضافية

اعرف حدود C

تواقيع C والمخازن وإعارة النص

المضيف وعقد التصريح

المضيف الأصلي فقط، إصدار ASPL 0.7.0 المنشور على Linux x86-64 مع glibc وSystem V ABI. ثبّت الأداة الأصلية وافحص متطلبات النظام ثم اتبع دليل C والأمثلة العامة. يرفض المتصفح الاستيرادات الخارجية قبل التنفيذ بالسبب foreign-imports-not-supported حتى إن لم تستخدم.

التصريح الخارجي على المستوى الأعلى ويربط اسم ASPL وتوقيعه باسم مكتبة مشتركة حرفي واسم رمز C حرفي وتوقيع ثابت مدعوم أو ملف تعريف محوّل خارجي. يجب أن تكون الأسماء غير فارغة وخالية من NUL. يرفض تكرار زوج المكتبة والرمز. ضع غير_آمن / unsafe على التصريح وكل استدعاء؛ لا توجد كتلة غير آمنة تلغي وسم كل استدعاء. التصريحات الخارجية خاصة افتراضيا ويمكن تصديرها باستخدام شارك / share في وحدات المصدر الأصلية. لا تصبح قيما عادية قابلة للاستدعاء.

مقطع توضيحي

غير_آمن خارجي absolute(value: ص32) -> ص32 = سي("libc.so.6", "abs");
دالة ابدأ_الرئيسية() -> ص64 {
    إذا غير_آمن absolute(ص32(-7)) ليس يطابق ص32(7) { أرجع 1; }
    أرجع 0;
}

على الكاتب مطابقة توقيع C الحقيقي وضمان صلاحية المؤشر وسلوك المكتبة. لا يحلل ASPL ترويسات C ولا يستنتج التوقيع من الرمز ولا يفحص errno ولا يحول إخفاقات المكتبة إلى نتائج ASPL تلقائيا.

التواقيع الثابتة وملفات التعريف المدعومة

يشتق سي / c التوقيع الثابت الدقيق من أنواع المصدر، من صفر إلى 32 معاملا أصليا. لا تضيف البيانات الوصفية معاملات C. لا توجد تحويلات عددية ضمنية؛ استخدم التحويل الصريح للمعامل ذي العرض المختلف.

نوع ASPL أو وصفه تمثيل C في هذا الهدف
منطقي / bool _Bool بحجم بايت واحد
ص8 / i8، ط8 / u8 عدد موقع أو غير موقع من 8 بت
ص16 / i16، ط16 / u16 عدد موقع أو غير موقع من 16 بت
ص32 / i32، ط32 / u32 عدد موقع أو غير موقع من 32 بت
ص64 / i64، ط64 / u64 عدد موقع أو غير موقع من 64 بت
ع32 / f32، ع64 / f64 float وdouble
مؤشر_سي / c_ptr مؤشر C معتم قابل لعدم وغير مملوك
وحدة / unit في النتيجة فقط C void
نص مع نص_سي(parameter) / cstring(parameter) إعارة const char * طوال الاستدعاء
سي::مخزن مع وصف مدى مؤشر إلى بايتات يملكها وقت التشغيل

نوع C char موقع هنا؛ وshort من 16 بت وint من 32 بت وlong وlong long والمؤشرات وsize_t من 64 بت. استخدم النوع الحقيقي الأساسي لـtypedef وenum. لا يوفر مؤشر_سي تحويل عنوان ولا يكشف تخزين مالك مدار كمؤشر خام. تستخدم قيمة المؤشر الفارغ عدم / null.

لا تدعم التواقيع متغيرة المعاملات أو المجاميع بالقيمة في المعامل أو النتيجة أو long double أو الأعداد المركبة أو مؤشرات الدوال الخام أو استيراد متغيرات C العامة. لا تعبر القوائم والسجلات والنتائج والقيم العادية القابلة للاستدعاء كقيم C عامة. يحتاج النص إلى وصف إعارة، والمخزن إلى وصف مدى واحد؛ ولا يصلح أي منهما كنوع نتيجة خارجية عامة.

ملف تعريف المحوّل الخارجي توقيع ASPL الدقيق نوع C الدقيق
سي_صحيح__مؤشر_محرف_ثابت / c_int__const_char_ptr (نص) -> ص64 / (string) -> i64 int (*)(const char *)
سي_مزدوج__مزدوج / c_double__double (ع64) -> ع64 / (f64) -> f64 double (*)(double)

تحتفظ الملفات بتحويلاتها الأصلية. ينسخ الأول نص C ويحول نتيجة C int بالقيمة إلى ص64؛ وتبقى النتيجة السالبة بيانات عادية. يمرر الثاني قيم binary64 ويطبّع NaN المعادة ويستعيد بيئة الحساب العائم. لا يفحص أي منهما أعلام استثناءات الحساب العائم أو errno. لا توسع هذه التحويلات تواقيع c العامة. يختبر مثالا puts وdouble المحوّلين؛ ويختبر المثال العادي التواقيع الثابتة.

إعارة نص C

في سي العام ضع نص_سي(text) / cstring(text) على معامل النص. يقيّم ASPL المعاملات ويرفض NUL الداخلي قبل دخول C وينسخ بايتات UTF-8 ويضيف فاصلة NUL. ينفذ المحوّل c_int__const_char_ptr الإعارة نفسها دون وصف صريح. تصح الإعارة طوال الاستدعاء فقط. يجوز لـC قراءتها أثناءه ولا يجوز تعديلها أو الاحتفاظ بمؤشرها بعد العودة. يختلف طولها بالبايتات عن عدد محارف Unicode.

يصبح النص الفارغ بايت النهاية فقط. يسبب NUL الداخلي فخا بالسبب foreign-string-contains-nul في ملف تعريف النص الأصلي وبالسبب invalid-foreign-argument في cstring العام؛ ويعطي فشل التخصيص نتيجة مضيف أو مورد لا رمز إرجاع من المكتبة. لا يمنع فحص العمر C من الاحتفاظ بالمؤشر أو إساءة استخدامه. انهيار الدالة الخارجية خارج ضمانات الفخ المنضبط في ASPL.

عمليات المخزن

استورد أساسي::سي أو core::c. تتاح البادئة المكتوبة فقط. النوع مخزن / Buffer وعملياته المقترنة هي:

العضو الإنجليزي / العربي التوقيع بأنواع إنجليزية
buffer / أنشئ_مخزن (list<u8>) -> result<Buffer>
zero_buffer / أنشئ_مخزن_صفري (u64) -> result<Buffer>
capacity / سعة (Buffer) -> result<u64>
bytes / انسخ_بايتات (Buffer, u64) -> result<list<u8>>
close / أغلق (Buffer) -> result<unit>

ينسخ buffer البايتات بما فيها NUL وFF؛ ويخصص zero_buffer بايتات مصفرة. ينسخ bytes البادئة المطلوبة إلى قائمة جديدة ويرفض العدد الأكبر من السعة بالرمز foreign.invalid_argument. تبقى القوائم والتخزين الأصلي مستقلين. تتشارك نسخ المخزن مالكا أصليا واحدا. يبطل إغلاق نسخة كل النسخ؛ وينجح الإغلاق المتكرر. يعيد الوصول إلى مخزن مغلق foreign.closed. قد يعيد الوصول أثناء الاستخدام الأصلي foreign.busy.

قد يرفض الإنشاء السعة المحاسبة التي تتجاوز ميزانية ذاكرة التنفيذ بالرمز foreign.resource_limit. يجب أن تلائم القوائم المستخرجة طولها القابل للتمثيل وحجم التخصيص. للمخزن ذي السعة صفر بايت sentinel واحد محاسب. هذه حالات رفض قابلة للاسترداد؛ لكن فشل التخصيص أو استنفاد الموارد أثناء إنشاء نتيجة قد ينهي التنفيذ. افحص ok قبل الوصول إلى أحد فرعي النتيجة. لا تحتوي result<unit> قيمة value قابلة للقراءة.

يحتفظ الوصول الأصلي بالتخزين المحاسب حتى السكون. تحرر نهاية المراجع وتنظيف التنفيذ المالكين الأصليين، بما في ذلك دورات الملكية غير القابلة للوصول. يشارك الإسناد التخزين الأصلي ولا يستنسخه. يفحص مثال المخزن نسخ البايتات والنسخ المشتركة والاستخراج الأكبر من السعة والإغلاق المتكرر.

مديات البايتات الخارجية

ضع وصفا واحدا لكل معامل مخزن باستخدام إدخال(buffer,count) / input أو إخراج / output أو إدخال_وإخراج / inout. العدد قيمة حرفية غير سالبة أو قيمة معامل من أي نوع عدد صحيح مدعوم، غير سالبة وضمن السعة. هو معامل مصدر موجود إذا احتاجه توقيع C؛ ولا يضيف الوصف معاملا.

يوفر الإدخال بايتات قابلة للقراءة. يصفر الإخراج المدى المحدد قبل دخول C. يحافظ الإدخال والإخراج على البايتات للقراءة والكتابة. لا تتراجع الكتابات عند نتيجة C سالبة. يستخدم المدى الفارغ مؤشر sentinel صالحا. تقبل نسخ القراءة فقط، لكن تمرير مالك مخزن واحد إلى معاملات متعددة يسبب فخا إن كان أي منها قابلا للكتابة، حتى مع مدى فارغ. تسبب الأعداد السالبة أو الزائدة والمخازن المغلقة أو المشغولة والنسخ القابلة للكتابة فخا قبل دخول C. يجوز لـC الوصول إلى المدى المحدد أثناء الاستدعاء ولا يجوز الاحتفاظ بمؤشره بعد العودة. لا تثبت هذه الفحوص التزام C بتلك القواعد.

التحميل والإخفاقات وحدود الإدارة

يفحص check وbuild دون تحميل مكتبات مشتركة. يجهز run وبرنامج ELF المولد كل الاستيرادات قبل دالة البداية، بما فيها غير المستخدمة، بترتيب بايتات المكتبة ثم الرمز ثم معرّف المحوّل. يفتح كل اسم مكتبة حرفي مرة واحدة باستخدام RTLD_NOW | RTLD_LOCAL ثم يحل الرموز بواسطة dlsym وdlerror. تمر الأسماء دون تغيير إلى محمّل glibc. يمنع الفشل الأول البداية ويغلق المقابض المفتوحة بترتيب عكسي. تظل البرامج المبنية محتاجة إلى المكتبات المسماة، رغم عدم حاجتها إلى المترجم أو ملفات المصدر.

الإخفاق النتيجة المشاهدة
محوّل مجهول أو توقيع غير مطابق أو اسم غير صالح أو هدف مكرر أو غياب وسم عدم الأمان خطأ مصدر بحالة CLI 1: unknown-foreign-adapter، foreign-signature-mismatch، invalid-foreign-library-name، invalid-foreign-symbol-name، duplicate-foreign-target، unsafe-required-on-foreign-declaration، unsafe-required-on-foreign-call
غياب مكتبة أو رمز فشل تحميل بالحالة 4: foreign-library-open-failed، foreign-symbol-lookup-failed
نص NUL أو مدى غير صالح أو مخزن مغلق أو مشغول أو نسخ قابلة للكتابة فخ بالحالة 5: foreign-string-contains-nul، invalid-foreign-argument، closed-foreign-handle، busy-foreign-buffer، aliased-foreign-buffer
رفض أداة مخزن نتيجة فاشلة: foreign.invalid_argument، foreign.closed، foreign.busy، foreign.resource_limit
فشل تخصيص أو ميزانية تنفيذ نتيجة مضيف أو مورد، لا تحويل تلقائي لنتيجة C إلى نتيجة فاشلة

الاستدعاءات العادية غير الآمنة متزامنة وقد تحجب التنفيذ ولا تكتسب امتيازات التعليق أو الإلغاء أو الاستدعاءات الراجعة المدارة. تستبعدها معالجات HTTP والاستدعاءات الراجعة المدارة عبر كل مسارات الاستدعاء. تشارك الروابط المراجعة الموردة مع الأداة فقط في قواعد الإدارة؛ وتشمل المكتبات العامة الحالية HTTP وRaylib. لا تستطيع تصريحات المستخدم تسجيل عمليات مدارة ولا توجد ABI عامة مستقلة لتثبيت روابط مدارة. ليست تجهيزات اختبار الاستدعاءات الراجعة الخاصة بالمساهمين أمثلة عامة قابلة للتشغيل. راجع مجموعتي HTTP وRaylib لعقد كل منهما.

الحدود المعيارية للإصدار

انتقل إلى Linux

متطلبات النظام

مضيف ASPL 0.7.0 الأصلي

يستهدف الأرشيف المنشور Linux بمعمارية x86-64 الأساسية وglibc 2.34 أو أحدث. محمله /lib64/ld-linux-x86-64.so.2، واعتمادا ELF المباشران للأداة هما libm.so.6 وlibc.so.6. ليس حزمة لـmusl أو ARM أو Windows أو macOS. يحتوي الملف التنفيذي المترجم ووقت التشغيل والقوالب الأصلية، ولذلك لا يتطلب الفحص والتشغيل والبناء المعتاد مترجم C أو رابطا أو ترويسات تطوير.

uname -m
getconf GNU_LIBC_VERSION

توقع x86_64 وإصدار glibc لا يقل عن 2.34. لا تثبت هذه الفحوص المكتبات المفقودة. افحص سجل الاعتمادات الأصلي لمعرفة بناء الإصدار وتفاصيل قوالبه. تحتاج إلى tar بدعم xz وsha256sum من أجل التثبيت المتحقق منه.

اعتمادات البرنامج الخاصة

يعمل البرنامج المبني دون ASPL، لكنه يظل بحاجة إلى محمل Linux ومكتبات التشغيل. يستخدم البرنامج الأساسي libc وlibm. تتطلب الاستدعاءات الخارجية مكتباتها المشتركة المسماة عند التنفيذ. تتضمن الأداة دعم HTTP الأصلي؛ ويتطلب HTTPS أيضا إعداد ثقة صالحا للشهادات. تحتاج برامج Raylib إلى نظام رسوم ونوافذ مناسب، وإلى دعم الصوت عند استعماله. يحدد سجل الاعتمادات متطلبات كل قالب؛ لا تستنتج جميع اعتمادات الرسوم من مكتبتي الأداة الأساسية.

تتطلب استيرادات وحدات المصدر ملفاتها أثناء الفحص والتشغيل والبناء. تحتوي البرامج المبنية الوحدات المترجمة. تبقى ملفات بيانات التنفيذ خارجية ما لم يوفر البرنامج محتواها بنفسه. تستخدم عمليات الملفات الأصلية دليل عمل العملية.

مضيف Console الاختياري

Console 0.7.0 تطبيق Qt مكتبي منفصل لنظام Linux x86-64. يتطلب Qt 6.11 أو أحدث من النظام، ومكتبات OpenGL ووقت تشغيل C++، وإضافة منصة Qt لسطح المكتب وخطا يدعم العربية. لا يتضمن Qt ولا يضمن الحد المستقل glibc 2.34 الخاص بـASPL. يسمي README المنشور الحزم qt6-base وqt6-wayland وnoto-fonts على Arch Linux أو Omarchy الحاليين. يجب أن توفر التوزيعات الأخرى الحزم المتوافقة بأسمائها الخاصة.

ثبت ASPL 0.7.0 منفصلا واختره بخيار Console المسمى --aspl. راجع تثبيت Console وفحوصه وبيانات إصداره الأصلية. لا يحتاج ملعب المتصفح أيا من الأرشيفين، ولا يستطيع تنفيذ برامج ELF أو مكتبات المضيف الأصلي.

الحدود المعيارية للإصدار

التنزيلات وسجل الإصدارات

تنزيلات الإصدار المختار

هذه مدخلات ASPL 0.7.0 المنشورة الأصلية. يحفظ الموقع بايتاتها ولا يعيد بناءها أو تغليفها. اختر المضيف المتوافق، ثم اتبع تعليمات التثبيت الأصلي المعتمدة أو تثبيت Console المنفصل.

المكون الأرشيف التحقق
ASPL 0.7.0 الأصلي، Linux x86-64 تنزيل الأرشيف الأصلي تنزيل SHA256SUMS الأصلي
Console 0.7.0 الاختياري، Linux x86-64 تنزيل أرشيف Console تنزيل SHA256SUMS الخاص بـConsole

لكل ملف بصمات أرشيفه الخاص. احتفظ بتنزيلات الأداة وConsole في مجلدين منفصلين لأن اسم كلا الملفين SHA256SUMS. تحقق بأمر sha256sum --check SHA256SUMS قبل الاستخراج. يجب إيقاف التثبيت عند اختلاف البصمة أو تلف الأرشيف.

الاعتمادات والبيانات الوصفية والرخص

مدخلات الأداة الأصلية: تنزيل DEPENDENCIES.json، وتنزيل رخصة MIT، وتنزيل رخصة Apache، وتنزيل إشعارات الأطراف الثالثة. يصف سجل الاعتمادات المحمل والحد الأدنى لـglibc واعتمادات التشغيل وبايت الكود الخاص والمكونات المضمنة. ترافق هذه الملفات الأداة التنفيذية داخل الأرشيف أيضا.

مدخلات Console: تنزيل README الأصلي، وتنزيل بيانات الإصدار، وتنزيل رخصة MIT، وتنزيل رخصة Apache، وتنزيل إشعارات الأطراف الثالثة. يستخدم Console نسخة Qt في النظام ولا يضمن نسخة منها في الأرشيف. تحدد بياناته أرشيفه وملفاته والحد الأدنى لإصدار Qt.

توافق المضيف

تتطلب الأداة الأصلية Linux x86-64 وglibc 2.34 أو أحدث. لـConsole متطلبات Qt وسطح مكتب منفصلة ولا يضمن الحد نفسه لـglibc. لا يمثل أي من الأرشيفين نسخة لنظام Windows أو macOS أو ARM أو musl. راجع المتطلبات الكاملة وفحوص المضيف.

المسارات الثابتة وسجل الإصدارات

للسكربت أو سجل التثبيت المرتبط بإصدار محدد، استخدم هذه المسارات الثابتة:

يسرد فهرس الإصدارات المنشور (يفتح في نافذة جديدة) الإصدارات 0.1.1 و0.2.0 و0.3.0 و0.4.0 و0.5.0 و0.6.0 و0.7.0، ويوصي بـ0.7.0. تتاح اللقطات العربية المجمدة للإصدارات 0.1.1 (يفتح في نافذة جديدة) و0.2.0 (يفتح في نافذة جديدة) و0.3.0 (يفتح في نافذة جديدة) و0.4.0 (يفتح في نافذة جديدة) و0.5.0 (يفتح في نافذة جديدة) و0.6.0 (يفتح في نافذة جديدة) و0.7.0 (يفتح في نافذة جديدة). تحتفظ كل لقطة بمتطلباتها وحدودها. تنطبق تعليمات التثبيت الحالية على 0.7.0 ولا تنطبق تلقائيا على الإصدارات السابقة. انظر الترقية والرجوع للأداة الأصلية.

الحدود المعيارية للإصدار

أول برنامج أصلي

اختيار الأداة والتحقق منها

يفترض هذا المسار أنك تستخدم الطرفية بالفعل، ولا يتطلب إكمال دروس المبتدئين. تحقق أولا من متطلبات النظام. تختار هذه التعليمات ASPL 0.7.0 لنظام Linux بمعمارية x86-64. أما Console فهو اختياري ومنفصل.

نزّل أرشيف الأداة الأصلية وملف SHA256SUMS الخاص به في مجلد جديد. تحقق قبل الاستخراج أو التنفيذ، وتوقف عند اختلاف البصمة أو خطأ الأرشيف. تكشف البصمة اختلاف البايتات، لكن تنزيلها من الموقع نفسه لا يجعلها توقيعا مستقلا للناشر.

sha256sum --check SHA256SUMS &&
tar -tJf aspl-0.7.0-x86_64-linux-gnu.tar.xz &&
tar -xJf aspl-0.7.0-x86_64-linux-gnu.tar.xz

يحتوي الأرشيف مجلدا واحدا باسم aspl-0.7.0-x86_64-linux-gnu/ فيه aspl وDEPENDENCIES.json والرخصتان وTHIRD-PARTY-NOTICES. لا يوجد سكربت تثبيت. احتفظ بهذه الملفات معا في مجلد مستخدم خاص بالإصدار، ثم اختر الملف التنفيذي بوصلة رمزية. إذا كان ~/.local/bin/aspl موجودا، فافحصه قبل استبداله.

mkdir -p "$HOME/.local/opt" "$HOME/.local/bin"
mv aspl-0.7.0-x86_64-linux-gnu "$HOME/.local/opt/"
ln -s "$HOME/.local/opt/aspl-0.7.0-x86_64-linux-gnu/aspl" "$HOME/.local/bin/aspl"
export PATH="$HOME/.local/bin:$PATH"
hash -r

نفذ ذلك مرة واحدة للإصدار المختار. افحص مجلد الإصدار الموجود بدلا من الكتابة فوقه. أضف سطر export PATH مرة واحدة إلى ملف بدء الصدفة إذا أردت استعماله في الطرفيات اللاحقة.

التحقق من التثبيت المختار

command -v aspl
aspl --version
aspl --diagnostic-language=en --help

يجب أن يشير الأمر الأول إلى تثبيت المستخدم المختار، وأن يكون الإصدار aspl 0.7.0. إذا اختير تثبيت آخر، فافحص ترتيب PATH وامسح ذاكرة أوامر الصدفة. عند فقد المحمل أو مكتبة مشتركة، راجع متطلبات المضيف بدلا من اعتباره خطأ في المصدر. العربية هي لغة التشخيص الافتراضية؛ يغير --diagnostic-language=en التشخيصات دون المصدر أو الخرج.

حفظ برنامج أول كامل

نزّل إحدى صيغ المصدر المتاحة أدناه واحفظها باسم hello.aspl، ثم اتبع مسار الفحص والتشغيل والبناء. يعيد برنامج Hello المعتمد حالة صفر ولا يطبع شيئا. طباعة النص وإرجاع حالة العملية عمليتان منفصلتان.

الترقية والرجوع وإلغاء التثبيت

للترقية، اختر إصدارا منشورا من سجل الإصدارات. اقرأ متطلباته، وتحقق من أرشيفه وبصماته الخاصة، واستخرجه في مجلد إصدار منفصل. اختبر مساره التنفيذي المطلق على مصدرك بأوامر --version وcheck وrun وbuild قبل اختياره. احتفظ بالمجلد السابق ونسخ المصدر الاحتياطية.

لاختيار مجلد 0.7.0 المتحقق منه مجددا في Bash:

ln -sfn "$HOME/.local/opt/aspl-0.7.0-x86_64-linux-gnu/aspl" "$HOME/.local/bin/aspl"
hash -r
command -v aspl
aspl --version

يغير الرجوع إلى إصدار أصلي هذه الوصلة إلى ملف تنفيذي أصلي سابق احتفظت به. استبدل المسار بمجلد الإصدار السابق المتحقق منه وافحص الإصدار وتوافق المصدر. لا يعيد ذلك كتابة البرامج التي بنيت بإصدار آخر. تستعيد حزمة استعادة موقع ASPL تقديم الموقع وأصوله المحتفظ بها، ولا ترجع الأداة الأصلية المثبتة على جهازك.

لإلغاء هذا التثبيت، تحقق أولا من هدف الوصلة بأمر readlink "$HOME/.local/bin/aspl". احذف الوصلة ومجلد الإصدار المحدد فقط إذا كانا التثبيت المقصود:

rm "$HOME/.local/bin/aspl"
rm -r "$HOME/.local/opt/aspl-0.7.0-x86_64-linux-gnu"
hash -r
command -v aspl

احذف سطر PATH من ملف بدء الصدفة فقط إذا لم تستخدم أدوات أخرى ذلك المجلد. تبقى ملفات المصدر والبرامج المبنية قابلة للاستعمال. ولـConsole خطوات إلغاء مستقلة.

الحدود المعيارية للإصدار

الفحص والتشغيل والبناء

فحص المصدر دون تشغيله

بعد تثبيت الأداة الأصلية المتحقق منها، احفظ مصدر Hello المعتمد باسم hello.aspl. تقبل الأوامر ملف مصدر جذريا واحدا ينتهي بـ.aspl أو .لبات مع وحدات المصدر المستوردة صراحة. يوفر الإدخال القياسي بيانات البرنامج ولا يوفر مصدره.

aspl --diagnostic-language=en check hello.aspl

يترجم check المصدر ويتحقق منه دون تنفيذه أو قراءة إدخال البرنامج أو تحميل المكتبات الخارجية أو كتابة برنامج. الفحص الناجح صامت ويعيد صفرا. لا يثبت الفحص أن التنفيذ سينجح.

التشغيل وفحص حالة العملية

aspl run hello.aspl
printf 'status=%s\n' "$?"

لا يطبع Hello شيئا ويعيد صفرا. لرؤية خرج عادي، نزّل صيغة مصدر من مثال الجمع باسم sum.aspl. يطبع aspl run sum.aspl النص 55 متبوعا بسطر جديد ويعيد صفرا. تكتب print في stdout. يحدد العدد الصحيح الذي تعيده ابدأ_الرئيسية حالة العملية ولا يطبعها. اقرأ $? مباشرة بعد الأمر الذي تقيسه.

تتراوح نتيجة دالة البداية العادية من 0 إلى 255. النتيجة غير الصفرية مسموحة، أما النتيجة خارج المجال فتسبب فخ invalid-process-status. تستخدم حالات الفشل جدول حالات الأوامر، ولذلك لا يكفي رقم الحالة وحده لتمييز نتيجة عادية عن فشل تنفيذ. اقرأ stderr أيضا.

البناء وتنفيذ برنامج مستقل

aspl build -o hello hello.aspl
./hello
printf 'status=%s\n' "$?"

ضع -o قبل مسار المصدر. يترجم build البرنامج ويتحقق منه وينشر ملف ELF تنفيذيا ذريّا. لا يشغل البرنامج أو يحمل مكتباته الخارجية أو يستدعي مترجم C أو رابطا. دون -o، يزيل لاحقة المصدر الأخيرة لاختيار اسم الخرج. لا ينشئ المجلدات الأب المفقودة. يحافظ الفشل قبل النشر على الخرج الموجود.

يحتوي ELF آلته الافتراضية وبايت كوده الخاص. يعمل دون المصدر أو تثبيت ASPL أو مترجم C أو ملف بايت كود منفصل. يظل محمل Linux المتوافق ومكتبات النظام مطلوبين، وكذلك المكتبات الخارجية وملفات البيانات الخاصة بالبرنامج. تحل مسارات الملفات النسبية أثناء التنفيذ ضد دليل عمل العملية. انظر الإدخال الأصلي والبرامج المبنية.

معالجة حالات الفشل الشائعة

أصلح تشخيصات المصدر قبل التشغيل أو البناء. ملف المصدر المفقود فشل مضيف. تؤدي المصادر الجذرية المتعددة أو الخيارات اللاحقة أو المعاملات غير المدعومة أو اختيار المصدر نفسه للخرج إلى أخطاء استخدام. لمسار مصدر يبدأ بشرطة، استخدم aspl check -- -name.aspl. العربية هي لغة التشخيص الافتراضية حتى مع المصدر الإنجليزي. راجع صياغة أوامر Linux ومراحلها لمعرفة الأشكال الدقيقة.

الحدود المعيارية للإصدار

أول برنامج أصلي

اختيار الأداة والتحقق منها

يفترض هذا المسار أنك تستخدم الطرفية بالفعل، ولا يتطلب إكمال دروس المبتدئين. تحقق أولا من متطلبات النظام. تختار هذه التعليمات ASPL 0.7.0 لنظام Linux بمعمارية x86-64. أما Console فهو اختياري ومنفصل.

نزّل أرشيف الأداة الأصلية وملف SHA256SUMS الخاص به في مجلد جديد. تحقق قبل الاستخراج أو التنفيذ، وتوقف عند اختلاف البصمة أو خطأ الأرشيف. تكشف البصمة اختلاف البايتات، لكن تنزيلها من الموقع نفسه لا يجعلها توقيعا مستقلا للناشر.

sha256sum --check SHA256SUMS &&
tar -tJf aspl-0.7.0-x86_64-linux-gnu.tar.xz &&
tar -xJf aspl-0.7.0-x86_64-linux-gnu.tar.xz

يحتوي الأرشيف مجلدا واحدا باسم aspl-0.7.0-x86_64-linux-gnu/ فيه aspl وDEPENDENCIES.json والرخصتان وTHIRD-PARTY-NOTICES. لا يوجد سكربت تثبيت. احتفظ بهذه الملفات معا في مجلد مستخدم خاص بالإصدار، ثم اختر الملف التنفيذي بوصلة رمزية. إذا كان ~/.local/bin/aspl موجودا، فافحصه قبل استبداله.

mkdir -p "$HOME/.local/opt" "$HOME/.local/bin"
mv aspl-0.7.0-x86_64-linux-gnu "$HOME/.local/opt/"
ln -s "$HOME/.local/opt/aspl-0.7.0-x86_64-linux-gnu/aspl" "$HOME/.local/bin/aspl"
export PATH="$HOME/.local/bin:$PATH"
hash -r

نفذ ذلك مرة واحدة للإصدار المختار. افحص مجلد الإصدار الموجود بدلا من الكتابة فوقه. أضف سطر export PATH مرة واحدة إلى ملف بدء الصدفة إذا أردت استعماله في الطرفيات اللاحقة.

التحقق من التثبيت المختار

command -v aspl
aspl --version
aspl --diagnostic-language=en --help

يجب أن يشير الأمر الأول إلى تثبيت المستخدم المختار، وأن يكون الإصدار aspl 0.7.0. إذا اختير تثبيت آخر، فافحص ترتيب PATH وامسح ذاكرة أوامر الصدفة. عند فقد المحمل أو مكتبة مشتركة، راجع متطلبات المضيف بدلا من اعتباره خطأ في المصدر. العربية هي لغة التشخيص الافتراضية؛ يغير --diagnostic-language=en التشخيصات دون المصدر أو الخرج.

حفظ برنامج أول كامل

نزّل إحدى صيغ المصدر المتاحة أدناه واحفظها باسم hello.aspl، ثم اتبع مسار الفحص والتشغيل والبناء. يعيد برنامج Hello المعتمد حالة صفر ولا يطبع شيئا. طباعة النص وإرجاع حالة العملية عمليتان منفصلتان.

الترقية والرجوع وإلغاء التثبيت

للترقية، اختر إصدارا منشورا من سجل الإصدارات. اقرأ متطلباته، وتحقق من أرشيفه وبصماته الخاصة، واستخرجه في مجلد إصدار منفصل. اختبر مساره التنفيذي المطلق على مصدرك بأوامر --version وcheck وrun وbuild قبل اختياره. احتفظ بالمجلد السابق ونسخ المصدر الاحتياطية.

لاختيار مجلد 0.7.0 المتحقق منه مجددا في Bash:

ln -sfn "$HOME/.local/opt/aspl-0.7.0-x86_64-linux-gnu/aspl" "$HOME/.local/bin/aspl"
hash -r
command -v aspl
aspl --version

يغير الرجوع إلى إصدار أصلي هذه الوصلة إلى ملف تنفيذي أصلي سابق احتفظت به. استبدل المسار بمجلد الإصدار السابق المتحقق منه وافحص الإصدار وتوافق المصدر. لا يعيد ذلك كتابة البرامج التي بنيت بإصدار آخر. تستعيد حزمة استعادة موقع ASPL تقديم الموقع وأصوله المحتفظ بها، ولا ترجع الأداة الأصلية المثبتة على جهازك.

لإلغاء هذا التثبيت، تحقق أولا من هدف الوصلة بأمر readlink "$HOME/.local/bin/aspl". احذف الوصلة ومجلد الإصدار المحدد فقط إذا كانا التثبيت المقصود:

rm "$HOME/.local/bin/aspl"
rm -r "$HOME/.local/opt/aspl-0.7.0-x86_64-linux-gnu"
hash -r
command -v aspl

احذف سطر PATH من ملف بدء الصدفة فقط إذا لم تستخدم أدوات أخرى ذلك المجلد. تبقى ملفات المصدر والبرامج المبنية قابلة للاستعمال. ولـConsole خطوات إلغاء مستقلة.

الحدود المعيارية للإصدار
ارجع إلى المحرر