Відмінність інтерпретованого та складеного коду, ймовірно, вигадка, як підкреслено коментарем Рафаеля :
the claim seems to be trivially wrong without further assumptions: if there is
an interpreter, I can always bundle interpreter and code in one executable ...
Справа в тому, що код завжди інтерпретується програмним забезпеченням, обладнанням або комбінацією обох, і процес компіляції не може визначити, яким він буде.
Ви сприймаєте як компіляцію - процес перекладу з однієї мови (для джерела) на іншу мову (для цілі). І, інтерпретатор для , як правило , відрізняється від перекладача для .T S TSТSТ
Складена програма переводиться з однієї синтаксичної форми в іншу синтаксичну форму , таким чином, що, з огляду на передбачувану семантику мов і , і мають однакову обчислювальну поведінку, до кількох речей, які ви зазвичай намагаєтеся зробити зміни, можливо для оптимізації, такі як складність або проста ефективність (час, простір, поверхня, енергоспоживання). Я намагаюся не говорити про функціональну еквівалентність, оскільки це вимагало б точних визначень.P T S T P S P TПSPTSTPSPT
Деякі компілятори фактично використовуються просто для зменшення розміру коду, а не для «покращення» виконання. Це стосувалося мови, що використовується в системі Платона (хоча вони не називали її складовою).
Ви можете розглянути ваш код повністю складений , якщо після процесу компіляції, вам більше не потрібен перекладач для . Принаймні, це єдиний спосіб я можу прочитати ваше запитання як інженерне, а не теоретичне питання (оскільки, теоретично, я завжди можу відновити перекладача).S
Одна річ, яка може викликати проблему, афаїк, - це метациркулярність . Саме тоді програма маніпулює синтаксичними структурами на своїй власній мові джерела , створюючи фрагмент програми, який потім інтерпретується так, ніби вони були частиною вихідної програми. Оскільки ви можете створити довільні фрагменти програми мовою в результаті довільних обчислень, що маніпулюють безглуздими синтаксичними фрагментами, я б припустив, що ви можете зробити майже неможливим (з інженерної точки зору) компілювати програму мовою , так що тепер генерувати фрагменти . Значить, знадобиться інтерпретатор для або, принаймні, компілятор від доS T T S S T SSSTTSST для логічного складання створених фрагментів у (див. Також цей документ ).S
Але я не впевнений, як це можна формалізувати належним чином (і не маю часу на це зараз). І неможливе велике слово для проблеми, яка не формалізована.
Подальші зауваження
Додано через 36 годин. Ви можете пропустити це дуже довге продовження.
Чимало коментарів до цього питання показують два погляди на проблему: теоретичний погляд, який вважає її безглуздою, та інженерний погляд, який, на жаль, не так легко формалізується.
Є багато способів поглянути на інтерпретацію та компіляцію, і я спробую замалювати декілька. Я спробую бути настільки ж неформальним, наскільки вмію
Діаграма надгробних плит
Однією з ранніх формалізацій (з початку 1960-х до кінця 1990-х років) є діаграми T або
Tombstone . Ці діаграми представлені в складових графічних елементах мовою реалізації інтерпретатора або компілятора, мовою-джерелом, що інтерпретується або компілюється, та цільовою мовою у випадку компіляторів. Більш досконалі версії можуть додавати атрибути. Ці графічні зображення можна розглядати як аксіоми, правила виводу, застосовні для механічного отримання генерації процесорів із підтвердження їх існування з аксіоми, а-ля Curry-Howard (хоча я не впевнений, що це було зроблено в шістдесяті роки :).
Часткова оцінка
Ще один цікавий погляд - парадигма часткової оцінки . Я сприймаю просте уявлення програм як свого роду реалізацію функції, яка обчислює відповідь на деякі вхідні дані. Потім інтерпретатор
для мови являє собою програму, прийняти програму ,
записану в і дані для цієї програми, і обчислює результат в відповідно до семантикою . Часткове оцінювання - це методика спеціалізації програми з двох аргументів та , коли відомий лише один аргумент, скажімо . Наміром є швидша оцінка, коли ви нарешті отримаєте другий аргумент S p S S d S a 1 a 2 a 1 a 2 a 2 a 1 a 1 a 2ISSpSSdSa1a2a1a2 . Особливо корисно, якщо змінюється частіше, ніж оскільки вартість часткової оцінки може бути амортизована для всіх обчислень, де змінюється лише .a2a1a1a2
Це часта ситуація в розробці алгоритмів (часто це тема першого коментаря до SE-CS), коли якась статична частина даних попередньо обробляється, так що вартість попередньої обробки може бути амортизована у всіх програмах алгоритму з більш змінними частинами вхідних даних.
Це також сама ситуація перекладачів, оскільки перший аргумент - це програма, яка виконується, і зазвичай виконується багато разів з різними даними (або підрозділи виконуються багато разів з різними даними). Отже, природною ідеєю є спеціалізація перекладача для більш швидкої оцінки певної програми, частково оцінивши її в цій програмі як перший аргумент. Це може розглядатися як спосіб складання програми, і була проведена значна дослідницька робота над складанням шляхом часткової оцінки перекладача за його першим (програмним) аргументом.
Теорема Smn
Приємним моментом у підході до часткової оцінки є те, що він бере свої корені в теорії (хоча теорія може бути брехуном), особливо в
теоремі Кміна Кліна . Я намагаюся тут дати інтуїтивне уявлення про це, сподіваючись, що це не засмутить чистих теоретиків.
Враховуючи нумерування Gödel рекурсивних функцій, ви можете розглядати як ваше обладнання, так що задане число Gödel
(читати код об'єкта ) програми є функцією, визначеною (тобто обчислюється кодом об'єкта на ваше обладнання).φ p φ p pφφpφpp
У своїй найпростішій формі теорема викладена у Вікіпедії таким чином (аж до невеликої зміни позначень):
Враховуючи нумерацію Gödel рекурсивних функцій, існує примітивна рекурсивна функція двох аргументів із наступною властивістю: для кожного числа Ґеделя часткової обчислюваної функції з двома аргументами, вирази і визначаються для однакових комбінацій натуральних чисел і , і їх значення рівні для будь-якого такого поєднання. Іншими словами, для кожного виконується наступна рівність функцій розширення :
φσqfφσ(q,x)(y)f(x,y)xyxφσ(q,x)≃λy.φq(x,y).
Тепер, взявши як інтерпретатор , як вихідний код програми , а як дані для цієї програми, ми можемо записати:
qISxpSydφσ(IS,pS)≃λd.φIS(pS,d).
φIS можна розглядати як виконання інтерпретатора
на обладнанні, тобто, як чорний ящик , готовий інтерпретувати програми , написані на мові .ISS
Функція може розглядатися як функція, яка спеціалізується на інтерпретаторі для програми , як у частковій оцінці. Таким чином може бути видно номер Gödel що має об'єктний код, який є компільованою версією програми .σISPSσ(IS,pS)pS
Отже, функція може розглядатися як функція, яка бере аргумент вихідний код програми
написана мовою , і повертає версію об'єктного коду для цієї програми Отже, - це те, що зазвичай називають компілятором.CS=λqS.σ((IS,qS)qSSCS
Деякі висновки
Однак, як я вже сказав: "теорія може бути брехуном", або насправді здається, що вона є однією. Проблема полягає в тому, що ми нічого не знаємо про функцію . Таких функцій насправді багато, і я здогадуюсь, що доказ теореми може використовувати для неї дуже просте визначення, яке, з інженерної точки зору, може бути не кращим, ніж рішення, запропоноване Рафаелем: просто зв'язати вихідний код з інтерпретатором . Це завжди можна зробити, щоб ми могли сказати: компіляція завжди можлива.q S I SσqSIS
Для формування більш обмежувального поняття, що таке компілятор, потрібен був би більш тонкий теоретичний підхід. Я не знаю, що, можливо, було зроблено в тому напрямку. Сама реальна робота з часткової оцінки є більш реалістичною з інженерної точки зору. Звичайно, існують інші методи написання компіляторів, включаючи вилучення програм із підтвердження їх специфікації, розроблені в контексті теорії типів, засновані на ізоморфізмі Кері-Говарда (але я виходжу за межі своєї компетенції) .
Моя мета тут полягала в тому, щоб показати, що зауваження Рафаеля не "божевільне", а розумне нагадування про те, що речі не очевидні і навіть не прості. Говорити про те, що щось неможливо - це сильне твердження, яке вимагає точних визначень та доказів, аби тільки точне розуміння того, як і чому це неможливо . Але побудувати належну формалізацію для висловлення такого доказу може бути досить складно.
Це говорить, навіть якщо певна особливість не є компілюваною, у розумінні, яку розуміють інженери, стандартні методи компіляції завжди можуть застосовуватися до частин програм, які не використовують таку функцію, як це зазначається у відповіді Жилла.
Дотримуючись ключових зауважень Жилла, що, залежно від мови, якась річ може бути виконана під час компіляції, а інша повинна бути виконана під час виконання, тому вимагаючи конкретного коду, ми можемо побачити, що концепція компіляції насправді неправильно визначені і, ймовірно, не визначені задовільним чином. Компіляція - це лише процес оптимізації, як я намагався показати у розділі часткової оцінки , коли я порівнював її зі статичною попередньою обробкою даних у деяких алгоритмах.
Як складний процес оптимізації, концепція складання фактично належить до континууму. Залежно від характеристик мови чи програми, деяка інформація може бути доступна статично і дозволяє краще оптимізувати. Інші речі потрібно перенести на час виконання. Коли справи стають по-справжньому поганими, все потрібно зробити під час виконання хоча б для деяких частин програми, і поєднання вихідного коду з інтерпретатором - це все, що ви можете зробити. Отже, ця група є лише нижнім кінцем цього континууму складання. Значна частина досліджень компіляторів - це пошук способів статично зробити те, що раніше робилося динамічно. Збір сміття під час збирання здається хорошим прикладом.
Зауважте, що сказати, що процес компіляції повинен створювати машинний код - це не допоможе. Це саме те, що пакет може виконувати як інтерпретатор, це машинний код (ну, річ може стати трохи складнішою при перехресній компіляції).