Как перевести программу с одного языка программирования на другой
Обновлено: 21.11.2024
Universal-transpiler – это компилятор исходного кода, который переводит небольшое подмножество нескольких языков программирования в несколько других. Он также может переводить несколько нотаций метасинтаксиса, таких как EBNF и ABNF.
Universal-transpiler был написан как экспериментальный «доказательство концепции», поэтому он может переводить только относительно простые программы. Перевод не всегда на 100% точен, но, надеюсь, он все же будет полезен.
Онлайн-версия этого переводчика написана на JavaScript, но экспериментальная версия также пишется на Prolog.
Основной целью этого проекта является перевод TypeScript и JavaScript на другие языки, которые компилируются в C или собственный код. Например, можно преобразовать подмножество TypeScript в Zig:
Некоторые поддерживаемые функции
Циклы Foreach Этот переводчик может преобразовывать многие языки во многие другие:
Программирование с ограничениями и автоматические рассуждения
Universal-transpiler может генерировать код на нескольких языках программирования с ограничениями и системах компьютерной алгебры, включая MiniZinc, Maxima, Sage, Algebrite и Axiom. Некоторые языки также могут быть переведены на языки SMT-LIB, TPTP, Coq, Isabelle/HOL и альтернативные языки для автоматизированного доказательства теорем. В качестве экспериментальной функции он также преобразует подмножество Prolog в язык автоматического планирования PDDL.
Языки онтологии
Universal-transpiler также может переводить языки программирования в язык онтологии KIF.
Создание парсеров с помощью universal-transpiler
Universal-transpiler также может переводить различные грамматические обозначения, такие как jison, marpa, peg.js и Nearley.
Переводчик Пролога все еще незаконченный и экспериментальный. Вы можете установить пакет, набрав pack_install(transpiler) в консоли SWI-Prolog. Теперь вы можете использовать переводчик для преобразования исходного кода JavaScript в Lua:
Здесь представлено ограниченное количество правил перевода, но вы можете легко добавить свои собственные правила на transpiler.pl . Это упрощенная версия одного из его правил трансляции, реализующая функцию синуса:
Другие запланированные функции:
- Добавьте переводчик для языков линз, таких как Augeas и Boomerang.
- Упрощение и рефакторинг генератора кода с помощью интерполяции строк.
- Преобразование SQL в Linq и наоборот
- Одновременное редактирование двух языков программирования в двух текстовых областях из других языков в Prolog.
- Попробуйте перевести языки разметки, подобные Pandoc.
- Попробуйте преобразовать SVG в другие форматы векторной графики.
- Попробуйте конвертировать X3D в другие форматы векторной графики
Существует несколько других компиляторов исходного кода и генераторов кода, похожих на этот.
JTransc компилирует Java, Kotlin и Scala в несколько других языков программирования. Pandoc — универсальный конвертер документов
Хотите улучшить этот вопрос? Обновите вопрос, чтобы он был сосредоточен только на одной проблеме, отредактировав этот пост.
Закрыт 7 лет назад.
Большинство языков программирования являются полными по Тьюрингу, а это означает, что любую задачу, которую можно решить на одном языке, можно решить на другом или даже на машине Тьюринга. Тогда почему нет автоматических переводчиков, которые могут конвертировать программы с любого заданного языка на любой другой язык? Я видел пару попыток для двух языков, но они всегда работают только на ограниченном подмножестве языка и вряд ли могут быть использованы для преобразования реальных проектов.
Можно ли хотя бы теоретически написать 100% корректный переводчик между всеми языками? Какие трудности возникают на практике? Есть ли работающие переводчики?
Помните, что «все языки» включают даже такие глупые, как Oook! (Полнота по Тьюрингу — это еще не все; на практике вам также понадобятся системные вызовы.)
Есть некоторые. В какой-то момент трансляторы с C на Pascal и с Pascal на C были довольно распространены. Как показывают ответы ниже, вывод обычно не был таким читаемым, по крайней мере, без какой-либо ручной уборки. И это относительно простые языки с относительно простыми библиотеками, которые хорошо справляются со своей задачей, например. C++ на Haskell или наоборот, вероятно, будет невозможно.
Все компиляторы транслируют один ЯП в другой, однако они не гарантируют, что код в целевом ЯП легко читается
После того, как я увидел точность Google Translate, я уверен, что когда-нибудь увижу универсального переводчика. Да, это будет сложной задачей и может потребовать огромных усилий, как в случае анализа большой базы кода, такой как github или stackoverflow, но это произойдет, и спрос на такой инструмент также возрастет в грядущие века, особенно сейчас что есть много программистов для изучения ИИ и машинного обучения. Возможно, не найдется ни одного человека, который сам разработает такой инструмент.Однако можно разработать бота для разработки ботов для решения этой проблемы.
11 ответов 11
Самая большая проблема заключается не в самом переводе программного кода, а в переносе API платформы.
Подумайте о переводчике с PHP на Java. Единственный возможный способ сделать это без встраивания части бинарного файла PHP — переопределить все модули PHP и API на Java. Это включает в себя реализацию более 10 000 функций. По сравнению с этим работа по фактическому переводу синтаксиса проста как пирог. И даже после всей этой работы у вас не будет Java-кода, у вас будет какое-то чудовище, которое работает на платформе Java, но структурировано как PHP внутри.
Вот почему единственные такие инструменты, которые приходят на ум, связаны с переводом кода для его развертывания, а не для его последующего обслуживания. Google GWT «компилирует» Java в JavaScript. Хип-хоп от Facebook компилирует PHP в C.
Если у вас есть промежуточный формат, вы можете реализовать что-то, что переводит программу на языке X в этот формат, а также из этого формата в язык Y. Реализуйте эти преобразования для всех интересующих вас языков, и вы закончили, верно?
Ну знаете что? Такой формат уже существует: сборка. Компилятор уже выполняет преобразование «язык X в ассемблер», а дизассемблеры — в преобразование «ассемблирование в язык Y».
Дизассемблер преобразует машинный исполняемый двоичный файл обратно в ассемблер для этого конкретного типа процессора (не весь мир использует x86). Вы действительно имеете в виду декомпилятор, чтобы вернуть скомпилированный код обратно в источник. Это ужасно сложная задача, поскольку каждый компилятор каждого производителя на каждом уровне оптимизации будет преобразовывать исходные строки в другую выходную двоичную форму.
Можно ли хотя бы теоретически написать 100% корректный переводчик между всеми языками? Какие проблемы возникают на практике?
- Перевод с более структурированного языка на менее структурированный язык, который по-прежнему является полным по Тьюрингу, всегда возможен.
- Это утверждение следует рассматривать в строгом техническом смысле: оно означает, что переведенная программа будет давать точно такой же результат при выполнении.
- Ничего не подразумевается в отношении удобочитаемости переведенного кода или сохранения исходной структуры программы.
Вы попали в самую точку. Попробуйте прочитать код, который выходит из бэкэнда LLVM C. Технически это допустимый код C, но это некрасиво (TM).
@dsimcha: Читаемость в стороне от того, что серверная часть C делает вывод намного проще для чтения, чем отладка или дизассемблирование. Я так рад, что они снова вернули эту серверную часть после того, как она ненадолго перестала обслуживаться.
Зачем вам нужно конвертировать программу?
Оба языка, исходный и целевой, в любом случае компилируются в (виртуальный) машинный код*, поэтому по техническим причинам нет необходимости иметь компилятор для другого языка высокого уровня.
Языки предназначены для людей. Итак, неявное требование вашего вопроса: «почему нет переводчика, который генерирует удобочитаемый код», и ответ будет (имхо): потому что, если есть два языка, которые достаточно разные, способы написания «читабельного кода» отличаются таким образом, что требуется не просто перевод алгоритмов, но и использование других алгоритмов.
Например, сравните типичную итерацию в C и в lisp. Или питоны «наилучший способ» с идиоматическим рубином.
Здесь начинают проявляться те же проблемы, что и в реальных языках, например, когда вы переводите фразу "Идет дождь из кошек и собак" во что-то со значением "Льет, как из ведра" при переводе с английского на немецкий, вы слово в слово уже не переведешь, а смысл искать надо.
И «смысл» — непростая концепция для работы.
*) ну, есть coffeescript.
Хороший ответ. Можно было бы добавить, что если бы два языка имели точно такой же набор функций и идиом, можно было бы достаточно эффективно переводить один язык на другой, но большинство языков разработаны с целью поддержки функций и идиом, которые их создатели считают нужными. недостаточно поддерживаются на других языках. Механический перевод поддерживаемого кода иногда возможен, когда функции и идиомы в целевом языке являются расширенным набором функций и идиом в исходном языке, но такие ситуации не очень распространены.
Теоретически это возможно, но в основном бесполезно. Возможна почти любая комбинация исходного и целевого языков, но в большинстве случаев никому не захочется смотреть или использовать результат.
Ключевым моментом, однако, является то, что это действительно полезно, только если вы рассматриваете цель как язык ассемблера, который используется только как шаг в процессе компиляции.В частности, вы обычно не хотите, чтобы обычный программист читал или работал с этим результатом; обычно это не очень читабельно.
FWIW, есть переводчик с Java на D. Он называется TioPort и использовался при довольно серьезной попытке портировать SWT на D. Основная проблема, с которой он столкнулся, заключалась в том, что необходимо было бы портировать огромные части Стандартная библиотека Java.
Есть несколько автоматических переводчиков. Если вашей целью является создание компилируемого кода, а не читаемого кода, это вполне возможно и иногда полезно, просто не очень часто. Известно, что первый компилятор C++ на самом деле не был компилятором, а переводил C++ в (действительно сложный) исходный код C, который затем компилировался компилятором C. Многие компиляторы могут генерировать ассемблерный код по запросу, но вместо того, чтобы выдавать ассемблерный текст и затем преобразовывать его в машинный код, они обычно могут генерировать машинный код напрямую.
Учитывая полную спецификацию языка А, в принципе не так сложно написать программу, которая выражает свои директивы на каком-то языке Б. Но обычно любой, кто возьмет на себя труд, выберет что-то очень низкоуровневое для "языка Б" : машинный код, или в наши дни байт-код: Jython — это реализация python, которая генерирует байт-код java, который интерпретируется виртуальной машиной Java. Не нужно заморачиваться написанием и компиляцией иерархии классов Java!
Хотя это и не перевод кода как таковой, концепция языковых рабочих мест показывает, как можно реализовать что-то вроде 100% правильного переводчика между всеми языками.
В нашем текущем подходе исходный код хранится в текстовом формате. Во время компиляции эти удобочитаемые текстовые файлы анализируются в представление абстрактного синтаксического дерева, которое, в свою очередь, используется для генерации байт-кода или машинного кода. Однако это абстрактное представление является временным и внутренним для компилятора.
В подходе языковых рабочих мест аналогичное представление абстрактного синтаксического дерева является постоянным хранимым артефактом. И машинный код, и текстовый «исходный» код генерируются на основе этого абстрактного представления. Одним из следствий такого метода является то, что абстрактное представление программы фактически не зависит от языка и может использоваться для генерации текстового кода на любом реализованном языке. Это означает, что один человек может свободно работать над различными аспектами системы, используя любой язык, который он считает наиболее подходящим, или каждый член команды может работать над общим проектом на языке, с которым он лучше всего знаком.
Насколько мне известно, эта технология все еще далека от использования в основной разработке, однако несколько групп работают над ней независимо. Трудно сказать, выполнит ли кто-нибудь из них свои обещания, но было бы интересно посмотреть, как это произойдет.
Это делается постоянно.
Каждый компилятор транслирует «основной язык», такой как C++, в собственный язык ассемблера машины или архитектурно-независимый байт-код в случае интерпретируемых языков.
Я думаю, вы не об этом. Вероятно, вам нужен переводчик, который преобразует C++ во что-то вроде Java или Python. Хотя какой в этом смысл? В лучшем случае конечный результат будет иметь точно такую же эффективность, как и первоисточник. (На практике будет намного хуже.)
Если вы просто хотите, чтобы код был переведен так, чтобы вы могли читать его на понятном вам языке, такой переводчик будет иметь эффект, противоположный желаемому. У вас останется множество загадочного, неинтуитивного и нечитаемого кода.
- Если программа тривиальна, вы можете получить достойный результат. Но тогда, если это так просто, какой вообще смысл запускать это через переводчик?
- Если программа нетривиальна, код будет низкого качества.
В конце концов, единственный способ написать хороший код — это написать его на самом деле. Компьютеры просто не могут — по крайней мере, пока — сравниться с людьми в вопросах удобочитаемости, лучших практик и элегантных решений.
Короче говоря, оно того не стоит.
Ваша аналогия также применима к обычной компиляции, а мы знаем эмпирически, что это не так! Компьютеры «генерируют» (а не пишут) код хорошего качества. Что они часто делают плохо, так это читабельность/ремонтопригодность. Если кому-то действительно нужен такой процесс, что, поверьте мне, люди иногда делают, ни одна из проблем не является препятствием для шоу. Если да, то очевидно, что изначально перевод никогда не был важен.
Для языков программирования не существует языковых переводчиков, поскольку языки программирования невероятно сложны. Хотя это гипотетически возможно, существует много проблем.
Первая проблема заключается просто в допустимых практиках языка. Преобразование между двумя объектно-ориентированными языками, такими как Java и C++, невероятно сложно, и оба они основаны на C.Программа-переводчик должна в совершенстве знать стандартные библиотеки для обоих языков и уметь различать их поведение. Вам придется создать огромный словарь, и даже тогда различия в стилях программирования от программиста к программисту будут означать, что ему придется догадываться, как выполнять некоторые изменения.
После перевода синтаксиса вам нужно выяснить, как преобразовать конструкцию на первом языке в конструкцию на втором языке. Это нормально, если вы переводите объект на C++ в объект на Java (это сравнительно просто), но что вы делаете со своими структурами C++? Или функции вне классов С++? Решить, как с этим справиться, может быть сложно, поскольку это может привести к другой проблеме, а именно к созданию объекта большого двоичного объекта. Блоб — это достаточно распространенный антишаблон.
Это не полный список проблем, но это только две, и они очень серьезные. Один из моих профессоров упомянул, что в 80-х кто-то убедил его работодателя, что они могут перевести машинный код на C, но тогда это не сработало. Сомневаюсь, что когда-нибудь найдется работающая полностью.
Преобразование синтаксиса между языками программирования — не единственный способ преобразования кода с одного языка на другой. Это процесс преобразования данных с максимально возможным сохранением структуры. Недавние исследования показывают, что миграция существующей кодовой базы на более современный или эффективный язык, такой как Java или C++, требует навыков как в исходном, так и в целевом языках и может быть дорогостоящей. Например, Commonwealth Bank of Australia потратил около 750 миллионов долларов в течение пяти лет, чтобы перевести свою платформу с COBOL на Java. В принципе, транскомпилятор может сэкономить время, избавляя от необходимости переписывать код с нуля. Тем не менее, их сложно реализовать на практике, поскольку разные языки имеют разный синтаксис и полагаются на разные API платформы, стандартные библиотечные функции и типы переменных.
Препятствие
Миграция устаревшего кода на другой язык программирования может выполняться на разных уровнях, каждый из которых является более масштабным и сложным для реализации. В результате по мере прохождения уровней потребность в ручном преобразовании возрастает. На самом базовом уровне миграция — это процесс преобразования кода с одного языка на другой. На более высоком уровне структура системы может быть изменена, например, путем преобразования кода, написанного на чисто процедурном языке, в код, написанный на чисто объектно-ориентированном языке. На еще более высоких уровнях может потребоваться изменение глобальной архитектуры. По мере ежедневного появления новых технологий становится все труднее поддерживать согласованность между разными языками. Новые функции также вводятся по мере развития языков программирования. В результате все компиляторы межконверсионного преобразования, связанные с этим языком, должны быть обновлены.
Например, Джордж и др. заявить, что каждые 3-5 лет ANSI C++ обновляется. В измененную формулировку могут быть включены новые ключевые слова. Например, constexpr — это новое ключевое слово в ANSI C++0x. В результате все идентификаторы с тем же именем в ранних приложениях должны быть обновлены, иначе они будут неправильно интерпретированы.
Существующие инструменты транскомпилятора
Давайте рассмотрим некоторые инструменты, доступные для перевода кода между языками программирования.
BCX. BCX – это небольшой инструмент командной строки, который берет файл исходного кода BCX BASIC и преобразует его в файл исходного кода C, который можно скомпилировать с помощью любого компилятора C или C++.
PERTHON — Perthon переводит исходный код Python в исходный код Perl 5.x, который люди могут читать. Он анализирует с помощью Parse::Rec Descent Дэмиана Конвея и пытается повторно реализовать язык Python в соответствии со Справочным руководством Python и грамматикой BNF.
GWT от Google. С помощью GWT вы можете создавать и отлаживать приложения AJAX на Java, используя предпочитаемые инструменты разработки Java. Компилятор GWT преобразует ваше приложение Java в совместимый с браузером JavaScript и HTML, когда вы запускаете его в рабочую среду.
Hiphop от Facebook. HipHop компилирует ваш исходный код PHP с помощью g++ после его программного преобразования в высокоэффективный C++.
TransCoder AI от Facebook — TransCoder, система Facebook, которая может выполнять перевод между C++, Java и Python, использует подход к решению проблемы без учителя. TransCoder начинается с предварительной подготовки межъязыковой языковой модели, которая преобразует фрагменты кода, выражающие одни и те же инструкции, в эквивалентные представления независимо от языка программирования.
Будущий прогресс
Цель программистов – добиться максимальной эффективности преобразования без ущерба для качества преобразованной системы.Несмотря на то, что преобразование языка кажется простым, это геркулесова задача со множеством сложностей. Это по праву считается одной из десяти основных трудностей программирования, с которыми сталкивается земной шар. Еще до того, как будет доступен надежный полуавтоматический преобразователь, необходимо добиться значительного прогресса. Возможно, в будущем станет возможным переводить код между двумя совершенно разными платформами одним щелчком мыши. Поскольку одна библиотека не может безупречно выполнить такое преобразование и определить шаблон замены в языке, это может зависеть от достижений в области искусственного интеллекта. Хорошим примером является преобразование настольной программы в веб-приложение и наоборот. Точно так же рассуждения, используемые для разработки аналогичного настольного или веб-приложения, могут быть применены для создания мобильных приложений. Следовательно, в ближайшем будущем мы можем ожидать появления компетентного транскомпилятора от исследовательского сообщества.
Искусственный интеллект подходит для вашей работы по программированию! Ну это заголовок. Правда в том, что потребуется больше времени, чтобы полностью вывести человека из цикла, но это не значит, что сейчас нет задач, которые ИИ не может взять на себя.
Искусственный интеллект проникает во все аспекты современных технологий, и программирование не является исключением. В недавней статье «Неконтролируемый перевод языков программирования», подготовленной Facebook AI Research, описывается, как нейронная сеть научилась переводить существующие программы с одного языка на другой — транскомпиляции. Как говорится в документе:
"Транскомпилятор, также известный как транслятор исходного кода, представляет собой систему, которая преобразует исходный код из одного языка программирования высокого уровня (например, C++ или Python) в другой. Транскомпиляторы в основном используются для обеспечения совместимости. , а также для переноса кодовых баз, написанных на устаревшем или устаревшем языке (например, COBOL, Python 2), на современный язык. Обычно они основаны на созданных вручную правилах перезаписи, применяемых к абстрактному синтаксическому дереву исходного кода. К сожалению, полученные переводы часто не удобочитаемы, не соблюдают соглашения о целевом языке и требуют ручных изменений для правильной работы. Общий процесс перевода занимает много времени и требует знаний как исходного, так и целевого языков, что делает проекты по переводу кода дорогими."< /p>
Это, конечно, причина того, что Cobol до сих пор используется во многих финансовых системах. Если вы когда-нибудь пытались перевести даже небольшую программу с двух похожих языков, скажем, с Python 2 на 3, вы знаете, что это удивительно сложно. Всплывают вещи, о которых вы никогда не думали, и все идет не по плану.
Группа Facebook взяла много кода с GitHub на C++, Java и Python. Идея заключалась в том, чтобы использовать методы обработки естественного языка для извлечения шаблонов из языков. Программа изучила независимое от языка представление функции, а затем смогла использовать его для создания функции на другом языке. Ключевым фактором является то, что это представление было изучено без присмотра, то есть ни один человек не сообщал нейронной сети, что делает программа, не было цели для обучения и не применялось вознаграждение за подкрепление. Образцов в языке, по-видимому, достаточно. Что удивительно, но аналогичный подход работает и для естественных языков, что еще более удивительно.
Систему не обучали, показывая ей примеры одной и той же функции, написанной на другом языке, как вы можете представить, как она будет работать. Это больше похоже на то, как человек выполняет эту работу, читая функцию, понимая, что она делает, а затем повторно выражая ее на новом языке.
Кажется, да.
"Мы видим, что TransCoder успешно понимает синтаксис, характерный для каждого языка, изучает структуры данных и их методы, а также правильно согласовывает библиотеки между языками программирования".
Это не всегда правильно, но достаточно впечатляет, чтобы предположить, что происходит что-то глубокое.
Идея независимого от языка представления программы, которое можно использовать для создания реализации на определенном языке, может привести к созданию ИИ, способного генерировать программы на основе требований или описаний.
Возможно, это еще не с нами, но, да, я должен сказать, что день, когда ИИ сможет взять на себя создание программ, кажется намного ближе после этого исследования.
Дополнительная информация
Мари-Анн Лашо, Батист Розьер, Ловик Шануссо и Гийом Лэмпл
Читайте также: