مترجم (حوسبة)

نمط تصميم W3sDesign Interpreter UML

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

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

يمكن تشغيل الشيفرة البرمجية التي تعمل في مترجم فوري على أي منصة مزودة بمترجم فوري متوافق . ويمكن توزيع الشيفرة نفسها على أي منصة من هذا القبيل، بدلاً من الحاجة إلى إنشاء ملف تنفيذي لكل منصة على حدة. وعلى الرغم من أن كل لغة برمجة ترتبط عادةً ببيئة تشغيل محددة، إلا أنه يمكن استخدام اللغة نفسها في بيئات مختلفة. وقد تم تصميم مترجمات فورية للغات التي ترتبط تقليديًا بالترجمة ، مثل ALGOL و Fortran و COBOL و C و C++ .

تاريخ

في بدايات الحوسبة، كانت المترجمات أكثر شيوعًا واستخدامًا من المفسرات لأن الأجهزة في ذلك الوقت لم تكن قادرة على دعم كل من المفسر والتعليمات البرمجية المفسرة، كما أن بيئة المعالجة الدفعية النموذجية في ذلك الوقت حدّت من مزايا التفسير. [ 1 ]

استُخدمت المترجمات منذ عام 1952 لتسهيل البرمجة في ظل قيود الحواسيب آنذاك (مثل نقص مساحة تخزين البرامج، أو عدم وجود دعم أصلي للأعداد العشرية). كما استُخدمت المترجمات للترجمة بين لغات الآلة منخفضة المستوى، مما سمح بكتابة التعليمات البرمجية للأجهزة التي كانت لا تزال قيد الإنشاء واختبارها على الحواسيب الموجودة بالفعل. [ 2 ] كانت لغة ليسب أول لغة برمجة عالية المستوى تُفسَّر . طُبِّقت ليسب لأول مرة على يد ستيف راسل على حاسوب IBM 704. كان راسل قد قرأ ورقة جون مكارثي بعنوان "الدوال التكرارية للتعبيرات الرمزية وحسابها بواسطة الآلة، الجزء الأول"، وأدرك (مما أثار دهشة مكارثي) أنه يمكن تنفيذ دالة eval في ليسب بلغة الآلة. [ 3 ] وكانت النتيجة مترجمًا فعالًا للغة ليسب، والذي يمكن استخدامه لتشغيل برامج ليسب، أو بتعبير أدق، "تقييم تعبيرات ليسب".

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

يستخدم

تشمل الاستخدامات البارزة للمترجمين الفوريين ما يلي:

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

كفاءة

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

قد يُنشئ المفسر تمثيلاً وسيطاً (IR) للبرنامج من شفرة المصدر لتحقيق أهداف مثل سرعة الأداء أثناء التشغيل. كما قد يُنشئ المُترجم تمثيلاً وسيطاً، لكنه يُنشئ شفرة الآلة للتنفيذ لاحقاً، بينما يُهيئ المفسر البرنامج للتنفيذ. هذه الأهداف المختلفة تؤدي إلى تصميمات مختلفة للتمثيل الوسيط. تستبدل العديد من مفسرات لغة BASIC الكلمات المفتاحية برموز أحادية البايت ، والتي يمكن استخدامها للعثور على التعليمات في جدول القفز . [ 4 ] تحقق بعض المفسرات، مثل مفسر PBASIC ، مستويات أعلى من ضغط البرنامج باستخدام بنية ذاكرة برنامج موجهة بالبتات بدلاً من البايتات، حيث تشغل رموز الأوامر حوالي 5 بتات، وتُخزن الثوابت "ذات 16 بت" في شفرة متغيرة الطول تتطلب 3 أو 6 أو 10 أو 18 بت، وتتضمن معاملات العنوان "إزاحة بت". تستطيع العديد من مفسرات BASIC تخزين وقراءة تمثيلها الداخلي المُرمز.

توجد عدة حلول وسط بين سرعة التطوير عند استخدام المفسر وسرعة التنفيذ عند استخدام المترجم. تسمح بعض الأنظمة (مثل بعض لغات ليسب ) للبرامج المفسرة والمترجمة باستدعاء بعضها البعض ومشاركة المتغيرات. هذا يعني أنه بمجرد اختبار روتين ما وتصحيحه باستخدام المفسر، يمكن ترجمته، وبالتالي الاستفادة من سرعة التنفيذ أثناء تطوير الروتينات الأخرى. [ 6 ]

تطبيق

بما أن المراحل المبكرة من التفسير والترجمة متشابهة، فقد يستخدم المفسر نفس المحلل المعجمي والمحلل النحوي مثل المترجم، ثم يفسر شجرة بناء الجملة المجردة الناتجة .

مثال

مترجم تعابير مكتوب بلغة C++ .

استيراد std ؛باستخدام std :: runtime_error ؛ باستخدام std :: unique_ptr ؛ باستخدام std :: variant ؛// أنواع البيانات لفئة تعداد شجرة بناء الجملة المجردة Kind : char { VAR , CONST , SUM , DIFF , MULT , DIV , PLUS , MINUS , NOT };// تعريف مسبق للفئة Node ;class Variable { public : int * memory ; };class Constant { public : int value ; };class UnaryOperation { public : unique_ptr < Node > right ; };class BinaryOperation { public : unique_ptr < Node > left ; unique_ptr < Node > right ; };باستخدام التعبير = متغير < متغير ، ثابت ، عملية ثنائية ، عملية أحادية > ؛class Node { public : Kind kind ; Expression e ; };// إجراء المفسر [ [ nodiscard ] ] int executeIntExpression ( const Node & n ) { int leftValue ; int rightValue ; switch ( n - > kind ) { case Kind :: VAR : return std :: get <Variable> ( n.e ) .memory ; case Kind :: CONST : return std :: get <Constant> ( n.e ) .value ; case Kind :: SUM : case Kind :: DIFF : case Kind :: MULT : case Kind :: DIV : const BinaryOperation & bin = std :: get <BinaryOperation> ( n.e ) ; leftValue = executeIntExpression ( bin.left.get ( ) ) ; rightValue = executeIntExpression ( bin.right.get ( ) ) ; switch ( n.kind ) { case Kind :: SUM : return leftValue + rightValue ; case Kind :: DIFF : return leftValue - rightValue ;في حالة الضرب : أرجع قيمة اليسار مضروبة في قيمة اليمين ؛ في حالة القسمة : إذا كانت قيمة اليمين تساوي صفرًا ، فأطلق خطأ وقت التشغيل " القسمة على صفر" . وإلا، فأرجع قيمة اليسار مقسومة على قيمة اليمين .} case Kind :: PLUS : case Kind :: MINUS : case Kind :: NOT : const UnaryOperation & un = std :: get <UnaryOperation> ( n.e ) ; rightValue = executeIntExpression ( un.right.get ( ) ) ; switch ( n.kind ) { case Kind :: PLUS : return + rightValue ; case Kind :: MINUS : return -rightValue ; case Kind :: NOT : return ! rightValue ; } default : std :: unreachable ( ) ; } }

مجموعة مُجمّعة في الوقت المناسب

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

الاختلافات

مترجم جدول التحكم
يتم تحديد المنطق كبيانات منسقة على شكل جدول.
مترجم بايت كود
تقوم بعض المفسرات بمعالجة الشفرة الوسيطة، وهي صيغة منطقية وسيطة مُجمَّعة من لغة برمجة عالية المستوى. على سبيل المثال، تُجمَّع لغة Emacs Lisp إلى شفرة وسيطة تُفسَّر بواسطة مفسر. يمكن القول إن هذه الشفرة المُجمَّعة هي شفرة آلية لآلة افتراضية - يُنفِّذها المفسر. يُطلق على هذا النوع من المفسرات أحيانًا اسم " المُجمِّع" . [ 7 ] [ 8 ]
مترجم التعليمات البرمجية متعدد الخيوط
يُشبه مُفسّر الشفرة المترابطة مُفسّر الشفرة البايتية، ولكنه يستخدم المؤشرات بدلاً من البايتات. كل تعليمة عبارة عن كلمة تُشير إلى دالة أو سلسلة تعليمات، وقد يتبعها مُعامل. يقوم مُفسّر الشفرة المترابطة إما بجلب التعليمات واستدعاء الدوال التي تُشير إليها، أو بجلب التعليمة الأولى والانتقال إليها، وتنتهي كل سلسلة تعليمات بجلب التعليمة التالية والانتقال إليها. من أمثلة الشفرة المترابطة شفرة فورث المُستخدمة في أنظمة البرامج الثابتة المفتوحة . تُترجم لغة المصدر إلى "شفرة فورث" (شفرة بايتية)، والتي تُفسّرها بعد ذلك آلة افتراضية .
مترجم شجرة بناء الجملة المجردة
يقوم مُفسِّر شجرة بناء الجملة المجردة بتحويل الشفرة المصدرية إلى شجرة بناء جملة مجردة (AST)، ثم يُفسِّرها مباشرةً، أو يستخدمها لتوليد شفرة أصلية عبر الترجمة الفورية (JIT). [ 9 ] في هذا النهج، لا تحتاج كل جملة إلا إلى تحليل واحد. ومن مزايا شجرة بناء الجملة المجردة على الشفرة البايتية، أنها تحافظ على بنية البرنامج العامة والعلاقات بين العبارات (التي تُفقد في تمثيل الشفرة البايتية)، وعند ضغطها تُوفِّر تمثيلاً أكثر إيجازًا. [ 10 ] لذا، اقتُرح استخدام شجرة بناء الجملة المجردة كصيغة وسيطة أفضل من الشفرة البايتية. مع ذلك، بالنسبة للمُفسِّرات، تُسبِّب شجرة بناء الجملة المجردة عبئًا إضافيًا أكبر من مُفسِّر الشفرة البايتية، نظرًا لوجود عُقد متعلقة ببناء الجملة لا تُؤدِّي أي عمل مُفيد، ولأن التمثيل أقل تسلسلًا (يتطلب اجتياز المزيد من المؤشرات)، ولأن زيارة الشجرة تُسبِّب عبئًا إضافيًا. [ 11 ]
مترجم القوالب
بدلاً من تنفيذ التعليمات البرمجية باستخدام عبارة switch كبيرة تحتوي على جميع التعليمات البرمجية الممكنة، أثناء العمل على مكدس برمجي أو مسار شجري، يحتفظ مترجم القوالب بمصفوفة كبيرة من التعليمات البرمجية (أو أي تمثيل وسيط فعال) مُرتبطة مباشرةً بتعليمات الآلة الأصلية المقابلة التي يمكن تنفيذها على جهاز المضيف كأزواج مفتاح-قيمة (أو في تصميمات أكثر كفاءة، عناوين مباشرة للتعليمات الأصلية)، [ 12 ] [ 13 ] والمعروفة باسم "القالب". عند تنفيذ جزء معين من التعليمات البرمجية، يقوم المترجم ببساطة بتحميل أو الانتقال إلى تعيين رمز العملية في القالب وتشغيله مباشرةً على الجهاز. [ 14 ] [ 15 ] نظرًا لتصميمه، يُشبه مترجم القوالب إلى حد كبير مُترجم JIT أكثر من المترجم التقليدي، إلا أنه ليس مُترجم JIT من الناحية الفنية لأنه ببساطة يُترجم التعليمات البرمجية من اللغة إلى استدعاءات أصلية رمز عملية واحد في كل مرة بدلاً من إنشاء تسلسلات مُحسّنة من تعليمات وحدة المعالجة المركزية القابلة للتنفيذ من جزء التعليمات البرمجية بأكمله. نظرًا لتصميم المفسر البسيط الذي يعتمد على تمرير الاستدعاءات مباشرةً إلى المكونات المادية بدلًا من تنفيذها مباشرةً، فهو أسرع بكثير من جميع الأنواع الأخرى، حتى مفسرات الشفرة البايتية، وأقل عرضةً للأخطاء إلى حد ما. لكن في المقابل، يصعب صيانته نظرًا لاضطراره لدعم الترجمة إلى بنى معمارية متعددة مختلفة بدلًا من آلة افتراضية/مكدس مستقل عن المنصة. حتى الآن، التطبيقات الوحيدة لمفسرات القوالب للغات المعروفة على نطاق واسع هي المفسر الموجود في تطبيق جافا المرجعي الرسمي، وآلة جافا الافتراضية Sun HotSpot، [ 12 ] ومفسر Ignition في محرك تنفيذ جافا سكريبت V8 من جوجل.
الشفرة المصغرة
توفر الشفرة المصغرة طبقة تجريدية تعمل كمترجم للأجهزة، حيث تُنفذ شفرة الآلة بلغة شفرة آلة منخفضة المستوى. [ 16 ] وهي تفصل تعليمات الآلة عالية المستوى عن الإلكترونيات الأساسية ، مما يتيح تصميم وتعديل التعليمات عالية المستوى بحرية أكبر. كما تُسهل توفير تعليمات معقدة متعددة الخطوات، مع تقليل تعقيد دوائر الحاسوب.

انظر أيضاً

مراجع

  1. «لماذا كُتب أول مُترجم قبل أول مُفسِّر؟» . آرس تكنيكا . 8 نوفمبر 2014. تم الاطلاع عليه في 9 نوفمبر 2014 .
  2. بينيت، جيه إم؛ برينز، دي جي؛ وودز، إم إل (1952). "الروتينات الفرعية التفسيرية". وقائع المؤتمر الوطني لجمعية آلات الحوسبة، تورنتو .
  3. وفقًا لما ذكره بول غراهام في كتابه "هاكرز آند بينترز" (صفحة 185)، قال مكارثي: "قال ستيف راسل: انظر، لماذا لا أبرمج دالة التقييم هذه ...، فقلت له: ها ها، أنت تخلط بين النظرية والتطبيق، فهذه الدالة مخصصة للقراءة لا للحساب. لكنه مضى قدمًا وفعل ذلك. أي أنه قام بتجميع دالة التقييم في بحثي إلىلغة الآلة IBM 704 ، مع إصلاح الخلل ، ثم روّج لها كمترجم للغة ليسب، وهو ما كانت عليه بالفعل. وهكذا، في تلك المرحلة، اتخذت لغة ليسب شكلها الحالي..."
  4. 1 2 3 تستند هذه المقالة إلى مواد مأخوذة من Interpreter في قاموس الحوسبة المجاني على الإنترنت قبل 1 نوفمبر 2008 وتم دمجها بموجب شروط "إعادة الترخيص" الخاصة بـ GFDL ، الإصدار 1.3 أو أحدث.
  5. "المترجمات مقابل المفسرات: شرح واختلافات" . دليل IONOS الرقمي . تم الاطلاع عليه بتاريخ 16-09-2022 .
  6. نانز، سيباستيان؛ فوريا، كارلو أ. (مايو 2015). "دراسة مقارنة للغات البرمجة في برنامج روزيتا كود". المؤتمر الدولي السابع والثلاثون لهندسة البرمجيات IEEE/ACM لعام 2015. الصفحات 778-788 . arXiv : 1409.0252 . doi : 10.1109/icse.2015.90 . ISBN  978-1-4799-1934-5.
  7. ^ كونيل، كلاوس (1987) [1986]. "4. الحواسيب الصغيرة - Eigenschaften und Möglichkeiten" [ 4. الحواسيب الصغيرة - الخصائص والإمكانيات ] . في إرليكامبف، راينر؛ مونك، هانز يواكيم (محرران). Mikroelektronik in der Amateurpraxis [ الإلكترونيات الدقيقة للهواة العمليين ] (باللغة الألمانية) (3 ed.). برلين: Militärverlag der Deutschen Demokratischen Republik ، لايبزيغ. ص. 222. ردمك   3-327-00357-27469332.
  8. ^ هاين، ر. (1984). "المترجم الأساسي لـ U880" [ المترجم الأساسي لـ U880 (Z80) ] . راديو-فيرنسيهن-إلكترونيك (باللغة الألمانية). 1984 (3): 150-152 .
  9. تمثيلات وسيطة لشجرة بناء الجملة المجردة ، منتدى لامدا النهائي
  10. كيستلر، توماس؛ فرانز، مايكل (فبراير 1999). "بديل قائم على الشجرة لرموز بايت جافا" (ملف PDF) . المجلة الدولية للبرمجة المتوازية . 27 (1): 21-33 . CiteSeerX 10.1.1.87.2257 . doi : 10.1023/A:1018740018601 . ISSN 0885-7458 . S2CID 14330985. تاريخ الاسترجاع: 20 ديسمبر 2020 .   
  11. أرشيف مدونة Surfin' Safari  » الإعلان عن SquirrelFish . Webkit.org (2008-06-02). تاريخ الاطلاع: 2013-08-10.
  12. 1 2 "أوبنجدك/جدك" . جيثب . 18 نوفمبر 2021.
  13. "نظرة عامة على وقت تشغيل HotSpot" . Openjdk.java.net . تم الاسترجاع في 2022-08-06 .
  14. "تبسيط فهم JVM: متغيرات JVM، ومفسر Cpp، ومفسر القوالب" . metebalci.com .
  15. "مفسر قوالب JVM" . ProgrammerSought .
  16. كينت، ألين؛ ويليامز، جيمس ج. (5 أبريل 1993). موسوعة علوم وتكنولوجيا الحاسوب: المجلد 28 - الملحق 13. نيويورك: مارسيل ديكر، إنك. ISBN 0-8247-2281-7تم الاطلاع عليه بتاريخ 17 يناير 2016 .

مصادر