Інтерпретоване проти складеного: Корисна відмінність?


29

Тут задають багато питань щодо інтерпретованих та компільованих мовних програм. Мені цікаво, чи відрізняння насправді має сенс. (Насправді питання зазвичай стосуються мов, але вони дійсно замислюються над найпопулярнішими реалізаціями цих мов).

Сьогодні майже жодна реалізація не трактується суворо. тобто майже ніхто не розбирає і не запускає код один рядок. Крім того, реалізація, яка компілюється в машинний код, також стає менш поширеною. Все частіше компілятори націлені на якусь віртуальну машину.

Насправді більшість впроваджень сходяться на одній і тій же базовій стратегії. Компілятор виробляє байтовий код, який інтерпретується або компілюється в нативний код через JIT. Це дійсно поєднання традиційних ідей складання та інтерпретації.

Отже, я запитую: Чи корисна відмінність між інтерпретованими реалізаціями та складеною реалізацією в ці дні?


7
@DeadMG Не настільки новий, як вам здається: коротка історія тогочасного часу ...
yannis

4
@DeadMG З огляду на те, що більшість нових мов, впроваджених протягом останніх 10 років або в основному, працюють в основному на одній машині VM, я б сказав, що він має сенс. Звичайно, все ще є (і це буде протягом десятиліть) мов, зібраних на рідний код, і JIT залишиться розкішшю (чи ні, якщо хлопці з PyPy знайдуть свій шлях). Отже, так, можлива завищення, але я погоджуюся, що основний (на даний момент і найближчим часом) здається компілятором байт-коду + можливо JIT.

4
@DeadMG, ви повинні мати довгу білу бороду, якщо модель VM для вас "нова". P-codeбула введена вперше в 1966 році. IBM Aix існує з 1986 року.
SK-логіка

6
Такі речі, як оболонки Unix, Tcl та подібні, завжди були б чисто інтерпретовані, тому розрізнення має сенс, принаймні, в академічному КС. Але це правда, що коли кодери нарікають на перекладачів проти компіляторів, то вони в більшості випадків не мають сенсу.
SK-логіка

3
@ SK-логіка, я вважаю, що ваш коментар є кращою відповіддю, ніж будь-яка відповідь, яку насправді опублікував
Вінстон Еверт,

Відповіді:


23

Важливо пам’ятати, що інтерпретація та складання не є лише альтернативою один одному. Зрештою, будь-яка програма, яку ви пишете (включаючи одну, складену до машинного коду), буде інтерпретована. Інтерпретувати код просто означає взяти набір інструкцій і повернути відповідь.

З іншого боку, компілювання означає перетворення програми з однієї мови на іншу. Зазвичай передбачається, що коли відбувається компіляція, код компілюється на мову "нижчого рівня" (наприклад, машинний код, якийсь байт-код VM тощо). Цей скомпільований код все ще інтерпретується згодом.

Що стосується вашого питання про те, чи є корисна відмінність між інтерпретованими та складеними мовами, моя особиста думка полягає в тому, що кожен повинен мати базове розуміння того, що відбувається з кодом, який вони пишуть під час тлумачення. Отже, якщо їх код збирається JIT або кешується байт-кодом тощо, програміст повинен хоча б мати базове розуміння того, що це означає.


3
Так, програміст повинен мати базове розуміння. Але мені цікаво, чи складена / інтерпретована термінологія не перешкоджає цьому.
Вінстон Еверт

2
Дякую!! Інтерпретоване - це лише синонім "виконаного", і саме так запускаються всі програми.
садок

9

Відмінність має глибоке значення, оскільки складені мови обмежують семантику способами, що інтерпретовані мови не обов'язково. Деякі методи інтерпретації складно (практично неможливо) скласти.

Інтерпретований код може робити такі речі, як генерування коду під час виконання, і надавати видимість цього коду в лексичні прив'язки існуючої області застосування. Це один приклад. Інша полягає в тому, що перекладачів можна розширити інтерпретованим кодом, який може керувати тим, як оцінюється код. Це є основою для стародавніх Lisp "fexprs": функції, які викликаються з неоціненими аргументами і вирішують, що з ними робити (маючи повний доступ до необхідного середовища для проходження коду та оцінки змінних тощо). У складених мовах ви не можете реально використовувати цю техніку; ви замість цього використовуєте макроси: функції, які викликаються під час компіляції з неоціненими аргументами, і перекладаєте код, а не інтерпретуючи.

Деякі мовні реалізації будуються навколо цих методів; їхні автори відкидають складання як важливу мету, і скоріше сприймають цю гнучкість.

Інтерпретація завжди буде корисна як техніка завантаження компілятора. Для конкретного прикладу подивіться CLISP (популярна реалізація Common Lisp). У CLISP є компілятор, написаний сам по собі. Коли ви створюєте CLISP, цей компілятор інтерпретується під час початкових етапів створення. Він використовується для компіляції, а потім, як тільки він складається, компіляція виконується за допомогою компільованого компілятора.

Без ядра інтерпретатора вам потрібно буде завантажитися з деякими існуючими Lisp, як це робить SBCL.

За допомогою інтерпретації ви можете розробити мову з абсолютного нуля, починаючи з асемблерної мови. Розробіть основні підпрограми вводу / виводу та основної програми, а потім напишіть мову, яка ще не є машиною. Після того, як ви отримаєте eval, пишіть мовою високого рівня; машинне кодове ядро ​​виконує оцінку. Скористайтеся цим засобом, щоб розширити бібліотеку ще багатьма процедурами та написати компілятор. Використовуйте компілятор для компіляції цих підпрограм та самого компілятора.

Інтерпретація: важливий трамплін на шляху, що веде до складання!


1
ІМО, це найкраща відповідь. Я працюю над моєю власною іграшкою, а останній абзац описує спосіб її розробки. Це дійсно полегшує роботу над новими ідеями. Також +1 для згадування процесу завантаження CLISP.
Сінан

Теоретично будь-яка "інтерпретована" мова може бути перетворена на "компільовану", генеруючи файл EXE, що складається з інтерпретатора плюс вихідний код або байт-код для інтерпретованої програми. Хоча це може бути не дуже ефективно.
dan04

Прочитайте, як Wirth та ін винайшли P-код для спрощення перенесення PASCAL до нових архітектур машин. Це було на початку 1970-х.
Джон Р. Стром

1
Я підозрюю, що ваш початковий абзац плутає компіляцію та інтерпретацію зі статичною та динамічною поведінкою, але я виберу вас на користь сумнівів і просто попрошу приклад мови з семантикою, яку практично неможливо скласти. Що стосується завантаження компілятора, то правда, що перша реалізація повинна бути написана якоюсь іншою мовою, яку ви реалізуєте, але вона не повинна бути інтерпретатором, це може бути компілятор, написаний іншою мовою.
8bittree

1

Насправді багато мов реалізації все ще строго трактуються, ви просто можете їх не знати. Щоб назвати декілька: мови оболонки UNIX, оболонки Windows cmd та PowerScript, Perl, awk, sed, MATLAB, Mathematica тощо.


3
Я вважаю, що Perl компілюється всередині байт-коду, і принаймні Mathematica може бути скомпільований. І ніщо не диктує реалізацію awk та sed (я вважаю, що деякі GNU coreutils складають регулярні вирази для обмежених автоматів перед виконанням, що, певно, може перевести їх у "компіляцію до проміжного представлення, інтерпретувати цю" категорію).

1
Насправді я майже впевнений, що Perl, MATLAB, Mathematica всі збираються в байт-код. Я не знайомий з PowerScript, ти маєш на увазі Powershell? Якщо так, то, використовуючи CLR і так, використовується байт-код.
Вінстон Еверт

@WinstonEwert, вибачте, що я мав на увазі PowerShell. Я розумію, що переклад у проміжну форму не означає, що щось не інтерпретується. Гек, оригінальний інтерпретатор Dartmouth BASIC переклав джерело в лексеми перед інтерпретацією. Кожен із інструментів, про який я згадував, має режим, коли він 1) зчитує рядок джерела, 2) переводить цей рядок у виконувану форму (можливо, якийсь проміжний код, а не рідний код); 3) виконує код для цього рядка, 4) петля назад до 1). Це відповідає моєму розумінню перекладача.
Чарльз Е. Грант

2
Байт-код має на увазі компільований. Компілятор байт-кодів - це просто програма, яка бере джерело і перетворює його в байт-код. Отже, всі види використання байт-коду повинні включати компілятор байт-кодів. Але також слід інтерпретувати байт-код (або JITted). Тож все, що використовує байт-код, є перекладачем / компілятором гібридом.
Вінстон Еверт

4
Дійсно, моя річ у тому, що люди викидають твердження типу "інтерпретується python" та "Java компілюється", не розуміючи реалізації. Я шукаю, чи корисно навіть описати реалізацію в цих умовах. Правда зазвичай складніша, і намагатися звести її до інтерпретованого / складеного не корисно.
Вінстон Еверт

1

Я думаю: Абсолютно так .

Насправді більшість впроваджень сходяться на одній і тій же базовій стратегії

Дійсно, C ++ має на меті перенести на домі компілятора якусь концепцію високого рівня, яку зазвичай передають перекладачам, але вона залишається на стороні меншості ...


2
Зачекайте, поки Clang + LLVM стане найпопулярнішим інструментарієм компіляторів.
SK-логіка

@ SK-логіка, незважаючи на назву, я вважаю, що Clang + LLVM виробляє нативний код.
Вінстон Еверт

1
@Winston Ewert, лише якщо ти хочеш. Ви можете зупинитися на ІР-рівні LLVM і робити з ним все, що завгодно - інтерпретувати, компілювати JIT, інструментувати будь-яким способом. Ви навіть можете перевести його на Javascript, а потім пройти через перекладача: github.com/kripken/emscripten/wiki
SK-логіка

@ SK-логіка, акуратні речі! Я не знав, що LLVM може це зробити.
Вінстон Еверт

1
Краса llvm полягає в цьому навмисному розділенні між переднім і заднім кінцем. І інструменти для маніпулювання серединою, перш ніж орієнтуватися на набір інструкцій. Ви можете об'єднати весь проект у байт-код, а потім оптимізувати все це, з іншими компіляторами вам потрібно мати одне джерело файлу або принаймні одне, що включає його шлях вниз через дерево джерела, щоб компілятор діяв на одне об'єднане джерело. Також один набір інструментів під llvm є загальним для всіх цілей, вам не потрібно будувати для кожної цілі, один компілятор підходить для всіх (принаймні, до асм-цілі).
old_timer

-1

Корисна відмінність: інтерпретовані програми можуть змінювати себе, додаючи або змінюючи функції під час виконання.


8
Дурниці. Самомодифікуючий (машинний) код - найдавніший трюк у книзі. Потім знову дехто стверджує, що навіть власний код в кінцевому підсумку інтерпретується інтерпретатором, закинутим у кремній (CPU). Але якщо припустити, що весь код інтерпретується і різниці не можна робити.

2
@delnan має рацію. Я просто додам, що сучасні мови можуть змінювати себе, створюючи динамічно нові класи та завантажуючи / вивантажуючи бібліотеки (або "збірки" в .NET, наприклад)
Jalayn,

5
Загальний Lisp компілюється, але ви все одно можете легко замінити визначення функцій під час виконання.
SK-логіка

Це дійсно цікава та необхідна (наприклад, у Prolog) особливість інтерпретації.
CapelliC
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.