علوم البرمجة

ما هو الفرق بين المُترجم والمُفسّر في عالم لغات البرمجة؟ Compiler vs Interpreter

مقدمة: حول الحاجة للمترجمات والمفسرات

تعتمد لغات البرمجة المستخدمة في وقتنا الحاليّ وعلى اختلاف أنواعها على مبدأ بسيط، وهو تحويل الشيفرة المصدرية (البرنامج) من تمثيلٍ عالي المستوى إلى تعليماتٍ تنفيذية بلغة الآلة يستطيع المعالج فهمها، التعامل معها وتنفيذها. يبرز بهذا السياق مصطلحٌ هو “نظام معالجات لغات البرمجة Programming Languages Processing System” والذي يشير إلى الخطوات المطلوب تنفيذها من أجل تحويل الشيفرة المصدرية إلى لغة الآلة.

بالنسبة لمعظم لغات البرمجة الشهيرة المستخدمة اليوم، يتم استخدام طريقتين أساسيتين كوسائل لمعالجة الشيفرة المصدرية وتنفيذها، فإما أن يتم “ترجمة Compile” اللغة وإما أن يتم “تفسيرها Interpret“، وهذا يتم عبر برامجٍ وسيطة هي المترجم Compiler والمفسر Interpreter.

كنا قد استعرضنا في مقالاتٍ سابقة آلية عمل المترجم والمفسر بشكلٍ مفصل، والهدف من هذا المقال هو توفير ملخصٍ سريع يمكن عبره توضيح أبرز الفروقات بين هذه البرامج واللغات التي تستخدمها، فعندما تعتمد لغة البرمجة على مترجمٍ من أجل تكوين التعليمات التنفيذية الخاصة بالمعالج يطلق عليها اسم “لغة مُترجمة Compiler Language“، في حين أن اللغات التي تعتمد على المفسر يُطلق عليها اسم “لغات مفسرة Interpreted Languages“. هنالك بعض اللغات التي يُنظر لها على أنها مترجمة ومفسرة بنفس الوقت، مثل لغة جافا.

ما الذي تقوم به المترجمات والمفسرات؟

يقوم المترجم والمفسر بتأدية نفس الوظيفة من حيث المبدأ: تأمين آلية لتحويل الشيفرة المصدرية إلى تمثيلٍ مفهوم من قبل المعالج يمكن تنفيذه. الفرق الأساسيّ بينهما هو بكيفية تنفيذ ذلك.

بالنسبة للمترجم، فإن عمله يقوم على تحليل كامل الشيفرة المصدرية والتأكد من صحتها القواعدية والدلالية وعدم وجود أي أخطاء برمجية، ومن ثم يتم تحسين البرنامج لضمان تنفيذه بأعلى سرعة ممكنة وبأقل استهلاكٍ للذاكرة، وأخيراً يتم توليد ملف (أو مجموعة ملفات) يُعرف باسم الملف الكائنيّ Object File يستخدم من قبل برنامجٍ يدعى الرابط Linker لتوليد البرنامج التنفيذيّ القابل للتشغيل مباشرةً.

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

المترجمات والمفسرات: مساوئ وحسنات

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

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

المترجمات والمفسرات: خلاصة المقارنة

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

وجه المُقارنةالمترجماتالمفسرات
مبدأ العملتحليل كامل للشيفرة المصدرية، تحسينها وتوليد البرنامج التنفيذي تنفيذ الشيفرة المصدرية بشكلٍ مباشر سطراً تلو الآخر
دخل كامل الشيفرة المصدرية سطر واحد من الشيفرة المصدرية
الخرج برنامج تنفيذي بلغة الآلة تنفيذ مباشر للشيفرة المصدرية
شيفرة الآلةتتطلب حفظ البرنامج التنفيذي على الذاكرة، والذي يتضمن شيفرة الآلة لا تقوم بتوليد شيفرة تنفيذية تتطلب الحفظ على الذاكرة
زمن التنفيذسريع بالنسبة للبرنامج بعد ترجمته، ولكنه يتطلب وقتاً إضافياً للترجمة والبناءالشيفرة المُفسرة تتطلب وقتًا أطول للتنفيذ
زمن التطويربشكل عام، تتطلب اللغات المُترجمة وقتاً أثناء عملية التطوير لتوليد البرنامج التنفيذيبشكلٍ عام، تتطلب المُفسرات وقتاً أقصر أثناء عملية التطوير لتنفيذ البرنامج
آلية التنفيذتنفيذ البرنامج منفصل عن مرحلة الترجمة، ولا يمكن إجراء التنفيذ إلا بعد انتهاء كامل عملية الترجمة بنجاحتنفيذ البرنامج هو جزء من عملية التفسير
ما بعد التنفيذأي تعديل أو تطوير سيحتاج لتعديل الشيفرة المصدرية وتوليد برنامج تنفيذي جديدتعديل وتطوير الشيفرة المصدرية أبسط بسبب عدم وجود برنامج تنفيذي
متطلبات الذاكرةيتطلب البرنامج التنفيذي حجز جزءٍ من الذاكرة، إلا أن تنفيذه لا يتطلب وجود المترجم الذاكرةلا يتم حجز أي جزء من الذاكرة بسبب عدم توليد برنامج تنفيذيّ، ولكن المفسر نفسه يتطلب جزءاً من الذاكرة أثناء التنفيذ
تحسين الشيفرة المصدريةعادةً ما يكون البرنامج الناتج أفضل بسبب إجراء المترجم لتحليلٍ لكامل الشيفرة المصدريةعادةً ما يكون ناتج التفسير أقل كفاءة ومتانة بسبب تنفيذ البرنامج سطراً تلو الآخر
اكتشاف الأخطاءيقوم المترجم باكتشاف كافة الأخطاء والتنبيهات أثناء زمن الترجمة ومن ثم يتم عرضها. لن يتم توليد برنامج تنفيذي في حال وجود أخطاءيقوم المفسر باكتشاف الأخطاء على مستوى السطر أثناء زمن التنفيذ، ويتوقف تنفيذ البرنامج حصراً في حال وجود خطأ بسطرٍ ما
أشهر اللغاتC, C++, C#, ScalaPython, Ruby, PHP

خلاصة: من الأفضل؟

البشر مهووسون بالمقارنات التي من شأنها إظهار خياراتهم على أنها الأصح. نحن مهووسون بالفوز، وهذا ينطبق أيضاً على البرمجة. يوجد مبرمجون متعصبون مستعدون للنقاش ساعاتٍ وساعاتٍ لإقناعك أن لغة البرمجة التي يجيدونها ويفضلونها هي “الأفضل” وأن أسلوب البرمجة الذي يتبعونه هو الأنجح وأن اعتمادهم على لغةٍ مترجمة (أو مفسرة) هو المفتاح للسعادة الأبدية.

هل استخدام اللغات المفسرة أفضل من اللغات المترجمة؟ أو العكس؟ الجواب على هذا السؤال بسيط جداً: كما في كل شيء آخر بالحياة، مفهوم “الأفضل” هو مفهومٌ نسبيّ. استخدام لغة برمجة بدلاً من الأخرى يتبع بشكلٍ أساسيّ للمجال المستهدف والتطبيق المراد إنشاؤه. لغة بايثون تمتلك شهرةً كبيرة بمجال تحليل البيانات وتطبيقات معالجة الصورة والذكاء الصنعيّ وتعلم الآلة، ولذلك فإن الراغبين بالغوض بأحد هذه المجالات سيُفضل غالباً التوجه وتعلم لغة بايثون. لغة سي تستخدم بشكلٍ كبير في مجال برمجة الأنظمة المضمنة وأنظمة التشغيل، ولذلك فإن من يرغب بالغوض بهذا المجال سيُفضل غالباً تعلم لغة سي. لا أعتقد أن هنالك “أفضل”، وقد أكون مخطئاً في ذلك، إلا أن الأكيد هو أن البحث عن الأفضل والسعي لإثبات “الأفضل” هو إضاعة لوقتٍ يمكن استثماره في تعلم لغة برمجة جديدة أو البدء بمشروعٍ جديد أو تحسين مشروعٍ ومنتج موجودٍ أصلاً.

مصادر إضافية للاطلاع

مقالات ذات صلة

زر الذهاب إلى الأعلى