آزمون مرد یا پسر

**آزمون مرد یا پسر** توسط دانشمند کامپیوتر دونالد کنوت به عنوان ابزاری برای ارزیابی پیاده سازی زبان برنامه نویسی ALGOL 60 پیشنهاد شد. هدف از این آزمون تشخیص کامپایلرهایی بود که به درستی «مرجع بازگشتی و غیر محلی » را از آنهایی که این کار را انجام نداده بودند، پیاده سازی کردند. 

تعداد زیادی مترجم ALGOL60 وجود دارند که برای مدیریت صحیح مراجع بازگشتی و غیر محلی طراحی شده اند، و من فکر کردم شاید یک برنامه آزمایشی کوچک ممکن است مفید باشد. از این رو من روال ساده زیر را نوشته ام که ممکن است کامپایلر مرد را از کامپایلر پسر جدا کند.

- دونالد کنوت

## مثال کنوت
در ALGOL 60 :
```pascal
begin
  real procedure A(k, x1, x2, x3, x4, x5);
  value k; integer k;
  real x1, x2, x3, x4, x5;
  begin
    real procedure B;
    begin k := k - 1;
          B := A := A(k, B, x1, x2, x3, x4)
    end;
    if k ≤ 0 then A := x4 + x5 else B
  end;
  outreal(1, A(10, 1, -1, -1, 1, 0))
end
```
این یک درخت از فریم‌های فراخوانی *B* ایجاد می‌کند که به یکدیگر و فریم‌های فراخوانی حاوی *A* اشاره می‌کنند، که هر کدام کپی مخصوص به *خود* را دارند که هر بار که *B* مرتبط فراخوانی می‌شود، تغییر می‌کند. تلاش برای کار بر روی کاغذ احتمالا بی نتیجه است، اما برای *k*&nbsp;=&nbsp;10، پاسخ صحیح -67 است، علیرغم این واقعیت که کنوت در مقاله اصلی آن را 121- حدس زده است. حتی ماشین‌های مدرن به‌سرعت فضای پشته‌ای برای مقادیر بزرگ‌تر *k* که در جدول زیر نشان داده شده‌اند تمام می‌شود (  ).

## توضیح
سه ویژگی Algol در این برنامه استفاده شده است که پیاده سازی صحیح آنها در یک کامپایلر دشوار است:

# **تعاریف [[Nested function|تابع تودرتو]]** : از آنجایی که *B* در بافت محلی *A* تعریف می شود، بدنه *B* به نمادهایی دسترسی دارد که محلی برای *A* هستند - به ویژه *k* که آنها را اصلاح می کند، اما *x1* ، *x2* ، *x3* ، *x4* و *x5 را* نیز تغییر می دهد. این کار در پاسکال نوادگان الگول ساده است، اما در نواد اصلی دیگر الگول C امکان‌پذیر نیست (بدون شبیه‌سازی دستی مکانیزم با استفاده از عملگر آدرس-از C، انتقال نشانگرها به متغیرهای محلی بین توابع).
# **[[توابع کلاس اول|ارجاعات تابع]]** : *B* در فراخوانی بازگشتی `A(k, B, x1, x2, x3, x4)` فراخوانی به *B* نیست، بلکه ارجاعی به *B* است، که تنها زمانی فراخوانی می شود که *k* بزرگتر از صفر باشد. این در پاسکال استاندارد ( ISO 7185 ) و همچنین در C ساده است. برخی از انواع پاسکال (مثلاً نسخه‌های قدیمی‌تر توربو پاسکال ) از مراجع رویه پشتیبانی نمی‌کنند، اما وقتی مجموعه توابعی که ممکن است به آنها ارجاع داده شود از قبل شناخته شده باشد (در این برنامه فقط *B* است)، می‌توان این کار را انجام داد.
# **دوگانه گرایی ثابت/توابع** : پارامترهای *x1* تا *x5* *A* ممکن است ثابت های عددی یا ارجاعاتی به تابع *B* باشند - عبارت `x4 + x5` باید برای رسیدگی به هر دو حالت آماده شود، به گونه ای که گویی پارامترهای رسمی *x4* و *x5* با پارامتر واقعی متناظر ( فراخوانی با نام ) جایگزین شده اند.  این احتمالاً در زبان‌های تایپ‌شده استاتیک بیشتر از زبان‌های تایپ شده پویا مشکل‌ساز است، اما راه‌حل استاندارد این است که ثابت‌های 1، 0، و 1 را در فراخوانی اصلی *A* به‌عنوان توابعی بدون آرگومان‌هایی که این مقادیر را برمی‌گردانند، دوباره تفسیر کنیم.

با این حال، این چیزها چیزی نیست که آزمون در مورد آن است. آنها صرفاً پیش نیازهایی برای معنی دار بودن آزمون هستند. آنچه *در مورد* آزمون است این است که آیا ارجاعات مختلف به *B* به نمونه *صحیح* *B* می رسد - نمونه ای که به همان نمادهای محلی *A* دسترسی دارد که *B* که مرجع را ایجاد کرده است. به عنوان مثال، یک کامپایلر "پسر" ممکن است به جای آن برنامه را کامپایل کند تا *B* همیشه به بالاترین فریم تماس *A* دسترسی داشته باشد.

## جستارهای وابسته
* مشکل فونارگ
* دستگاه جنسن

## پیوند به بیرون

* نمونه های تست مرد یا پسر در بسیاری از زبان های برنامه نویسی

## منابع


رده:مقاله‌های ایجادشده توسط ایجادگر
رده:کامپایلرسازی
رده:معرفی‌شده‌های مرتبط با رایانه در ۱۹۶۴ (میلادی)
رده:دانلد کنوت
رده:طراحی زبان‌های برنامه‌نویسی