defer گو توی کامپایلر تایپاسکریپت
خلاصهٔ کاملتر
نویسنده تو این پست میگه دلش میخواسته ببینه اضافهکردن دستور defer زبان Go به کامپایلر تایپاسکریپت چقدر سخته، ولی تا کارو تموم کرده به این نتیجه رسیده که این قابلیت احتمالاً اصلاً نباید وجود داشته باشه. تو Go، defer اجرای یه فراخوانی رو تا لحظهٔ تمومشدن تابع دربرگیرنده عقب میندازه؛ کاربرد اصلیش اینه که گرفتن یه منبع و آزادکردنش کنار هم بمونن، مثل گرفتن و رهاکردن یه سمافور.
تایپاسکریپت معادل دقیقی برای این کار نداره و معمولاً باید سراغ try/finally رفت که به گفتهٔ نویسنده زیاد خوشگل نیست. هدف این بوده که بشه مستقیم همچین کدی نوشت:
async function readFile(path: string) {
await sema.acquire();
defer sema.release(); // New!
// ... use resource
}خود tsc عمدتاً یه موتور تحلیل ایستاست؛ سختی کارش تایپچککردن یه زبان ذاتاً پویا و کامپایل افزایشی خیلی سریع برای IDEهاست. خبر خوب اینه که برای اضافهکردن defer لازم نیست وارد تایپها بشیم: tsc از قبل کلی تبدیل AST به AST داره — مثلاً ?. رو به عبارت شرطی تبدیل میکنه — پس فقط یه بازنویسی درخت دیگه لازمه.
کار از پارسر شروع میشه: یه گره به اسم DeferStatement به فهرست syntax kindها اضافه میشه که یه عملوند عبارتی میگیره. بعد چند بررسی تو چکر لازمه؛ مثلاً defer باید داخل بدنهٔ یه تابع باشه و عبارتش قابل فراخوانی باشه، وگرنه خطای گرامری «defer فقط داخل بدنهٔ تابع مجازه» گرفته میشه. آخرش هر تابعی که defer داره اینشکلی بازنویسی میشه:
function f() {
const __defers = [];
try {
__defers.push(() => cleanup());
work();
} finally {
// Pop and invoke
}
}حرف آخر نویسنده اینه که با اینکه این هک کار میکنه، defer احتمالاً نباید به تایپاسکریپت اضافه بشه. دستاورد واقعی این آزمایش بیشتر نشوندادن اینه که ساختار tsc چقدر برای اضافهکردن نحو تازه آمادهست، نه اینکه زبان به این کلیدواژه نیاز داره.
نکات کلیدی:
- defer تو Go اجرای یه فراخوانی رو تا پایان تابع عقب میندازه و گرفتن و آزادکردن منبع رو کنار هم نگه میداره
- تایپاسکریپت معادلی نداره و راهحل رایجش try/finally ـه
- اضافهکردنش به tsc یعنی یه گره DeferStatement تو پارسر، چند بررسی تو چکر و یه تبدیل AST به AST
- کد خروجی از یه آرایهٔ __defers بهعلاوهٔ try/finally استفاده میکنه
- نویسنده با وجود کارکردن این هک، معتقده این قابلیت بهتره به زبان اضافه نشه




