Nand2Tetris — الجزء الثاني: من الآلة الافتراضية إلى نظام التشغيل › المشروع 11: المصرِّف II: توليد الشيفرة 5 / 6 السابق التالي

المشروع 11: المصرِّف II: توليد الشيفرة

المشروع 11: المصرِّف II - توليد الشيفرة

خلفية

في هذا المشروع نُكمل بناء مصرِّف Jack الذي بدأناه في المشروع السابق.

العقد

وسّع مُحلّل الصياغة المبني في المشروع 10 ليصبح مصرِّف Jack كامل النطاق. وينبغي أن يكون خرج المصرِّف شيفرة VM مصمّمة للعمل على الآلة الافتراضية المُنفّذة في المشروعين 7-8. واستخدم مصرِّفك لتجميع جميع برامج Jack المذكورة أدناه. وتأكّد من أن كل برنامج مترجم ينفّذ وفق ما تقتضيه وثائقه.

الموارد

القراءة ذات الصلة بهذا المشروع هي الفصل 11 من الكتاب. وستحتاج إلى أداتين: لغة البرمجة التي ستنفّذ بها مصرّفك، ومُحاكٍ الآلة الافتراضية المرفق، لاختبار الشيفرة التي يولّدها مصرّفك. وجميع ملفات الاختبار اللازمة لهذا المشروع متوفّرة في projects/11 على حاسوبك.

التنفيذ المقترح

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

المرحلة الأولى: جدول الرموز

نقترح أن تبدأ ببناء وحدة جدول الرموز في المصرِّف واستخدامها لتوسيع مُحلّل الصياغة المبني في المشروع 10. ففي الوقت الحاضر، كلما صادف المُحلّل معرّفًا في الشيفرة المصدريّة، مثل foo مثلًا، يُخرج سطر XML الآتي: " foo ". وبدلًا من ذلك، دَع مُحلّلك يُخرج المعلومات التالية كجزء من خرجه بصيغة XML (باستخدام أي صيغة خرج تختارها):

  • اسم المعرّف، كما يفعل الإصدار الحالي من مُحلّل الصياغة.

  • فئة المعرّف: var، أو argument، أو static، أو field، أو class، أو subroutine.

  • إذا كانت فئة المعرّف var أو argument أو static أو field، فإن الفهرس الجاري الذي يُسنده جدول الرموز إلى المعرّف.

  • ما إذا كان المعرّف يُعرَّف حاليًا (أي أنه يمثّل متغيّرًا مُعلَنًا في عبارة "var") أو مستخدَمًا.

يمكنك اختبار وحدة جدول الرموز والقدرة المذكورة أعلاه بتشغيل مُحلّل الصياغة المُوسّع على برامج Jack الاختبارية المرفقة في المشروع 10. وحين يتضمّن خرج مُحلّلك المُوسّع المعلومات الواردة أعلاه، فذلك يعني أنك طوّرت قدرة تنفيذية كاملة على فهم البنية النحوية لبرامج Jack. وفي هذه المرحلة يمكنك التحوّل إلى مصرِّف كامل النطاق، والبدء في توليد شيفرة VM بدلًا من خرج XML. ويمكن فعل ذلك بتحويل شيفرة مُحلّل الصياغة المُوسّع تدريجيًا إلى مصرِّف كامل النطاق.

المرحلة الثانية: توليد الشيفرة

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

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

لكل برنامج اختبار، اتّبع الروتين التالي:

  • ترجم مجلد البرنامج باستخدام مصرّفك. وينبغي أن يترجم هذا الإجراء جميع ملفات .jack في المجلد إلى ملفات .vm مقابلة؛

  • افحص ملفات .vm المولّدة. وإذا كانت هناك أي مشكلات ظاهرة، فأصلح مصرّفك وارجع إلى الخطوة 1 (تذكّر: جميع برامج الاختبار المرفقة خالية من الأخطاء)؛

  • اختبر برنامج VM المترجَم بتحميل مجلد البرنامج إلى مُحاكٍ الآلة الافتراضية المرفق، وتنفيذه باستخدام وضع "no animation". ويتضمّن كل برنامج من برامج الاختبار الستة إرشادات تنفيذ محدّدة، كما هي مُبيّنة أدناه؛ فاختبر البرنامج وفقًا لهذه الإرشادات؛

  • إذا تصرّف برنامج الاختبار على نحو غير متوقّع، أو عرض مُحاكٍ الآلة الافتراضية رسالة خطأ ما، فأصلح مصرّفك وارجع إلى الخطوة 1.

الاختبار

كل برنامج من البرامج المذكورة أدناه مصمّم لاختبار قدرات محدّدة على التعامل مع اللغة في مصرّفك، اختبارًا تدريجيًا وحدويًا.

برنامج الاختبار الوصف الغرض
السبعة: Main.jack يحسب قيمة العبارة (3*2)+1 ويطبع الناتج في أعلى يسار الشاشة. ولاختبار ما إذا كان مصرّفك قد ترجم البرنامج ترجمة صحيحة، شغّل الشيفرة المترجمة في مُحاكٍ الآلة الافتراضية المرفق وتأكّد من أنها تعرض العدد 7 بصورة صحيحة. يختبر كيف يتعامل مصرّفك مع برنامج بسيط يتضمّن ثلاثة أشياء: عبارة حسابية بثوابت صحيحة (دون متغيّرات)، وعبارة do، وعبارة return.
التحويل إلى ثنائي: Main.jack يفكّك عددًا من 16 بتًّا إلى تمثيله الثنائي. يأخذ البرنامج القيمة من 16 بتًّا المخزّنة في RAM[8000] ويخزّن بتّاتها فردةً في RAM[8001..8016] (كل موقع سيحتوي على 0 أو 1). وقبل بدء التحويل، يهيّئ البرنامج مواقع RAM[8001...8016] إلى -1. ولاختبار ما إذا كان مصرّفك قد ترجم البرنامج ترجمة صحيحة، حمّل الشيفرة المترجمة إلى مُحاكٍ الآلة الافتراضية المرفق واتّبع الروتين التالي: - ضع (تفاعليًا) قيمة ما في RAM[8000]؛ - شغّل البرنامج لبضع ثوانٍ، ثم أوقف تنفيذه؛ - تحقّق (تفاعليًا) من أن مواقع RAM[8001...8016] تحتوي على النتائج الصحيحة، وأن أياً منها لا يحتوي على -1. يختبر كيف يتعامل مصرّفك مع جميع العناصر الإجرائية للغة Jack، أي العبارات والدوالّ وجميع عبارات اللغة. ولا يختبر البرنامج التعامل مع الدالّات العضوية والبانيات والمصفوفات والسلاسل والمتغيّرات الساكنة ومتغيّرات الحقول.
رقصة المربعات: Main.jack Square.jack SquareGame.jack تطبيق تفاعلي بسيط، موصوف بالتفصيل في المشروع 9. يتيح تحريك مربّع رسومي حول الشاشة باستخدام مفاتيح الأسهم الأربعة في لوحة المفاتيح. وأثناء الحركة، يمكن زيادة حجم المربّع أو تصغيره بالضغط على مفتاحي "z" و"x" على الترتيب. وللخروج من التطبيق، اضغط مفتاح "q". ولاختبار ما إذا كان مصرّفك قد ترجم الشيفرة المصدريّة ترجمة صحيحة، شغّل الشيفرة المترجمة في مُحاكٍ الآلة الافتراضية المرفق وتأكّد من أنها تعمل وفق الوصف أعلاه. يختبر كيف يتعامل مصرّفك مع التراكيب الموجّهة بالكائنات في لغة Jack: البانيات والدالّات العضوية والحقول والعبارات التي تتضمّن نداءات دوالّ عضوية. ولا يختبر البرنامج التعامل مع المتغيّرات الساكنة.
المتوسط: Main.jack يحسب متوسّط متتالية من الأعداد الصحيحة يقدّمها المستخدم. ولاختبار ما إذا كان مصرّفك قد ترجم البرنامج ترجمة صحيحة، شغّل الشيفرة المترجمة في مُحاكٍ الآلة الافتراضية المرفق واتبع التعليمات المعروضة على الشاشة. يختبر كيف يتعامل مصرّفك مع المصفوفات والسلاسل.
Pong: Main.jack Ball.jack Bat.jack PongGame.jack في هذه اللعبة الكلاسيكية، تتحرّك الكرة عشوائيًا وترتد عن "جدران" الشاشة. ويمكن للمستخدم تحريك مجداف صغير أفقيًا بالضغط على مفتاحي السهم الأيسر والأيمن في لوحة المفاتيح. وفي كل مرة يصطدم فيها المجداف بالكرة، يكسب المستخدم نقطة ويصغر المجداف قليلًا، لتجعل اللعبة أصعب قليلًا. وإذا أخطأ المستخدم واصطدمت الكرة بالأسفل، تنتهي اللعبة. ولاختبار ما إذا كان مصرّفك قد ترجم هذا البرنامج ترجمة صحيحة، شغّل الشيفرة المترجمة في مُحاكٍ الآلة الافتراضية المرفق والعب اللعبة. وتأكّد من كسب بعض النقاط، لاختبار الجزء من البرنامج الذي يعرض النتيجة على الشاشة. يوفّر اختبارًا كاملاً لكيفية تعامل مصرّفك مع الكائنات والمتغيّرات الساكنة.
مصفوفات مركّبة: Main.jack ينفّذ خمسة حسابات مركّبة باستخدام المصفوفات. وبالنسبة لكل حساب منها، يطبع البرنامج على الشاشة النتيجة المتوقّعة مقابل النتيجة الفعلية (كما ينفّذها البرنامج المترجَم). ولاختبار ما إذا كان مصرّفك قد ترجم البرنامج ترجمة صحيحة، شغّل الشيفرة المترجمة في مُحاكٍ الآلة الافتراضية المرفق وتأكّد من أن النتائج الفعلية مطابقة للنتائج المتوقّعة. يختبر كيف يتعامل مصرّفك مع مراجع المصفوفات والعبارات المركّبة.