Typescript транслируется в JS. Затем идет встряхивание дерева, "менее" (необязательно) и что еще в процессе создания развертывания. Но ничего подобного (афаик) не имеет ничего общего с «компиляцией». Все объединяется и сильно оптимизируется, но на самом деле не компилируется, верно?
Компиляция означает преобразование программы, написанной на языке A, в семантически эквивалентную программу, написанную на языке B, так что оценка скомпилированной программы в соответствии с правилами языка B (например, интерпретация его с помощью интерпретатора для B) дает тот же результат и имеет те же побочные эффекты, что и оценка исходной программы в соответствии с правилами языка A (например, интерпретируя его с помощью интерпретатора для A).
Компиляция просто означает перевод программы с языка A на язык B. Это все, что это значит. (Также обратите внимание, что A и B могут быть одним и тем же языком.)
В некоторых случаях у нас есть более специализированные имена для определенных типов компиляторов, в зависимости от того, что такое A и B и что делает компилятор:
- если A воспринимается как язык ассемблера, а B — как машинный язык, то мы называем его ассемблером,
- если A воспринимается как машинный язык, а B — как язык ассемблера, тогда мы называем его дизассемблером,
- если A воспринимается как более низкий уровень, чем B, мы называем его декомпилятором,
- если A и B — один и тот же язык, а получившаяся программа в чем-то быстрее или легче, то мы называем ее оптимизатором,
- если A и B являются одними и теми же языками, а результирующая программа меньше, то мы называем ее минификатором,
- если A и B являются одними и теми же языками, а результирующая программа хуже читается, то мы называем ее обфускатором,
- если воспринимается, что A и B находятся примерно на одном уровне абстракции, мы называем это транспилером, и
- если A и B воспринимаются как находящиеся примерно на одном уровне абстракции, и полученная программа сохраняет форматирование, комментарии и намерения программиста, так что можно сохранить результирующий программу так же, как и исходную программу, мы называем ее инструментом реинжиниринга.
Также обратите внимание, что в старых источниках могут использоваться термины «перевод» и «переводчик» вместо «компиляция» и «компилятор». Например, C говорит о «единицах перевода».
Вы также можете наткнуться на термин «языковой процессор». Это может означать компилятор, интерпретатор или оба компилятора и интерпретатора в зависимости от определения.
Сам Javascript все еще интерпретируется, верно?
JavaScript — это язык. Языки — это набор логических правил и ограничений. Языки не интерпретируются и не компилируются. Языки просто есть.
Компиляция и интерпретация - это черты компилятора или интерпретатора (да!). Каждый язык может быть реализован с помощью компилятора, и каждый язык может быть реализован с помощью интерпретатора. Многие языки имеют как компиляторы, так и интерпретаторы. Многие современные высокопроизводительные механизмы выполнения имеют по крайней мере один компилятор и по крайней мере один интерпретатор.
Эти два термина принадлежат разным уровням абстракции. Если бы английский был типизированным языком, «интерпретируемый язык» был бы ошибкой типа.
Обратите также внимание на то, что некоторые языки не имеют ни интерпретатора, ни компилятора. Есть языки, которые вообще не имеют реализации. Тем не менее, это языки, и на них можно писать программы. Вы просто не можете запустить их.
Также обратите внимание, что все интерпретируется в некоторый момент: если вы хотите что-то выполнить, вы должны это интерпретировать. Компиляция просто переводит код с одного языка на другой. Это не работает. Интерпретация запускает его. (Иногда, когда интерпретатор реализован аппаратно, мы называем его «ЦП», но это все равно интерпретатор.)
Показательный пример: каждая существующая в настоящее время основная реализация JavaScript имеет компилятор.
V8 начинался как чистый компилятор: он компилировал JavaScript прямо в умеренно оптимизированный собственный машинный код. Позже был добавлен второй компилятор. Теперь есть два компилятора: легкий компилятор, который производит умеренно оптимизированный код, но сам компилятор очень быстрый и использует мало оперативной памяти. Этот компилятор также внедряет код профилирования в скомпилированный код. Второй компилятор является более тяжелым, медленным и более дорогим компилятором, который, тем не менее, производит гораздо более компактный и гораздо более быстрый код. Он также использует результаты кода профилирования, введенного первым компилятором, для принятия решений по динамической оптимизации. Кроме того, решение о том, какой код перекомпилировать с помощью второго компилятора, принимается на основе этой информации профилирования. Обратите внимание, что переводчик никогда не участвует. V8 никогда не интерпретирует, он всегда компилируется. Он даже не содержит интерпретатора. (На самом деле, я считаю, что в настоящее время это так, я описываю первые две итерации.)
SpiderMonkey компилирует JavaScript в байт-код SpiderMonkey, который затем интерпретирует. Интерпретатор также профилирует код, а затем код, который чаще всего выполняется, компилируется компилятором в собственный машинный код. Таким образом, SpiderMonkey содержит два компилятора: один из JavaScript в байт-код SpiderMonkey, а другой — из байт-кода SpiderMonkey в собственный машинный код.
Почти все механизмы выполнения JavaScript (за исключением V8) следуют этой модели компилятора AOT, который компилирует JavaScript в байт-код, и механизма смешанного режима, который переключается между интерпретацией и компиляцией этого байт-кода.
Вы написали в комментарии:
Я действительно думал, что где-то задействован машинный код.
Что вообще означает «машинный код»?
Что для одного человека машинный язык является промежуточным языком для другого и наоборот? Например, есть ЦП, которые могут выполнять байт-код JVM по умолчанию, на таком ЦП байт-код JVM является собственным машинным кодом. И есть интерпретаторы для машинного кода x86, когда вы запускаете этот машинный код x86, является интерпретируемым байт-кодом.
Существует интерпретатор x86 под названием JPC, написанный на Java. Если я запускаю машинный код x86 на JPC, работающем на родном ЦП JVM…, какой байт-код и какой собственный код? Если я компилирую машинный код x86 в JavaScript (да, есть инструменты, которые могут это сделать) и запускаю его в браузере на своем телефоне (у которого есть процессор ARM), какой байт-код и какой собственный машинный код? Что, если программа, которую я компилирую, является эмулятором SPARC, и я использую его для запуска кода SPARC?
Обратите внимание, что каждый язык порождает абстрактную машину и является машинным языком для этой машины. Таким образом, каждый язык (включая языки очень высокого уровня) является родным машинным кодом. Кроме того, вы можете написать интерпретатор для каждого языка. Таким образом, каждый язык (включая машинный код x86) не является родным.
person
Jörg W Mittag
schedule
10.10.2017