Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

ما هو المترجم (Compiler)؟

المترجم (compiler) برنامج يحوّل الكود المصدري المكتوب بلغة برمجة إلى لغة الآلة، أو إلى صيغة أدنى مستوى مثل البايت كود، قبل تشغيل البرنامج. وبعد ذلك يعمل البرنامج المترجَم دون الحاجة إلى الكود المصدري الأصلي.

بقلم Kevin Spektor, شريك مؤسس ورئيس قسم التكنولوجيا (CTO)

آخر تحديث 24 سبتمبر 2026

الكود المصدري
  1. 1print("Hello")
  2. 2total = 2 + 3
  3. 3print(total)
  4. 4print("Done")
الناتج
مرات الترجمة0
مرات التشغيل0

ترجم مرة واحدة، ثم شغّل البرنامج كما تشاء من المرات: يزداد عدّاد التشغيل، ولا يزداد عدّاد الترجمة. فعّل الخطأ الإملائي وسيرفض المترجم البرنامج كله، فلا يُطبع شيء.

احفظ برنامج C هذا باسم hello.c:

#include <stdio.h>

int main(void) {
    int price = 4;
    printf("Total: %d\n", price * 3);
    return 0;
}

ثم اكتب gcc hello.c -o hello. لا يحدث شيء ظاهر للحظة، ثم يظهر ملف جديد اسمه hello بجوار ملفك المصدري. هذا الملف هو ناتج المترجم: لغة آلة يستطيع معالجك تنفيذها. احذف hello.c وسيظل ./hello يعمل، لأن كل ما يحتاجه البرنامج قد تُرجم بالفعل.

gcc hello.c -o hello
./hello
Total: 12

كيف يعمل المترجم خطوة بخطوة

يقرأ المترجم الكود المصدري كنص عادي ويعالجه على مراحل. لنأخذ السطر الواحد total = price * 3:

  1. التحليل المعجمي (lexical analysis). يُقسَّم النص إلى رموز (tokens)، وهي "كلمات" اللغة: الاسم total، والعامل =، والاسم price، والعامل *، والعدد 3. وتُحذف المسافات والتعليقات في هذه المرحلة.
  2. التحليل النحوي (parsing). تُرتَّب الرموز في شجرة صياغة تسجّل البنية: عملية إسناد قيمتها حاصل ضرب price في 3. والكود الذي يخالف قواعد اللغة يتوقف هنا مع خطأ في الصياغة.
  3. التحليل الدلالي (semantic analysis). يفحص المترجم المعنى: هل price معرَّف؟ هل الأنواع متوافقة؟ هل الدالة المستدعاة موجودة؟
  4. التحسين (optimization). يُعاد كتابة البرنامج ليعمل أسرع أو يستهلك ذاكرة أقل دون تغيير ما يفعله. قد يصبح x * 2 تعليمة إزاحة واحدة، ويُحذف الكود الذي لا يمكن أن يُنفَّذ أبدًا.
  5. توليد الكود (code generation). يكتب المترجم الناتج لمنصة مستهدفة: لغة آلة لمعالجات x86-64 أو ARM، أو بايت كود لآلة افتراضية.

وفي C وC++ توجد خطوة أخيرة هي الربط (linking)، تجمع ملفاتك المترجَمة مع كود المكتبات (مثل printf من مكتبة C القياسية) في ملف تنفيذي واحد. يشغّل gcc الرابط نيابةً عنك، ولهذا تبدو العملية كأنها أمر واحد.

توفّر Python المرحلتين الأوليين كوحدات قياسية، فيمكنك مشاهدتهما تعملان على مدخلات حقيقية:

NAME 'total'
OP '='
NAME 'price'
OP '*'
NUMBER '3'
Assign(
  targets=[
    Name(id='total', ctx=Store())],
  value=BinOp(
    left=Name(id='price', ctx=Load()),
    op=Mult(),
    right=Constant(value=3)))

هذه الشجرة هي ما تعمل عليه بقية مراحل المترجم. لم تعد تهتم بالمسافات أو الأسطر الجديدة، بل بالبنية فقط: أسند إلى total نتيجة ضرب price في 3.

وقت الترجمة: أخطاء تُكتشف قبل تشغيل البرنامج

لأن المترجم يقرأ البرنامج كله قبل تشغيل أي جزء منه، يستطيع رفض الأخطاء مبكرًا. في هذا المثال لا يُنفَّذ أي سطر من أسطر print الثلاثة داخل source، ولا حتى الأول، لأن مترجم Python يرفض النص قبل بدء التنفيذ:

Rejected before running anything:
  '(' was never closed (line 3)

مترجمات اللغات ذات الأنواع الثابتة (statically typed) تكتشف أكثر من أخطاء الصياغة. هذا السطر من C، في ملف اسمه bad.c، صحيح نحويًا، لكنه يخزّن نصًا في متغير صحيح:

int count = "five";

يتوقف GCC 14 وما بعده مع خطأ:

bad.c:4:17: error: initialization of 'int' from 'char *' makes integer from pointer without a cast [-Wint-conversion]

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

أمثلة على المترجمات

المترجميقرأيُنتج
GCC وClangC وC++لغة آلة لمعالجات x86-64 وARM وغيرها
MSVC (Microsoft Visual C++)C وC++ملفات تنفيذية لنظام Windows (.exe و.dll)
javacJavaبايت كود JVM (ملفات .class)
rustcRustلغة آلة
go buildGoملف تنفيذي واحد
tscTypeScriptJavaScript

يُظهر صفّان من الجدول أن "لغة الآلة" ليست الناتج الوحيد الممكن. يُنتج javac بايت كود تشغّله آلة Java الافتراضية، وهي جزء من بيئة تشغيل Java. ويحوّل tsc لغة TypeScript إلى JavaScript، وهي لغة عالية المستوى أخرى؛ والمترجم الذي يفعل ذلك يُسمّى غالبًا محوّلًا (transpiler).

لغة الآلة المترجَمة مرتبطة بعائلة معالجات واحدة ونظام تشغيل واحد. البرنامج المترجَم لنظام Windows على x86-64 لا يعمل على جهاز Mac بشريحة Apple من سلسلة M؛ عليك ترجمة الكود المصدري نفسه من جديد لكل منصة.

مترجم أم مفسر

المفسر يشغّل الكود المصدري مباشرة بدلًا من إنتاج ملف برنامج منفصل، وهكذا تُشغَّل Python وRuby عادةً. ومعظم أدوات اللغات الحديثة تستخدم الفكرتين معًا: CPython يترجم ملفك إلى بايت كود ثم يفسّره، وJVM ومحرك V8 الخاص بـ JavaScript يترجمان الكود كثير الاستخدام إلى لغة الآلة أثناء تشغيل البرنامج. الجدول الكامل للمقارنة موجود في صفحة المترجم مقابل المفسر.

مفاهيم خاطئة شائعة

  • "إذا تُرجم البرنامج فهو يعمل." المترجم يتحقق من أن البرنامج صالح، لا من أنه صحيح. الأخطاء المنطقية وأعطال وقت التشغيل مثل القسمة على صفر تمرّ دون أن يكتشفها.
  • "Python لا تُترجَم." يترجم CPython كل ملف إلى بايت كود قبل تشغيله. ملفات .pyc في مجلدات __pycache__ هي ذلك البايت كود، محفوظًا للوحدات التي يستوردها برنامجك حتى يتخطى التشغيل التالي هذه الخطوة.
  • "المترجم الإلكتروني (online compiler) مترجم." المواقع التي تشغّل كودك في المتصفح ترسله إلى خادم يشغّل سلسلة الأدوات كاملة (المترجم والرابط والبرنامج نفسه) ثم يعيد الناتج. المترجم قطعة واحدة من ذلك.
  • "الكود المترجَم يعمل في أي مكان." إنه يعمل على المعالج ونظام التشغيل اللذين بُني لهما. وقابلية النقل تأتي من إعادة الترجمة، أو من آلة افتراضية مثل JVM.

إلى أين بعد ذلك

توثيق C يُظهر المترجم في الاستخدام اليومي: صفحة كيف تترجم برنامج C وتشغّله تشرح المعالجة المسبقة والترجمة والتجميع والربط بأوامر gcc حقيقية. ولترى الطريقة الأخرى لتشغيل الكود، اقرأ المترجم مقابل المفسر، ثم بيئة التشغيل لتعرف ما يحيط بالبرنامج بعد أن يبدأ. ودورة C مكان جيد للتدرّب على لغة مترجَمة.

الأسئلة الشائعة

ما هي مكونات المترجم؟
يوصف المترجم عادةً بثلاثة أجزاء. الواجهة الأمامية (front end) تقرأ الكود المصدري، وتقسّمه إلى رموز (tokens)، وتحلّله إلى شجرة صياغة، وتفحص الأنواع. والجزء الأوسط (middle end) يحسّن صيغة وسيطة من البرنامج، والواجهة الخلفية (back end) تولّد لغة الآلة أو البايت كود للمعالج المستهدف.
كيف يستطيع المترجم أن يترجم نفسه؟
عبر ما يُسمّى الإقلاع الذاتي (bootstrapping). تُكتب النسخة الأولى من المترجم بلغة موجودة مسبقًا، أو يترجمها مترجم أقدم، ثم تُستخدم لترجمة النسخة التالية المكتوبة باللغة الجديدة نفسها. فمثلًا GCC مكتوب في معظمه بلغتي C وC++، ويُبنى بمترجم C++ موجود، غالبًا نسخة أقدم من GCC.
ما الفرق بين المترجم والمجمّع (assembler)؟
المترجم يترجم لغة عالية المستوى مثل C أو Rust، حيث يمكن أن يصبح سطر واحد تعليمات آلة كثيرة. أما المجمّع فيترجم لغة التجميع (assembly)، حيث يقابل كل سطر تقريبًا تعليمة آلة واحدة. وكثيرًا ما تُنتج مترجمات مثل GCC لغة التجميع أولًا ثم تسلّمها إلى المجمّع.
ما هو مترجم JIT؟
مترجم التنفيذ الفوري (just-in-time أو JIT) يحوّل الكود إلى لغة الآلة أثناء تشغيل البرنامج بدلًا من ترجمته قبل التشغيل. يراقب الأجزاء الأكثر تنفيذًا ويترجمها، فيصبح البرنامج الذي يعمل لفترة طويلة أسرع مع الوقت. وتستخدم JVM ومحرك V8 الخاص بـ JavaScript وPyPy جميعها ترجمة JIT.
هل أحتاج إلى تثبيت مترجم لتعلم البرمجة؟
ليس في البداية. المحررات التي تعمل في المتصفح ومنصات التجربة على الإنترنت تشغّل المترجم أو المفسر على خادم نيابةً عنك. وعندما تنتقل إلى جهازك الخاص، تحتاج C وC++ إلى مترجم مثل GCC أو Clang، وتحتاج Java إلى JDK، وتحتاج Python إلى مفسر Python.
Coddy programming languages illustration

تعلّم البرمجة مع Coddy

ابدأ الآن