ماهي لغة الأسس؟


لغة برمجة الأسس هي لغة برمجة متعددة الاستخدامات (general purpose) يمكن تمديدها بشكل ديناميكي من قبل المستخدمين. في جوهرها، هي لغة منخفضة المستوى مشابهة للغة C، حيث توفر للمستخدمين البرمجة الإجرائية والأصناف المفروضة (static typing) والمؤشرات وإدارة الذاكرة يدويًا وغيرها من الميزات منخفضة المستوى الموجودة في C/C++. بالإضافة إلى الميزات منخفضة المستوى، توفر الأسس أيضًا بعض المزايا التي تتيح توسيعها من قبل المستخدمين عموديًا لتوفير ميزات مرتفعة المستوى، وكذلك توسيعها أفقياً لدعم مجالات جديدة. مبدئيًا، برامج الأسس تترجم آنيًا عند التنفيذ (JIT compiled)، ولكنها تتيح أيضًا للمستخدمين الترجمة المسبقة لبرامجهم.

تعليمات التنصيب والتشغيل


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

كتابة أول برنامج


سنتعلم كيفية كتابة أول وأبسط كود برمجي يمكن تحقيقه باستخدام لغة الأسس وهو "طباعة جملة !Hello World". لذا بدايةً يجب أن نقوم بتضمين (استيراد) المكتبات اللازمة لتحقيق هذا البرنامج، وكما هو الحال في أي لغة هناك وحدة بناء أساسية تقوم بتنفيذ العمليات الإجرائية ضمن البرنامج، وفي لغة الأسس هذه الوحدة هي "libalusus_spp.so"، وبالتالي يجب أن يبدأ البرنامج بتضمين هذه الوحدة، بالشكل التالي:

اشمل "libalusus_spp.so"؛
import "libalusus_spp.so";

الآن سنحتاج إلى دالة تقوم بتنفيذ عملية الطباعة، وهذا يتم من خلال الدالة print الموجودة ضمن الوحدة Console الموجودة بدورها ضمن مكتبة التنفيذ المعيارية Srl لذا لابد من تضمينها أولاً:
اشمل "مـتم/طـرفية"؛
import "Srl/Console";

عندما تشمل ملفًا فإن المترجم يشمل أيضًا الملفات والمكتبات التي يشملها ذلك الملف، لذا فإذا شملت المكتبة "مـتم/طـرفية" فلست بحاجة لشمول المكتبة "libalusus_spp.so" يدويًا لأنها مشمولة من قبل مكتبة الطرفية. الآن أصبح بإمكاننا استخدام دالة الطباعة بالشكل التالي:
مـتم.طـرفية.اطبع("بسم الله الرحمن الرحيم\ج")؛
Srl.Console.print("Hello World!\n");

حيث نضع بين قوسين متغير يمثل السلسلة النصية المراد طباعتها أو السلسلة النصية مباشرةً موضوعةً بين علامتي اقتباس "" كما فعلنا للتو. أما بالنسبة للمعامل n\ فهو رمز اختياري كما كل لغات البرمجة، ومهمته النزول سطراً بعد تنفيذ عملية طباعة Hello World. وبالتالي يمكننا كتابة الكود كاملاً كالتالي:
اشمل "مـتم/طـرفية"؛
مـتم.طـرفية.اطبع("بسم الله الرحمن الرحيم\ج")؛
import "Srl/Console";
Srl.Console.print("Hello World!\n");

الخرج:
بسم الله الرحمن الرحيم
Hello World!

ملاحظة: لكي نجعل استدعاء الدالة `اطبع` (print) أكثر سهولة، يمكننا أن نستخدم الأمر `استخدم` (use) لكي تمنحنا القدرة على الوصول لعناصر وحدة ما مثل `مـتم` (Srl) دون كتابة اسم الوحدة في كل مرة.

اشمل "مـتم/طـرفية"؛
استخدم مـتم.طـرفية؛
اطبع("بسم الله الرحمن الرحيم\ج")؛
import "Srl/Console";
use Srl.Console;
print("Hello World!\n");

الطباعة والإدخال


إن عمليات الإدخال والطباعة في لغة الأسس تتم كلها عن طريق الوحدة `طـرفية` (Console). لذا لاتنسَ تضمينها (كما فعلنا في المثال السابق) قبل التفكير في تنفيذ عمليات إدخال أو طباعة. كما أنه لكل صنف بيانات طريقة إدخال وطباعة مختلفة.

الطباعة


نستخدم في لغة الأسس الدالة `اطبع` (print) لتنفيذ عمليات الطباعة، فهي الدالة الأساسية المستخدمة لطباعة الجمل النصية، حيث تمنحنا هذه الدالة التحكم في طريقة طباعة الجمل النصية أو ما يعرف بتنسيق الجمل النصية، وإمكانية طباعة قيم المتغيرات بداخل النص المراد طباعته. ولها الشكل التالي:

اطبع(نسق، ...)؛
print(format, ...);

حيث يمثل المعطى `نسق` (format) النص، والثلاثة نقاط ... تتيح إضافة عدد غير محدد مسبقا من المتغيرات أو الـمعطيات (arguments)، حيث يعرف هذا النوع من الدوال ب "الدوال المرنة" (Variadic function). ولطباعة قيم متغيرات (متغيرات من الصنف الصحيح integer أو الحقيقي real أو المحرفي char ..إلخ) نقوم بتضمين النسق (format) تعبيراً محدداً بحسب صنف المتغير.
فلنفترض أن لديك متغير x يحتوي على قيمة عددية ناتجة عن إجراء بعض العمليات الحسابية، وأنت تريد معرفة قيمة هذا المتغير، إذا قمت بكتابة اسم المتغير وهو x بداخل علامات التنصيص، فإن الحرف x هو الذي سيتم طباعته، وليست القيمة العددية التي يحتويها المتغير، لذلك يتم إستخدام هذه الدالة مع تضمين النسق (format) رمزاً محدداً لإتمام هذه العملية. انظر للمثال التالي الذي يبين لنا كيفية استخدام هذه الدالة لطباعة عدد صحيح:
اشمل "مـتم/طـرفية"؛
استخدم مـتم.طـرفية؛
عرف س: صحيح = 3؛ // تعريف متغير من الصنف الصحيح (سنناقش كل الأنماط في الدرس القادم)
اطبع("الـناتج = %d"، س)؛
import "Srl/Console.alusus";
use Srl.Console;
def x: int=3; // تعريف متغير من الصنف الصحيح (سنناقش كل الأنماط في الدرس القادم)
print("Result = %d", x);

النتيجة:
الـناتج = 3
Result = 3

حيث قمنا بكتابة الجملة المراد طباعتها بين علامات تنصيص مزدوجة (double quote)، وقمنا بحجز مكان بداخل النص (Placeholder) (أي عنصر أو متغير نائب -ينوب عن قيمة ستحدد لاحقاً-)، ليتم طباعة قيمة المتغير بداخله عن طريق كتابة الحرف % متبوعا بالحرف d، حيث أن الرمز % بالنسبة لدالة الطباعة يعتبر ذو معنى خاص (حيث يتم استبداله بقيمة المتغير) الذي تم تحديد نوعه عن طريق الحرف d، ثم قمنا بتمرير المتغير س (x) كمعطى (argument) ثاني للدالة.
يوجد مجموعة محددة من الحروف التي يمكن استخدامها مع الرمز % للتحكم في طريقة طباعة قيم المتغيرات، حيث يمثل كل حرف صنف محدد من البيانات، وفيما يلي سنوضح الحروف (الرموز) المحددة للإستخدام مع الرمز % ونوع البيانات الخاص بكل حرف..


الرمز %:
يستخدم هذا الرمز ليتم طباعة الرمز المئوي كما هو، حيث أن هذا الرمز يعتبر رمز خاص بالنسبة للدالة، فلا يمكن كتابته كما هو إلا إذا قمت بكتابته مرتين. مثال:

اشمل "مـتم/طـرفية"؛
استخدم مـتم.طـرفية؛
اطبع("لغة الأسس تدعم الكتابة بالإنجليزية والعربية 100%%")؛
import "Srl/Console";
use Srl.Console;
print("Alusus language supports coding in English & Arabic 100%%");

النتيجة:
لغة الأسس تدعم الكتابة بالإنجليزية والعربية 100%
Alusus language supports writing in English & Arabic by 100%

الرمزين d, i:
يستخدم الحرف d أو الحرف i، لطباعة الأعداد الصحيحة والتي تتمثل في صنف البيانات int، كلاهما يقومان بطباعة الأعداد الصحيحة في الدالة print. مثال:

اشمل "مـتم/طـرفية"؛
استخدم مـتم.طـرفية؛
عرف عدد_صحيح: صحيح؛
عدد_صحيح = 778؛
اطبع("%d"، عدد_صحيح)؛ // طباعته مع إبقاء مؤشر الطباعة على نفس السطر
// اطبع(عدد_صحيح)؛ // يكافئ عملية الطباعة السابقة
// اطبع("%d\ج"، عدد_صحيح)؛ // نفس الأمر السابق لكن هنا سينزل المؤشر سطراً
import "Srl/Console";
use Srl.Console;
def integerNum: int;
integerNum=778
print("%d",integerNum); // طباعته مع إبقاء مؤشر الطباعة على نفس السطر
//print(integerNum); // يكافئ عملية الطباعة السابقة
//print("%d\n",integerNum); // نفس الأمر السابق لكن هنا سينزل المؤشر سطراً

الرمز c:
يستخدم لطباعة البيانات من الصنف مـحرف (char) والتي تمثل محرفًا واحد أو رمزًا خاصًا من مجموعة المحارف ASCII.

اشمل "مـتم/طـرفية"؛
استخدم مـتم؛
عرف م: محرف = 'a'؛
طـرفية.اطبع("%c"، م)؛
import "Srl/Console";
use Srl;def c: char = 'a';
Console.print("%c", c)

الرمز f :
لطباعة الأعداد التي تحتوي على فاصلة عشرية، ويعرف هذا الصنف من البيانات بـ `عائم` (float) (سنتحدث عنه في درس المتغيرات).


الرمز s :
لطباعة نص يحتوي على أكثر من محرف، أي لطباعة السلاسل النصية (سنتحدث عنه في درس السلاسل النصية).


الرمز p :
لطباعة عنوان المؤشر بالنظام السداسي عشر. كما في المثال التالي:

اشمل "مـتم/طـرفية"؛
استخدم مـتم.طـرفية؛
عرف س: صحيح؛
اطبع("عنوان س في الذاكرة هو: %p\ج"، س~مؤشر)؛
import "Srl/Console.alusus";
use Srl.Console;
def x:int;
print("x Address is: %p\n", x~ptr);

النتيجة:
عنوان س في الذاكرة هو: 0x55a3b28493f0
x Address is: 0x55a3b28493f0

الرمز e أو E:
لطباعة الأعداد العشرية من الصنف عائم بالطريقة العلمية والمعروفة بـ Scientific Notation، وهي عبارة عن كتابة الأعداد العشرية مرفوعة لأس يمثل عدد الخانات العشرية، وهي الطريقة المتبعة لتمثيل البيانات العشرية والمعروفه بـ IEEE-32 و IEEE-64.


الرمز g أو G:
لطباعة الأعداد العشرية من الصنف عائم، حيث يتم طباعة الأعداد بالطريقة العادية fixed-point إذا كان يمكن كتابة العدد بهذه الطريقة، فإذا كان العدد أكبر من أن يتم طباعته بهذه الطريقة يتم طباعة العدد بإستخدام طريقة الـ scientific-notation، والفرق بين الحرف الصغير والكبير يتمثل في طريقة طباعة رمز الأس في العدد إما بحرف e صغير أو حرف E كبير في حالة ما تم طباعة العدد بالطريقة الثانية.


الرمز a أو A:
لطباعة الأعداد العشرية من الصنف عائم بطريقة تمثيل الأعداد بالنظام السداسي عشر، والفرق بين الحرف الكبير والصغير يتمثل في طباعة الرمز 0x السابق للعدد إما بحرف كبير أو صغير.


الإدخال


لإدخال عدد صحيح (int)، نستخدم الدالة `أدخل_صحيح` (getInt) كما في المثال التالي:

اشمل "مـتم/طـرفية"؛
استخدم مـتم.طـرفية؛
عرف عدد_صحيح: صحيح؛
عدد_صحيح = أدخل_صحيح()؛ // إدخال العدد
اطبع("%d"، عدد_صحيح)؛
import "Srl/Console";
use Srl.Console;
def integerNum: int;
integerNum=getInt (); // إدخال العدد
print("%d",integerNum);

لإدخال عدد عائم، نستخدم الدالة `أدخل_عائم` (getFloat) كما في المثال التالي:

اشمل "مـتم/طـرفية"؛
استخدم مـتم.طـرفية؛
عرف عدد_عائم: عائم[64]؛
عدد_عائم = أدخل_عائم()؛ // إدخال العدد
اطبع("%f"، عدد_عائم)؛
import "Srl/Console";
use Srl.Console;
def floatNum: float[64];
floatNum = getFloat (); // إدخال العدد
print("%f",floatNum);

لإدخال محرف char، نستخدم الدالة `أدخل_محرفا` (getChar) كما في المثال التالي:

اشمل "مـتم/طـرفية"؛
استخدم مـتم.طـرفية؛
عرف م: محرف = أدخل_محرفا()؛
اطبع("%c"، م)؛
import "Srl/Console";
use Srl.Console;
def c: char = getChar();
print("%c", c);

لإدخال سلسلة نصية نستخدم الدالة `أدخل_محارف` (getString) ولكن لن نتحدث عنها في هذا الدرس، حيث سنتحدث عنها في الدرس المخصص للصنف `نـص` (String).