Существуют ли программы, которые могут «переводить» исходный код между любыми двумя языками?

28

Существуют ли программы, которые могут «переводить» исходный код между любыми двумя языками (при условии, что переводчик имеет доступ к необходимым библиотекам)?

Если есть, как они работают (используемые методы, необходимые знания и т. Д.)? Как они могут быть построены?

Если нет, то какие ограничения мешают их развитию? Это полная проблема ИИ (перевод на естественный язык указан как один)?

РЕДАКТИРОВАНИЕ Преобразование ожидается только в том случае, если язык имеет одинаковую мощность выражения, может решить те же проблемы, а код, который нужно преобразовать, может быть выражен на языке назначения. (Например, преобразование из сценария оболочки в MATLAB не ожидается).

Тоби Алафин
источник
14
Что вы подразумеваете под "любыми двумя языками"? Конечно, есть программы, которые можно переводить с одного языка на другой. Они называются «компиляторами». Это буквально определение компилятора: программы, которая переводит программы с одного языка на другой. Но "любые два языка"? Я не думаю, что это возможно. Переводчик должен знать как исходный, так и целевой язык, и он обычно специфичен для конкретной пары языков.
Йорг Миттаг,
В программе указаны исходный и целевой языки. Я думаю о том, чтобы написать программу на C ++, перевести ее на Java, python, Perl, Ruby, Go и т. Д. Могут быть некоторые ограничения (я не ожидаю, что она конвертирует ваш скрипт оболочки, например, в MATLAB).
Тоби Алафин
4
Да, их называют компиляторами, они работают как компиляторы, и их можно создавать как компиляторы.
user253751
1
Если под «любыми двумя языками» вы в буквальном смысле подразумеваете, что (конечная) программа должна быть способна читать и понимать бесконечное количество языков ввода, ответ тривиально - нет . Тем не менее, возьмите конечный набор языков ввода, и вы можете найти компилятор для всех этих языков ..
Бакуриу

Ответы:

57

TLDR; это возможно, но не практично.

(при условии, что переводчик имеет доступ к необходимым библиотекам)?

Это становится хитрым и является частью того, почему такие вещи не используются на практике.

  1. Все составители являются переводчиками. Перевод с одного языка на другой, безусловно, возможен, и это буквально все, что делает компилятор. Язык, который компилятор выдает в качестве выходных данных, обычно является машинным кодом или сборкой, но это просто другой язык, и есть компиляторы (иногда называемые транспиляторами или транскомпиляторами), которые переводят между двумя языками . Например, существует множество языков компиляции в Javascript, таких как PureScript, Elm, ClojureScript и т. Д.

  2. Перевод между любыми двумя языками Turing Complete всегда возможен. То есть игнорирование таких вещей, как вызовы библиотек, FFI и другие неприятные практические моменты. Если язык является полным по Тьюрингу, то у вас есть:

    • Перевод, который преобразует машину Тьюринга в код на этом языке
    • Перевод с этого языка на машину Тьюринга

    Таким образом, для перевода с языка A на язык B вы конвертируете код A в машину Тьюринга, а затем конвертируете эту машину в код B.

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

  3. Делать этот перевод эффективно сложно . Разные языки расставляют приоритеты для разных вещей. Например, если вы переводите с C на Python, вам, вероятно, придется в конечном итоге симулировать память C как словарь Python, чтобы вы могли выполнять арифметику указателей. Это будет связано с накладными расходами, потому что теперь вы не получаете доступ к инструкциям памяти без поддержки.

    Разные языки имеют разные приоритеты производительности, поэтому что-то, что оптимизирует один язык (или, скорее, оптимизирует реализацию одного языка), может быть невозможно быстро сделать на другом языке. Перевод функционального языка с соответствующими хвостовыми вызовами будет иметь замедление, если вы переведете его на язык без надлежащих конечных вызовов.

  4. Выполнение этого перевода не делает код читабельным . Легко получить фрагмент кода на языке B, который ведет себя так же, как код из языка A. Трудно сделать так, чтобы он выглядел как код, написанный человеком на B, по ряду причин. A и B могут иметь разные инструменты абстракции, и компьютер не знает, что делает код читабельным. Это будет особенно верно, если вы в конечном итоге будете использовать перевод машины Тьюринга, который я описал ранее.

    Возникает вопрос: какой смысл в таком переводе? Если все, что вы получите в конце, это блок медленного, нечитаемого кода, почему бы просто не скомпилировать его в машинный код и использовать какой-то тип FFI или межпроцессное взаимодействие для соединения частей?

    Есть некоторые исключения из этого. Иногда вам нужны вещи на определенном языке (например, JavaScript). Иногда язык похож, и разумный перевод легко. Иногда язык предназначен не для запуска, а для извлечения его кода на другой язык (например, Coq).

    Но в целом это не очень практичная вещь.

jmite
источник
5
Одним из примеров является точка 4 asm.js . Сегодня можно сделать Сорта читаемым, используя Javascript Источник Карты и Element Inspector, но никто не хочет , чтобы сделать это ...
Исмаэль Miguel
1
Modelica - это еще один пример языка, предназначенного для компиляции на другой язык (в данном случае C).
Восстановите Монику
Перевод веб-сборки с C ++ на javascript.
Surt
Существует множество примеров переносчиков из X в Y, но это отличается от универсального компилятора что угодно. Очевидно, есть случаи, когда перенос имеет смысл.
Jmite
В IMO отсутствует одно важное исключение: компиляция в C. Причина в том, что многие необычные системы имеют существующий компилятор C, который обычно может генерировать вполне приемлемый машинный код. Следовательно, компилируя язык в C, вам не нужно иметь backends для этих редких архитектур.
MSalters
2

Есть такие программы. Например, переводчики Lisp-to-Fortran, которые широко использовались в свое время. Единственные компиляторы Lisp не компилируют Lisp напрямую, а генерируют код C вместо этого, который затем компилируется обычным компилятором C. Другим примером может быть Vala, которая не компилируется напрямую, а сначала транслируется в C ++ до компиляции кода C ++. Qt написан на MOC, языке, который переводится на C ++ для его компиляции (но поскольку MOC - это просто C ++ с несколькими дополнительными командами, можно поспорить, действительно ли он будет называться «новым языком») - и до того, как были компиляторы C ++, были C ++ - to-C-трансляторы. И некоторые проекты были написаны на Pascal, а затем переведены на C. Кроме того, clang и Java, как правило, представляют собой нечто вроде того, что они переводят код C ++ и Java на некоторый промежуточный язык, который затем можно обрабатывать дальше.

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

Гюнтер Кенигсманн
источник
0

Не прямой ответ, но есть инструментальный вызов ILSpy , который был написан для .Net Framework и позволяет декомпилировать сборку .Net в C # или VB.Net.

Если вы не знакомы с природой .Net, вы можете писать код .Net на многих языках, но в первую очередь на C # или VB.Net. Когда компилятор компилирует приложение, он переводит код в код «Intermediate Language» (или IL для краткости). Этот код затем компилируется в двоичные файлы .Net.

Так как приложения .Net являются двоичными файлами, скомпилированными из кода IL, ILSpy может перевести приложение .Net в обратное положение, обратно в код IL, а затем сделать еще один шаг вперед и обратно в C # или VB.Net.

Используя этот инструмент, все, что вам нужно сделать, это скомпилировать приложение, а затем вы можете просматривать скомпилированные файлы в виде кода IL, C # или VB.Net. Чтобы было ясно, не имеет значения, на каком языке изначально был написан код. Поскольку бинарный файл представляет собой сборку .Net, он может перепроектировать скомпилированные файлы и выводить содержимое на любом из этих трех языков.

Я знаю, что это не совсем компилятор, но это инструмент, который предлагает конечный результат, аналогичный тому, что вы ищете, и, фактически, я использовал это, чтобы «перевести» проекты VB.Net в нечто немного более знакомый мне - C #.

RLH
источник
0

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

SWIG - это инструмент разработки программного обеспечения, который связывает программы, написанные на C и C ++, с различными языками программирования высокого уровня. SWIG используется с различными типами целевых языков, включая распространенные языки сценариев, такие как Javascript, Perl, PHP, Python, Tcl и Ruby. В список поддерживаемых языков входят также языки, не относящиеся к сценариям, такие как C #, Common Lisp (CLISP, Allegro CL, CFFI, UFFI), язык D, Go, Java, включая Android, Lua, Modula-3, OCAML, Octave, Scilab и R Также поддерживаются несколько интерпретированных и скомпилированных реализаций Scheme (Guile, MzScheme / Racket, Chicken).

Натан Ринго
источник
0

Я вспоминаю почтенного f2c , который переводит источник с источника на Fortran 77 на C.

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

Александр С.
источник
0

Теория теории, которая говорит вам, что такие программы существуют, в принципе называется допустимой нумерацией . Мы можем доказать, что между любыми двумя такими нумерациями есть вычислимые компиляторы, и каждый полный по Тьюрингу формализм (или язык программирования), по сути, один.

Рафаэль
источник