Почему нет автоматических переводчиков с одного языка программирования на другой? [закрыто]


37

Большинство языков программирования являются полными по Тьюрингу, что означает, что любая задача, которая может быть решена на одном языке, может быть решена на другом или даже на машине Тьюринга. Тогда почему нет автоматических переводчиков, которые могут конвертировать программы с любого языка на любой другой язык? Я видел пару попыток для двух языков, но они всегда работают только на ограниченном подмножестве языка и вряд ли могут быть использованы для конвертации реальных проектов.

Можно ли, по крайней мере, теоретически, написать 100% правильный переводчик между всеми языками? Какие проблемы на практике? Существуют ли уже работающие переводчики?


5
Помните, что «все языки» включают даже такие глупые, как Oook! (Полнота Тьюринга - не вся история; на практике вам также нужны системные вызовы.)
Donal Fellows

Есть некоторые. Переводчики с C на Pascal и с Pascal на C были довольно распространены в одном месте. Как показывают ответы ниже, выходные данные обычно не были так удобочитаемы, по крайней мере, без некоторой ручной уборки. И это относительно простые языки с относительно простыми библиотеками - хорошо выполнить работу, например, с C ++ для Haskell или наоборот, было бы невозможно.
Steve314

Проверьте Roslyn компилятор .net как сервис, который имеет возможность переводить C # в VB и наоборот.
Даниэль Литтл

2
Все компиляторы переводят один PL в другой, они не гарантируют, что код в целевом PL легко читается, хотя
jk.

Убедившись в точности перевода Google, я убежден, что в своей жизни увижу универсального переводчика. Да, это будет сложная задача и может потребовать огромных усилий, как в случае анализа большой базы кода, такой как github или stackoverflow, но это произойдет, и спрос на такой инструмент также возрастет в ближайшие годы, особенно сейчас что есть много программистов для изучения ИИ и ОД. Там не может быть один человек, который разрабатывает такой инструмент сам по себе. Однако можно разработать бота для разработки ботов для решения этой проблемы.
Ганеш Камат - «Безумный кодекс»

Ответы:


32

Самой большой проблемой является не фактический перевод программного кода, а портирование API платформы.

Рассмотрим переводчик PHP на Java. Единственный реальный способ сделать это без встраивания части двоичного кода PHP - это переопределить все модули PHP и API в Java. Это включает в себя реализацию более 10.000 функций. По сравнению с этим работа по переводу синтаксиса очень проста. И даже после всей этой работы у вас не будет Java-кода, у вас будет какое-то чудовище, которое работает на платформе Java, но структурировано как PHP внутри.

Вот почему единственные такие инструменты, которые приходят на ум, - это перевод кода для его развертывания, а не для его последующего сопровождения. Google GWT «компилирует» Java в JavaScript. Хип-хоп Facebook компилирует PHP в C.



Похоже, кто-то создал переводчик php в java и действительно вставил бинарный файл PHP. Согласен, хотя это не меняет твою точку зрения. runtimeconverter.com/single-post/2017/09/15/...
user1122069

20

Если у вас есть промежуточный формат, то вы могли бы реализовать что-то, что переводит программу на языке X в этот формат, а также из этого формата в язык Y. Выполните эти преобразования для всех языков, которые вас интересуют, и все готово, верно?

Ну знаешь что? Такой формат уже существует: сборка. Компилятор уже выполняет преобразование «Язык X в сборку», а дизассемблеры - в преобразование «Сборка в язык Y».

Теперь ассемблер - не такой уж хороший язык для обратного преобразования, но MSIL на самом деле не так уж и плох. Скачать рефлектор и вы увидите, что у него есть возможность разобрать сборку .NET на несколько языков (а плагины предоставляют еще больше). Таким образом, вполне возможно взять программу на C #, скомпилировать ее в DLL (то есть, MSIL), а затем использовать рефлектор, чтобы разобрать ее на VB, C ++ / CLI, F # и целый ряд других. Конечно, все остальные конверсионные работы тоже. Возьмите файл F #, скомпилируйте в DLL, используйте Reflector, чтобы преобразовать его в C #.

Конечно, вы обнаружите две большие проблемы:

  1. Код в основном не читается. MSIL (даже с отладочной информацией) удаляет много информации из исходного источника, поэтому переведенная версия не имеет 100% -ной точности (теоретически выполнение преобразования C # -> MSIL-> C # должно вернуть вам исходный код, но это не будет).
  2. Многие языки .NET имеют свои собственные пользовательские библиотеки (например, библиотека времени выполнения VB, библиотека F # и т. Д.). Они также должны быть включены (или преобразованы), когда вы выполняете конвертацию.

Обойти # 2 действительно нечего, но вы, вероятно, могли бы обойти # 1 с некоторыми дополнительными аннотациями в MSIL (возможно, через атрибуты). Это была бы дополнительная работа, конечно.


Большая часть метаданных из исходного источника включена в MSIL (включая комментарии XML и исходный метод, имена свойств и элементов), поэтому я не думаю, что преобразование в C # столь же нечитабельно, как вы говорите. Попробуйте разобрать части .NET Framework; это очень читабельно. Конечно, ситуация может быть другой для преобразования F # в C #.
Роберт Харви

@ Роберт: XML-комментарии не включены в MSIL. Если вы посмотрите, Microsoft.NET\Framework\v2.0.50727\enнапример, вы можете увидеть всю документацию XML для системных библиотек. Это то, что Reflector (и другие) используют для отображения комментариев. Преобразование не является нечитаемым, все, что я говорил, это то, что это не 100% точность, которую вы могли бы ожидать от перевода на уровне источника.
Дин Хардинг

2
Дизассемблер преобразует исполняемый файл машины обратно в ассемблер для этого конкретного типа процессора (не весь мир - это x86). Вы действительно имеете в виду декомпилятор, который возвращает скомпилированный код в исходный код. Это чрезвычайно сложная задача, поскольку каждый компилятор каждого производителя на каждом уровне оптимизации преобразует строки исходного кода в различные выходные двоичные формы.
uɐɪ

20

Можно ли, по крайней мере, теоретически, написать 100% правильный переводчик между всеми языками? Какие проблемы на практике?

  • Перевод с более структурированного языка на менее структурированный язык, который все еще завершен по Тьюрингу, всегда возможен.
    • Это утверждение следует рассматривать в строго техническом смысле: это означает, что переведенная программа будет давать точно такой же результат при выполнении.
    • Ничто не подразумевает читабельность переведенного кода или сохранение исходных структур программы.
  • Возможен перевод с менее структурированного языка на более структурированный, но переведенный код останется в его менее структурированном виде.

1
В точку. Попробуйте прочитать код, который выходит из бэкэнда C LLVM. Это технически допустимый C-код, но это не очень красиво (TM).
дсимча

1
@dsimcha: кроме читабельности, бэкэнд C делает вывод намного проще для чтения, чем отладка или разборка. Я так рад, что они вернули этот бэкэнд обратно, после того как он вышел из строя на некоторое время.
JM Becker

10

Почему вы хотите конвертировать программу?

Оба языка, исходный и целевой языки в любом случае компилируются в (виртуальный) машинный код *, поэтому по техническим причинам нет необходимости иметь компилятор для другого языка высокого уровня.

Языки для людей. Итак, неявное требование вашего вопроса: «почему нет переводчика, который генерирует читаемый код» , и ответ будет (imho): потому что, если есть два языка, которые достаточно отличаются, пишется способ «читаемый код» отличается тем, что не только потребует перевода алгоритмов, но и других алгоритмов.

Например, сравните типичную итерацию в C и одну в lisp. Или питоны «одним из лучших способов» с идиоматическим рубином.

Здесь начинают появляться те же проблемы, что и у вас на реальных языках, например, когда вы переводите «Идет дождь с кошками и собаками» на что-то со значением «Это льется, как из ведер» при переводе с английского на немецкий, вы не можете переводить слово за словом больше, но вы должны искать смысл.

И «смысл» - не простая концепция для работы.

*) хорошо, есть coffeescript ...


1
Хороший ответ. Можно добавить, что если бы два языка обладали одинаковым набором функций и идиом, можно было бы достаточно эффективно переводить один язык на другой, но большинство языков разработаны с целью поддержки функций и идиом, которые, по мнению их создателей, неадекватно поддерживается на других языках . Механический перевод поддерживаемого кода иногда работает, когда функции и идиомы на целевом языке являются расширенным набором функций на исходном языке, но такие ситуации не очень распространены.
суперкат

6

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

Изрядное количество компиляторов делают таргетинг на C просто потому, что компиляторы C доступны практически для каждой существующей платформы (и существуют автоматические генераторы компиляторов, которые позволят вам разработать процессор и автоматически сгенерировать компилятор C, ориентированный на ваш новый процессор). Конечно, существует также немало реализаций, предназначенных для языков, используемых различными виртуальными машинами, такими как .NET, JVM, C-- и LLVM.

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


5

Кстати, есть переводчик с Java на D. Он называется TioPort и использовался в довольно серьезной попытке перенести SWT на D. Основная проблема, с которой он столкнулся, заключалась в том, что было бы необходимо портировать огромные части стандартной библиотеки Java. ,


4

Хотя это не перевод кода как таковой, концепция языковых рабочих мест показывает, как можно реализовать что-то похожее на 100% правильный переводчик между всеми языками.

В нашем текущем подходе исходный код хранится в текстовом формате. Во время компиляции эти читаемые человеком текстовые файлы анализируются в абстрактном синтаксическом дереве, которое, в свою очередь, используется для генерации либо байт-кода, либо машинного кода. Это абстрактное представление, однако, является временным и внутренним для компилятора.

В подходе инструментальных средств языка аналогичное представление абстрактного синтаксического дерева является постоянным, хранимым артефактом. И машинный код, и текстовый «исходный» код генерируются на основе этого абстрактного представления. Одним из следствий такого метода является то, что абстрактное представление программы фактически не зависит от языка и может использоваться для генерации текстового кода на любом реализованном языке. Это означает, что один человек может свободно работать над различными аспектами системы, используя любой язык, который он считает наиболее подходящим, или что каждый член команды может работать над общим проектом на языке, который ему наиболее знаком.

Насколько я знаю, технология все еще далека от использования в основной разработке, однако есть несколько групп, которые работают над ней независимо. Трудно сказать, выполнит ли кто-нибудь из них свои обещания, но было бы интересно увидеть, как это произойдет.


Не могли бы вы назвать некоторые из этих групп?
Qwertie

4

Там являются некоторыми автоматическими переводчиками. Если ваша цель - создавать скомпилированный код, а не читаемый код, это вполне возможно и иногда полезно, но не очень часто. Известно, что первый компилятор C ++ на самом деле не был компилятором, но преобразовал C ++ в (действительно сложный) источник C, который затем был скомпилирован компилятором C. Многие компиляторы могут генерировать ассемблерный код по запросу - но вместо того, чтобы выплевывать ассемблерный текст и затем переводить его в машинный код, они обычно могут генерировать машинный код напрямую.

Учитывая полную спецификацию языка A, в принципе не так сложно написать программу, которая выражает свои директивы на каком-то языке B. Но обычно любой, кто сталкивается с трудностями, выбирает что-то действительно низкое для «языка B»: Машинный код или в наши дни байт-код: Jython - это реализация python, которая генерирует Java-байт-код, который интерпретируется Java VM. Нет необходимости писать и компилировать иерархии классов Java!


3

Это делается все время.

Каждый компилятор переводит «основной язык», такой как C ++, на родной язык ассемблера машины или независимый от архитектуры байт-код в случае интерпретируемых языков.

Я полагаю, что это не то, о чем вы говорите. Возможно, вам нужен переводчик, который преобразует C ++ во что-то вроде Java или Python. Но какой в ​​этом смысл? В лучшем случае конечный результат будет иметь ту же эффективность, что и исходный источник. (Практически, это будет намного хуже.)

Если вы просто хотите, чтобы код был переведен, чтобы вы могли читать его на понятном вам языке, такой переводчик имел бы противоположность желаемому эффекту. Вы останетесь с множеством загадочного, не интуитивного и нечитаемого кода.

Это потому, что только самые тривиальные вещи переводятся непосредственно с одного языка на другой. Часто то, что просто в одном языке, требует массивных библиотек для другого - или может быть вообще невозможно. Следовательно:

  1. Если программа тривиальна, вы можете получить достойный результат. Но тогда, если это так просто, какой смысл запускать его через переводчик?
  2. Если программа нетривиальна, код будет низкого качества.

В конце концов, единственный способ написать хороший код - это написать его. Компьютеры просто не могут - по крайней мере, пока - не сопоставлять людей по вопросам читабельности, лучших практик и элегантных решений.

Короче говоря, это просто не стоит.


Ваша аналогия также применима к обычной компиляции, а мы знаем эмпирически, что это не так! Компьютеры «генерируют» (не пишут) код хорошего качества. То, что они часто делают плохо, это удобочитаемость / ремонтопригодность. Если кому-то действительно нужен такой процесс, который, как мне кажется, время от времени делают люди, ни одна из проблем не является пробкой. Если они, ну тогда, очевидно, перевод никогда не был важен изначально.
JM Becker

1

Для языков программирования нет языковых переводчиков, потому что языки программирования невероятно сложны. Хотя это гипотетически возможно, есть много проблем.

Первая проблема заключается только в приемлемой практике языка. Преобразование между двумя объектно-ориентированными языками, такими как Java и C ++, невероятно сложно, и оба они основаны на C. Программа переводчика должна была бы в совершенстве владеть стандартными библиотеками для обоих языков и уметь различать поведение. Вам придется создать огромный словарь, и даже тогда различия в стилях программирования от программиста до программиста означают, что ему придется угадывать, как выполнить некоторые изменения.

После того, как вы получили перевод синтаксиса, вы должны выяснить, как преобразовать конструкцию на первом языке в конструкцию на втором языке. Это нормально, если вы переходите от объекта в C ++ к объекту в Java (это сравнительно легко), но что вы делаете с вашими структурами C ++? Или функции вне классов C ++? Решить, как с этим справиться, может быть сложно, так как это может привести к другой проблеме, а именно к созданию объекта BLOB-объекта. BLOB-объект является достаточно распространенным антипаттерном.

Это не полный список проблем, но их всего две, и они большие. Один из моих профессоров упомянул, что кто-то убедил его работодателя, что в 80-х годах он может сделать его из машинного кода в C, но тогда он не работал. Я сомневаюсь, что когда-нибудь будет тот, который работает полностью.


Я думаю, что нет необходимости знать существующие библиотеки, он может просто переводить библиотеки по мере необходимости (при условии, что у них есть доступные источники).
2010 г.

1
Это на самом деле увеличивает сложность второй проблемы. И это при условии, что у вас есть доступ к исходному коду для его перевода. В любом случае, это все еще довольно невыполнимо.
indyK1ng

+1 пункт о libs абсолютно действителен, и всегда есть libs.
Дэн Розенстарк

1

Смысл компиляции - получить что-то полезное для компьютера. то есть то, что может работать. Зачем компилировать что-то, что может быть даже более высокого уровня, чем вы написали?

Мне больше нравится стратегия .NET. Скомпилируйте все на общий язык. Это дает возможность языкам общаться без необходимости создавать (N ^ 2) -N кросс-языковых компиляторов.

Например, если у вас было 10 языков программирования, вам нужно было бы написать только 10 компиляторов в соответствии с моделью .NET, и все они могли бы общаться друг с другом. Если бы вы сделали все возможные кросс-языковые компиляторы, вам нужно было бы написать 90 компиляторов. Это много дополнительной работы за небольшую выгоду.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.