مفسر پایتون تو ۱۰۲۴ بایت کد C
خلاصهٔ کاملتر
نویسنده میگه آخر هفتهها برای اینکه حس آدم بودن داشته باشه دستی کد میزنه، و چالش این بارش این بوده که یه مفسر پایتون رو تو ۱۰۲۴ بایت کد C جا بده، بدون ماکروبازی و بدون کتابخونهٔ کمکی. هدف پیادهسازی کل زبان نبوده، فقط اون تیکههایی که شبیه پایتون به نظر میرسن: def، دونقطه، تورفتگی و if بدون پرانتز. تلاش اولش با سقف ۵۱۲ بایت شکست خورد و تهش فقط یه ماشینحساب از آب دراومد.
معماریش عمداً خام و سادهست. کل وضعیت برنامه تو چندتا متغیر سراسری نگه داشته میشه: یه آرایهٔ ثابت ۹۹۹ کاراکتری برای خود سورس، و یه symbol table (یعنی جدولی که مقدار متغیرها توش ذخیره میشه) با ۲۵۶ خونه.
char src[999]; /* Entire program without most spaces. */
int vars[256]; /* Symbol table. */
int pos; /* Next character in src. */
int ch; /* Current character in src. */چون اسم متغیرها فقط یه حرف کوچیکه، مفسر لازم نیست دنبال چیزی بگرده و مستقیم با کد اسکی همون حرف سراغ خونهش میره. خبری از AST و بایتکد هم نیست؛ پارسر بازگشتی همونجا که میخونه، اجرا هم میکنه. هیچ مدیریت خطایی وجود نداره و مفسر فرض میکنه کلمههای کلیدی درست تایپ شدن.
کنترل جریان هم با همین منطق حل شده. تابع اجرای بلاک تا وقتی جلو میره که تورفتگی کم بشه، بعد برمیگرده و بقیهش با فراخوانکنندهست؛ یعنی عملاً از پشتهٔ خود برنامهٔ C برای بازگشت استفاده میشه. حلقهها هم چون چیزی کامپایل نمیشه، محل شرط رو یادداشت میکنن و بعد از هر بار اجرای بدنه به همون نقطه برمیگردن و سورس رو دوباره پارس میکنن. توابع دقیقاً همینطورن: محل تعریف تو جدول نمادها میمونه و بعد از اجرا مفسر به محل فراخوانی برمیگرده.
مرحلهٔ آخر کوچیککردن کد بوده. نویسنده میگه ترفندها رو از یه پست قدیمی Stack Overflow دربارهٔ code golf تو C برداشته: اسمهای تکحرفی، تکیه بر صفر بودن خودکار متغیرهای سراسری، این قانون C89 که نوع اعلامنشده رو int فرض میکنه، عملگر سهتایی و کاما بهجای if، و عملیات بیتی بهجای منطقی. مثلاً تابع پرش تا آخر خط اینطوری فشرده شده:
Y(){c&&c-10&&Y(G());}نسخهٔ خوانا بیشتر از ۴۸۰۰ بایته و نسخهٔ فشرده دقیقاً ۱۰۲۴ بایت. برای اینکه جا بشه، مقایسهها آخرین چیزی بودن که تا حد زیادی قربانی شدن، چون truthiness عددی (یعنی صفر بودن یا نبودن مقدار) بدون اونا هم کار میکنه. نویسنده میگه اگه فقط اجرای fizzbuzz مهم بود، احتمالاً زیر ۸۰۰ بایت هم میشد رفت. هر دو نسخه روی GitHub در دسترسن.
نکات کلیدی:
- نسخهٔ فشردهٔ مفسر دقیقاً ۱۰۲۴ بایت کد C و نسخهٔ خوانا بیش از ۴۸۰۰ بایته
- سورس برنامه تو یه آرایهٔ ثابت ۹۹۹ کاراکتری و متغیرها تو جدولی با ۲۵۶ خونه نگه داشته میشن
- اسم متغیرها فقط یه حرف کوچیکه تا جستوجوی جدول نمادها کلاً حذف بشه
- حلقهها و توابع با پرش به عقب و پارس دوبارهٔ سورس اجرا میشن، بدون AST و بدون بایتکد
- هیچ مدیریت خطایی وجود نداره و مفسر فرض میکنه کد ورودی درسته
- if/else، while، for x in range(y)، تابع بدون آرگومان (حتی بازگشتی) و print پشتیبانی میشن




