لغة التجميع
تصميم اللغة > وحدات الماكرو

تدعم العديد من المُجمعات وحدات الماكرو (بالإنجليزية: Macros)‏، وهي عبارة عن رموز مُعرفة عن طريق المبرمج وتحوي مجموعة من سطور النص المتسلسلة. هذا التسلسل للسطور النصية، قد يحوي سلسلة من التعليمات، أو سلسلة من تعليمات Pseudo-Ops خاصة بالبيانات. وطالما تم تعريف الماكرو عبر استخدام الـ Pseudo-Op المناسب، فإنه من الممكن استخدام اسمه، مثلما يتم استخدام أسماء الأوامر Mnemonic تماما. وعندما يقوم المُجمع بمعالجة جملة من تلك النوعية، فإنه يقوم باستبدال الجملة التي تحوي اسم الماكرو بالسطور النصية المرتبطة بذلك الماكرو. بعد ذلك، يقوم بمعالجة تلك السطور كما لو أنها قد ظهرت في ملف الشيفرة المصدرية (متضمنا، كما يحدث في بعض المُجمعات، محتويات أي ماكرو قد يظهر في السطور المُستبدلة -ماكرو داخل ماكرو-).
وبما أن وحدات الماكرو يمكن أن تحمل أسماء قصيرة يتم توسعتها إلى سطور طويلة من الكود، فإن وحدات الماكرو يمكن أن تستخدم لتجعل البرامج المكتوبة بلغة التجميع تبدو وكأنها أقصر (بمعنى أن يتطلب بناء التطبيق عددا أقل من سطور الكود، كما هو الحال مع لغات البرمجة عالية المستوى). ويمكن أيضا أن يتم استخدامها لإضافة هياكل Structures عالية المستوى إلى البرامج المكتوبة بلغة التجميع، ويمكن أن تقدم -بشكل اختياري- كود يستخدم لإدارة وإصلاح الأخطاء البرمجية بشكل ضمني، عبر المعاملات وعبر خصائص أخرى.
معظم المُجمعات تمتلك وحدات ماكرو مدمجة Built-in من أجل الاستدعائات عبر النظام System Calls ومن أجل بعض تسلسلات الكود الخاصة.
وغالبا ما تسمح المُجمعات لوحدات ماكرو بأن تمتلك معاملات. وبعض المُجمعات تمتلك لغة ماكرو معقدة جدا، وتقوم بدمج عناصر هذه اللغة عالية المستوى للقيام بوظائف متعددة: معاملات اختيارية Optional Parameters، متغيرات رمزية، جمل شرطية، معالجة لسلاسل الحرفية Strings، عمل عمليات حسابية، وجميع تلك الأشياء يمكن إعادة استخدامها أثناء تنفيذ وحدات ماكرو بعينها، وتسمح -تلك المُجمعات- لوحدات الماكرو بحفظ السياق Context أو تبادل المعلومات بين بعضها البعض. ولذلك، فإن الماكرو يمكنه توليد عدد ضخم من تعليمات لغة التجميع أو من تعريفات البيانات، استنادا إلى معاملات الماكرو Arguments. ويمكن استخدام ذلك لتوليد هياكل بيانات ذات شكل «سجلي» Record-Style، ويمكن استخدام ذلك أيضا لتولييد دوارات مبسوطة Unrolled Loops، على سبيل المثال، ويمكن أيضا استخدام نفس التقنية في توليد خوارزميات كاملة تستند على معاملات معقدة. ويمكن اعتبار مؤسسة تستخدم هذه النوعية من لغات التجميع والتي تم تمديد قدراتها بشكل مكثف عبر استخدام مجموعة وحدات الماكرو، يمكن اعتبارها وكأنها تستخدم لغة برمجة عالية المستوى، حيث أن مبرمجي الشركة لا يعملون مع عناصر الكمبيوتر المفاهيمية ذات المستوى المنخفض (مثال: لا يعملون مع المسجلات).
وقد تم استخدام وحدات الماكرو في عهد الحاسبات الكبيرة من أجل تخصيص Customize نظم برمجية واسعة النطاق Large Scale لتلبية طلبات محددة لعملاء معينين، واستخدت أيضا عبر فريق عمل أحد العملاء من أجل تلبية احتياجات موظفيه عبر بناء نسخ محددة من نظم تشغيل مصنع الكمبيوترات Manufacturer-الذي قد اشتراها هذا العميل-. وعلى سبيل المثال، فقد سبق فعل ذلك، مع مبرمجي النظم الذين كانوا يعملون لشركة آي بي إم، وبشكل أكثر تحديدا، كانوا يعملون على نظام مراقبة المحادثات/ النظام الافتراضي CMS/VM، وعلى نظام «معالجة المعاملات بشكل لحظي Real Time»، وعلى نظام «التحكم في بيانات العملاء»، وعلى ACP/TPF، وهو نظام مالي إداري -خاص بخطوط الطيران- بدأ في السبعينات وما زال يقوم بتشغيل نظم عالمية كبرى للتوزيع GDS ونظم بطاقات الائتمان حتى يومنا هذا.
وكان من الممكن أيضا أن يتم استخدام قدرات الماكرو المعالجة Processing فقط بحيث يقوم المُجمع بتوليد كود مكتوب بلغات مختلفة تماما، وعلى سبيل المثال، يمكن استخدام تلك التقنية في توليد نسخة من البرنامج مكتوبة بلغة كوبول عبر استخدام مجمع مزود ببرنامج ماكرو يحتوي على سطور من كود الكوبول، وأثناء وقت التجميع يمكن لمعاملات Operators أن توجه المُجمع لتوليد الكود بشكل تحكمي Arbitrary.
ويرجع سبب ذلك، كما تم إدراكه في السبعينات، أن مفهوم «معالجة الماكرو» Macro Processing يختلف عن مفهوم التجميع، حيث يشير المصطلح الأول في لغتنا الحاسوبية الحديثة إلى إمكانيات في برامج معالجة الكلمات، معالجة النصوص، أكثر من إشارته إلى توليد الكود. وحقيقة، فإن مفهوم «معالجة الماكرو» قد ظهر -وما زال يظهر- في لغة البرمجة «سي» C، حيث تدعم «تعليمات ما قبل المعالجة» Preprocessor Instructions من أجل تحديد قيم المتغيرات Set Variables. لاحظ أنه على عكس الأنواع المحددة لمعالجات الماكرو التي تم ذكرها والتي تعمل داخل المُجمعات، فإن المعالج القبيل للغة الـ C لم يكن Turing-Complete (متكامل مع معايير تورنغ) لنقص إمكانية «الدوارات» Loops أو الذهاب إلى تعليمة محددة عبر أمر Go To.
وبالرغم من قوة معالجة الماكرو، فقد تم إهمالها في اللغات عالية المستوى، بينما تظل مهمة وموجودة في المُجمعات Assemblers.
وذلك يرجع إلى الحيرة والارتباك التي وقع فيهما العديد من المبرمجين، حيث شكل لهم «تعويض معاملات» الماكرو مشكلة، ولم يستطيعوا فك الخلط بين معالجة الماكرو أثناء التجميع وأثناء التنفيذ.
ويتم استبدال معاملات الماكرو Parameter Substitution بشكل صارم عبر الاسم فقط: في وقت معالجة الماكرو، يتم استبدال قيمة المعامل باسم المعامل نصيا.وينتج أشهر صنف من الأخطاء Bugs عبر استخدام المعامل والذي كان يعبر -نفسه- عن Expression وليس عن اسم بسيط، في حين أن كاتب الماكرو يتوقع اسما Name.وفي الماكرو :
foo: macro a

load a*b القصد هنا هو أن يقوم المنادي Caller بتوفير اسم للمتغير، ويتم ضرب المتغير «العالمي» Global أو الثابت "b" في "a".إذا تم استدعاء foo مع المعامل a-c، سيقوم الماكرو بالتوسع بشكل غير متوقع.
ولتجنب هذا الأمر، تعلم مستخدمو «معالجة الماكرو» أن يقوموا بحصر المعاملات داخل تعريفات الماكرو Macro Definitions، ثم يكون على المناديين Callers أن يفعلوا المثل مع معاملاتهم «الحقيقية» Actual Parameters.
وقد قدمت لغات الـ PL/I وC ميزة الماكرو، لكن هذه الميزة كانت خطرة ولم تستخدم بشكل كافي لأنها لم تكن تعالج سوى النصوص. ومن ناحية أخرى، حافظ لغات الذكاء الصناعي Homoiconic مثل Lisp وProlog وForth على إمكانيات ماكروهات لغات التجميعات خاصتها، لأنهم جميعا قادرين على معالجة الكود الخاص بهم مثلهم مثل البيانات.