Faragiri

همهٔ زبان‌ها

آموزش کامپایلر و مفسرکد چطور اجرا می‌شود

یک فراخوانی با یک ورودی کم، در سی و در پایتون. اولی هیچ فایلی تحویل نمی‌دهد و دومی تا روزی که سبد از پانصد هزار بگذرد درست کار می‌کند.

۵بخش
۴دقیقه خواندن
۴عمق

ترجمه کی انجام می‌شود

هر زبانی ترجمه می‌کند، و سر زمانش با هم اختلاف دارند

یک سر این خط، همه ترجمه پیش از اجرا تمام شده است؛ سر دیگر، هیچ‌کدامش پیش از اجرا انجام نشده.

همه‌اش پیش از اجراهمه‌اش در حین اجرا
  1. سی، ساخته با clangیک فایل اجرایی، و ماشین مقصد به کامپایلر نیازی ندارد
  2. Rustاز سی هم جلوتر، چون بررسی بیشتری همین بالا انجام می‌شود
  3. جاوا و سی‌شارپبایت‌کد از پیش، و بعد کامپایل دوباره در حین اجرا
  4. پایتونسر وارد کردن کامپایل می‌شود، و همان بایت‌کد است که اجرا می‌شود
  5. جاوااسکریپت در مرورگرمتن برنامه از شبکه می‌رسد و همان جا ترجمه می‌شود

جای‌گذاری‌ها مال همین صفحه است و استاندارد نیست. برای هرکدام پروژه‌ای هست که جایش را عوض می‌کند: سی مفسر دارد و پایتون کامپایلری دارد که فایل اجرایی می‌دهد.

یک تابع دو ورودی می‌خواهد و در یک جای برنامه با یک ورودی صدا زده شده است. در سی، clang -O2 gheymat.c -o gheymat با پیام error: too few arguments to function call, expected 2, have 1 می‌ایستد و هیچ فایل اجرایی ساخته نمی‌شود. در پایتون همان اشتباه، در همان جا، اجرا می‌شود و عدد درست را چاپ می‌کند. هیچ‌کدام از دیگری دقیق‌تر نیست؛ سر این دعوا دارند که اشتباه کی به شما برسد.

سه سطری از اسکریپت فاکتور که ماه‌ها جواب می‌دهد:

  • def mablagh_nahaei(asl, takhfif): که دو ورودی می‌خواهد
  • if jam > 500000: شرطی که فقط برای سبدهای بزرگ درست است
  • return mablagh_nahaei(jam) فراخوانی با یک ورودی، و همین اشتباه است

با یک سبد دو قلمی، python3 faktor.py عدد ۲۷۷۰۰۰ را چاپ می‌کند و با کد صفر بیرون می‌آید. روزی که جمع سبد از پانصد هزار بگذرد آن شاخه گرفته می‌شود و پیام سرانجام می‌رسد: TypeError: mablagh_nahaei() missing 1 required positional argument، درست، دقیق، و ماه‌ها دیر.

سی همان کد را بدون یک بار اجرا رد می‌کند

نکته اینجاست که آن شاخه در سی هم اجرا نشد. لازم هم نبود: بررسی روی متن برنامه انجام شد، نه روی یک اجرا. کامپایلر می‌تواند برنامه‌ای را رد کند که آن شاخه در آن هرگز اجرا نمی‌شود، و همین چیزی است که کامپایل کردن را از تست کردن جدا می‌کند.

اگر فقط همین بررسی را بخواهید و فایل اجرایی نخواهید، clang -fsyntax-only gheymat.c همان خطا را می‌دهد و به ساخت کاری ندارد. پایتون معادلی برای این بررسی ندارد: py_compile فقط نحو را می‌بیند و درباره نام‌های داخل تابع چیزی نمی‌گوید.

چیزی که آخر کار در دست دارید

تفاوت دوم این است که از ترجمه چه باقی می‌ماند. clang یک فایل اجرایی ۱۶ کیلوبایتی تحویل می‌دهد که روی ماشینی بدون کامپایلر هم راه می‌افتد. پایتون چیزی تحویل نمی‌دهد که بشود فرستاد، چون ماشینی که اسکریپت را اجرا می‌کند باید خودش پایتون داشته باشد و ترجمه بخشی از اجراست.

این را می‌شود دم در اندازه گرفت. روی یک مک‌بوک با تراشه M1 Max، در تاریخ ۲۰۲۶-۰۹-۰۳ و با بهترین بیست‌وپنج اجرا، بالا آمدن یک فایل خالی پایتون حدود ۲۵ میلی‌ثانیه طول می‌کشد و یک برنامه کامپایل‌شده بی‌کار حدود چهار میلی‌ثانیه. بیست میلی‌ثانیه داخل اسکریپتی که یک دقیقه کار می‌کند هیچ است، و همان بیست میلی‌ثانیه کل بودجه دستوری است که قرار است در یک حلقه هزار بار صدا زده شود. همین است که یک برنامه واحد را هم انتخاب درست می‌کند و هم غلط، بسته به اینکه چند بار شروع می‌شود. از فایل متنی تا دستوری که پردازنده اجرا می‌کند بقیه این هزینه را جا به جا می‌کند.

پایتون هر دو کار را می‌کند، به همین ترتیب

این دو کلمه شبیه یک دوراهی به نظر می‌رسند و خود پایتون نقض آن است: پایتون اول کامپایل می‌کند و بعد همان را تفسیر می‌کند. جاوا و سی‌شارپ یک قدم جلوترند، چون ماشین مجازی بایت‌کد را در حین اجرا دوباره کامپایل می‌کند، این بار به دستور ماشین و فقط برای بخش‌هایی که داغ شده‌اند. جاوااسکریپت داخل مرورگر ته دیگر این خط است و متن برنامه‌اش از شبکه می‌رسد.

پرسش به‌دردبخور هرگز این نیست که یک زبان در کدام جعبه می‌نشیند، بلکه این است که ماشین اجازه دارد پیش از اجرای اولین سطر چقدر بداند. نزدیک به ماشین، و هیچ چیز پنهان نیست حالت حدی یک سر این خط است، و نوع‌ها روی جاوااسکریپت، و چیزی که می‌گیرند زبانی است که همان بررسی زودهنگام را به زبانی بسته که هرگز نداشتش.

جایی که کار گیر می‌کند، نصب زنجیره ابزار است نه زبان

کسی که از ایران شروع می‌کند تقریباً همیشه اول پایتون را می‌بیند، چون یک اسکریپت را در مرورگر هم می‌شود اجرا کرد. اولین برخورد با یک زبان کامپایلی معمولاً سر دانلود ابزار می‌شکند و نه سر زبان: ابزارهای خط فرمان اکسکد از سایت اپل و بسته‌های توسعه از مخزن‌های خودشان بی‌واسطه بالا نمی‌آیند، و نتیجه‌ای که آدم می‌گیرد این است که «زبان‌های کامپایلی سخت‌اند». نیستند. یک بار که کامپایلر روی ماشین نشست هیچ‌کدام از دستورهای این صفحه به شبکه کاری ندارند. سختی مال مرحله‌ای بود که اصلاً جزو زبان نبود.

ابزار، و سالی که این حرف درست است

در سال ۲۰۲۶ روی یک مک به‌روز، clang همان Apple clang 21.0.0 است و رایگان همراه ابزارهای خط فرمان اکسکد می‌آید؛ سال‌ها پیش جای gcc را به‌عنوان کامپایلر سیستم گرفت، و به همین دلیل است که روی مک هر دو نام به یک برنامه می‌رسند. پرچمی که از این صفحه ارزش سپردن دارد -fsyntax-only است، چون جای «بسازیم ببینیم چه می‌گوید» را می‌گیرد و چیزی هم نمی‌سازد. پایتون 3.14 نسخه‌ای است که در ۲۰۲۶ باید رویش بود و جانشین 3.13 شد.

سوال بعدی این است که وقتی برنامه بالا آمد آن مقدارها کجا نشسته‌اند و چه کسی جمعشان می‌کند، که مقدارها کجا می‌نشینند و چه وقت آزاد می‌شوند جوابش است. و اگر همین خطای کم بودن ورودی را می‌خواهید پیش از رسیدن کاربر بگیرید بی‌آنکه زبان عوض کنید، کاری که سی مجانی انجام می‌دهد را باید با یک چیز در هر بار، سریع و جدا خرید.

کنار این

بالای این