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

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

  • Это ориентировано на веб-разработку. Исходный и целевой код будут находиться поверх фреймворков (которые мне также придется написать). Эти фреймворки будут охватывать шаблон проектирования MVC и следовать строгим соглашениям о кодировании. Это должно несколько упростить перевод.

  • Я также смотрю на IOC и внедрение зависимостей, поскольку они могут упростить процесс перевода и снизить вероятность ошибок.

  • Я воспользуюсь модулем синтаксического анализатора Python, который позволяет мне возиться с абстрактным синтаксическим деревом. . По-видимому, самое близкое, что я могу найти с PHP, - это token_get_all (), что является началом.

  • С этого момента я могу создавать AST, таблицы символов и поток управления.

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

Прежде чем вы спросите, какой в ​​этом смысл? Ответ ... Это будет интересный опыт обучения. Если у вас есть идеи, как сделать это менее пугающим, дайте мне знать.


РЕДАКТИРОВАТЬ:

Мне больше интересно знать, какие типы шаблонов я могу применить к коду, чтобы упростить перевод (например, IoC, SOA?) Кода, чем то, как сделать перевод.


person NullUserException    schedule 11.08.2010    source источник
comment
Вы когда-нибудь смотрели на такие системы, как .NET CLR или Perl6's Parrot? Они компилируют набор языков до промежуточного представления, которое может выполняться обычным интерпретатором. Если вы можете вернуться от промежуточного представления к языку, у вас есть переводчик.   -  person Borealid    schedule 11.08.2010
comment
@Borealid AFAIK .NET CIL (относительно) легко скомпилировать в, но удачи вам получить обратно читаемый код. Сейчас смотрю на Попугая.   -  person NullUserException    schedule 11.08.2010
comment
Есть аналогичные проекты для других языков; Я не уверен, насколько богаты их авторы. И я на самом деле очень сдерживаюсь здесь, потому что нуждаюсь в фреймворке и придерживаюсь строгих правил кодирования.   -  person NullUserException    schedule 11.08.2010
comment
Я не могу добавить каких-либо конкретных знаний, но смотрели ли вы на пижамы (pyjs.org), в частности на translator.py? Это компилятор python для javascript.   -  person stephan    schedule 11.08.2010
comment
@stephan Мне нравится это имя (пижама). Спасибо за ссылку. Я думаю, что Python упростил выполнение этих переводов благодаря модулю синтаксического анализатора. Вот почему существует переводчик с Python на Perl, но не наоборот.   -  person NullUserException    schedule 11.08.2010
comment
Посмотрите на phpqatools.org некоторые инструменты, которые позволяют анализировать PHP-код на основе AST и кода операции.   -  person Gordon    schedule 14.08.2010
comment
@NullUserException В ответ на AFAIK .NET CIL (относительно) легко скомпилировать, но удачи в получении обратно читаемого кода. Что ж, это именно то, что делает Reflector!   -  person Josh Stodola    schedule 19.08.2010
comment
@NullUserException Действительно, Reflector отлично справляется со своей задачей. Всегда помните pdbs :)   -  person Rushyo    schedule 20.08.2010
comment
Re EDIT: если у вас есть контроль над кодом, который будет переведен, самое очевидное, что нужно сделать, - это избегать конструкций, которые трудно переводить! Например, C намного проще перевести на Java, если нет арифметики с указателями. Для Python я бы, вероятно, держался подальше от замыканий. Другая вещь, которую вы можете сделать, - это написать исходный код таким образом, чтобы более сложные для перевода части всегда кодировались идиоматически, что упростило их распознавание и обработку особых случаев.   -  person Ira Baxter    schedule 21.08.2010
comment
Не могу найти здесь вопрос.   -  person Lightness Races in Orbit    schedule 26.03.2013
comment
@NullUserException: свяжитесь со мной в автономном режиме.   -  person Ira Baxter    schedule 09.07.2013
comment
написать интерфейс llvm   -  person Jules G.M.    schedule 16.04.2015
comment
Если вы считаете, что этот вопрос не следует закрывать, нажмите повторно.   -  person Ira Baxter    schedule 17.04.2016


Ответы (6)


Я использовал инструменты для создания (DMS Software Reengineering Toolkit) для создания программ общего назначения манипуляции (особый случай - языковой перевод) с 1995 г. при поддержке сильной команды компьютерных ученых. DMS обеспечивает общий синтаксический анализ, построение AST, таблицы символов, управление и анализ потока данных, применение правил перевода, регенерацию исходного текста с комментариями и т. Д., Все это параметризуется явными определениями компьютерных языков.

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

Нет ничего плохого в том, что вы думаете о создании переводчика с одного языка на другой или пытаетесь его реализовать, но я думаю, что для реальных языков это будет гораздо более сложной задачей, чем вы ожидаете. Мы потратили около 100 человеко-лет только на DMS и еще 6-12 месяцев на каждое «надежное» определение языка (включая то, которое мы с трудом создали для PHP), и намного больше для неприятных языков, таких как C ++. Это будет «адский опыт обучения»; это было для нас. (Вы можете найти раздел технических статей на указанном выше веб-сайте, чтобы начать это обучение).

Люди часто пытаются построить какой-то универсальный механизм, начиная с некоторой части технологии, с которой они знакомы, которая выполняет часть работы. (Python AST - отличный пример). Хорошая новость в том, что часть работы сделана. Плохая новость заключается в том, что в машину встроен миллион предположений, большинство из которых вы не обнаружите, пока не попытаетесь заставить его делать что-то еще. В этот момент вы обнаруживаете, что механизм настроен на то, что он делает изначально, и действительно, действительно сопротивляется вашей попытке заставить его делать что-то еще. (Я подозреваю, что попытка заставить Python AST моделировать PHP будет очень весело).

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

Многие люди также ошибаются, полагая, что, если они могут анализировать (и, возможно, получить AST), они хорошо на пути к выполнению чего-то сложного. Один из трудных уроков состоит в том, что вам нужны таблицы символов и анализ потоков, чтобы проводить хороший анализ или преобразование программы. AST необходимы, но недостаточны. Это причина того, что книга компиляторов Ахо и Ульмана не ограничивается главой 2. (ОП имеет на это право в том смысле, что он планирует построить дополнительные механизмы помимо AST). Для получения дополнительной информации по этой теме см. Жизнь после анализа.

Замечание о том, что «мне не нужен идеальный перевод», вызывает беспокойство. Что делают слабые переводчики, так это конвертируют «легкие» 80% кода, оставляя сложные 20% делать вручную. Если приложение, которое вы собираетесь преобразовать, довольно маленькое, и вы собираетесь преобразовать его только один раз, то эти 20% в порядке. Если вы хотите преобразовать много приложений (или даже одно с небольшими изменениями с течением времени), это нехорошо. Если вы попытаетесь преобразовать 100K SLOC, то 20% - это 20 000 исходных строк кода, которые трудно перевести, понять и изменить в контексте еще 80 000 строк переведенной программы, которую вы уже не понимаете. Это требует огромных усилий. На уровне миллиона строк это просто невозможно на практике. (Поразительно, но есть люди, которые не доверяют автоматизированным инструментам и настаивают на переводе миллионов строк системы вручную; это даже сложнее, и они обычно обнаруживают болезненные результаты с длительными задержками, высокими затратами и часто откровенным отказом.)

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

Еще одно важное соображение - это размер транслируемого кода. Даже с хорошими инструментами для создания работоспособного надежного переводчика требуется много энергии. Хотя создание переводчика вместо простого ручного преобразования кажется привлекательным и крутым, для небольших кодовых баз (например, примерно до 100 000 SLOC по нашему опыту) экономия просто не оправдывает этого. Никому не нравится этот ответ, но если вам действительно нужно перевести всего 10K SLOC кода, вам, вероятно, лучше просто укусить пулю и сделать это. И да, это больно.

Я считаю наши инструменты очень хорошими (но тогда я довольно пристрастен). А создать хорошего переводчика по-прежнему очень сложно; на это у нас уходит 1,5–2 человеко-года, и мы знаем, как использовать наши инструменты. Разница в том, что с таким количеством оборудования мы добиваемся успеха гораздо чаще, чем терпим неудачу. .

person Community    schedule 11.08.2010
comment
Вы когда-нибудь думали о том, чтобы передать свое мучительно созданное определение PHP обратно сообществу PHP в целом, или оно слишком тесно связано с вашим собственным потоком доходов, чтобы сделать это возможным? - person TML; 17.08.2010
comment
Меня просили сделать все, что мы делаем, с открытым исходным кодом от множества людей, которые не хотели вносить свой вклад в поток доходов, и у которых не было энергии, чтобы делать работу и открывать исходный код самостоятельно. Если вы вносите лишь небольшую часть в очень большой проект и / или у вас есть другой источник дохода, открытый исходный код кажется прекрасным. Если вы сделали всю работу сами и это ваш единственный источник дохода, это намного менее привлекательно. [Я не хочу вдаваться в дискуссию об относительных достоинствах философии свободного программного обеспечения, поэтому я не буду участвовать в каких-либо дальнейших комментариях по этому поводу] - person Ira Baxter; 17.08.2010
comment
Я согласен с тем, что вы здесь сказали, поэтому я сформулировал вопрос именно так. Я думаю, мы должны интуитивно понять из этого ответа, что вы чувствуете, что он слишком тесно связан с вашим доходом, и в этом нет абсолютно ничего плохого - я просто подумал, что стоит спросить. - person TML; 20.08.2010
comment
@IraBaxter Вы просто говорите общие идиомы о практиках, связанных с компьютером, которые можно применить ко многим другим практикам. Единственное, что вас интересует во всем, что вы написали, - это ссылки на semanticdesigns.com (это ваша компания). - person amirouche; 04.04.2014
comment
@IraBaxter, почему в этом ответе есть ссылка на пресс-релиз вашей компании? - person xaxxon; 06.10.2016
comment
@xaxxon: Это явное доказательство того, что я знаю, о чем говорю. Читатели, кажется, одобряют ответ, даже если вы этого не сделаете. - person Ira Baxter; 06.10.2016
comment
Он предоставляет доказательство того, что вы создали веб-страницу. Почему бы вам не дать ссылку на соответствующий источник. Это на самом деле было бы полезно - при условии, что это будет хорошо. - person xaxxon; 06.10.2016
comment
В своих ответах вы часто указываете ссылки на страницы, связанные с Clang. Это только доказывает, что кто-то другой может создать веб-страницу. Большинство из нас полагает, что хорошо написанная веб-страница подразумевает серьезную реальную работу, а не просто мошенническую попытку обмануть читателя, как вы, кажется, подразумеваете в своем ответе. Вы действительно считаете, что веб-страница является мошеннической? Страница содержит справочную информацию о соответствующем источнике; он анонимизирован, потому что этого требовал контракт на выполнение работ. Я ничего не могу поделать. - person Ira Baxter; 06.10.2016
comment
@xaxxon: если он хорош. Хорошо, вы можете обвинить видение и инструменты в бесполезности (никуда не годном). Или вы можете решить, что я не лгу, и что инструменты были использованы для выполнения очень сложной задачи технического реинжиниринга критически важной системы одного из самых современных самолетов в мире. Возможно, я не смогу изменить ваше мнение. Ваше мнение не меняет фактов. - person Ira Baxter; 06.10.2016
comment
Если вы хотите подтвердить идеи в DMS или лежащие в ее основе, вы можете взглянуть на некоторые технические статьи, опубликованные после того, как они были просмотрены предположительно беспристрастными исследователями, хорошо осведомленными в этой области. См. semanticdesigns.com/Company/Publications/ и Акерс, Р., Бакстер, И., Мехлих, М., Эллис, Б., Люке, К., Практический пример: реинжиниринг моделей компонентов C ++ с помощью автоматического преобразования программ, информационных и программных технологий 49 (3): 275- 291 2007. sciencedirect.com/science/article/pii/S0950584906001856 - person Ira Baxter; 06.10.2016

Мой ответ будет касаться конкретной задачи синтаксического анализа Python, чтобы перевести его на другой язык, а не аспектов более высокого уровня, которые Ира хорошо рассмотрел в своем ответе.

Вкратце: не используйте модуль синтаксического анализатора, есть более простой способ.

Модуль ast, доступный начиная с Python 2.6, гораздо больше подходит для ваших нужд, поскольку он дает вам готовый AST для работы. Я написал статью об этом в прошлом году, но короче говоря, используйте parse метод ast для синтаксического анализа исходного кода Python в AST. Модуль parser предоставит вам дерево синтаксического анализа, а не AST. Остерегайтесь разницы.

Теперь, поскольку AST Python достаточно подробны, с учетом AST работа с интерфейсом не так уж и сложна. Я полагаю, у вас может быть простой прототип для некоторых частей функциональности, готовый довольно быстро. Однако получение полного решения займет больше времени, в основном из-за разницы в семантике языков. Простое подмножество языка (функции, базовые типы и т. Д.) Можно легко перевести, но как только вы перейдете на более сложные уровни, вам понадобится тяжелая техника для имитации ядра одного языка в другом. Например, рассмотрим генераторы Python и списки, которые не существуют в PHP (насколько мне известно, что, по общему признанию, плохо, когда задействован PHP).

В качестве последнего совета рассмотрим инструмент 2to3, созданный разработчиками Python для перевода кода Python 2 в код Python 3. Что касается внешнего интерфейса, в нем есть большинство элементов, необходимых для перевода Python на что-то. Однако, поскольку ядра Python 2 и 3 схожи, никаких механизмов эмуляции там не требуется.

person Eli Bendersky    schedule 14.08.2010
comment
Weeeell. 2to3 - это просто AST to AST. Он не поддерживает выполнение чего-либо, выходящего за рамки возможностей модуля ast. Обратите внимание, что все переводы идут с синтаксиса из, поддерживаемого хост-процессом python, в синтаксис, поддерживаемый хост-процессом python. Нет переводчика, который бы добавил, скажем, аннотации к функциям, потому что 2.6 его не поддерживает. - person habnabit; 16.08.2010
comment
... и вопрос OP может быть сформулирован в краткосрочной перспективе, как перейти от Python 2.6 AST к ... чему-то в PHP. Модуль ast, скорее всего, не захочет хорошо представлять синтаксис PHP, так что это даже не удивительно. - person Ira Baxter; 16.08.2010
comment
@Aaron: 2to3 можно рассматривать как пример использования AST, сгенерированного из ast. - person Eli Bendersky; 16.08.2010
comment
AFAIK, 2to3, возможно, является более простым переводом, чем Python на PHP (в конце концов, его Python на Python, верно)? И даже не особо хорошо работает. Обратите внимание на большое количество Python 2.6, которое еще не было пропущено через 2to3 ... потому что, по всей видимости, есть еще куча исправлений, которые нужно исправить вручную. Если бы он был полностью автоматизирован, Python 2.6 был бы мертв. - person Ira Baxter; 22.08.2010

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

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

Например:

word = 'This is not a word'
print word[::-2]

требуется много кода C ++ для дублирования (хорошо, ну, вы можете сделать это довольно быстро с некоторыми конструкциями цикла, но все же).

Думаю, это немного отступление.

Вы когда-нибудь писали токенизатор / парсер на основе языковой грамматики? Вы, вероятно, захотите узнать, как это сделать, если вы этого не сделали, потому что это основная часть этого проекта. Я бы придумал базовый полный синтаксис Тьюринга - что-то очень похожее на Python байт-код. Затем вы создаете лексический анализатор / анализатор, который использует грамматику языка (возможно, используя BNF) и на основе грамматики компилирует язык в ваш промежуточный язык. Тогда вам нужно сделать обратное - создать синтаксический анализатор вашего языка на целевые языки на основе грамматики.

Самая очевидная проблема, которую я вижу, заключается в том, что сначала вы, вероятно, создадите ужасно неэффективный код, особенно на более мощных * языках, таких как Python.

Но если вы сделаете это таким образом, вы, вероятно, сможете найти способы оптимизации вывода по мере продвижения. Обобщить:

  • прочитать предоставленную грамматику
  • компилировать программу в промежуточный (но также полный по Тьюрингу) синтаксис
  • компилировать промежуточную программу в конечный язык (на основе предоставленной грамматики)
  • ...?
  • Выгода!(?)

* под мощным я подразумеваю, что это занимает 4 строки:

myinput = raw_input("Enter something: ")
print myinput.replace('a', 'A')
print sum(ord(c) for c in myinput)
print myinput[::-1]

Покажите мне другой язык, который может делать что-то подобное, в 4 строки, и я покажу вам язык, столь же мощный, как Python.

person Wayne Werner    schedule 18.08.2010
comment
Вы когда-нибудь писали токенизатор / парсер на основе языковой грамматики? Я сделал это с помощью JavaCC. - person NullUserException; 19.08.2010
comment
Стажер Джоэла за лето выполнял частичную работу. Его исходный язык был подмножеством существующего языка, и, по-видимому, это подмножество можно было несколько скорректировать. Это значительно упрощает работу. Точно так же NullPointerException может захотеть начать с более простых частей Python, возможно, пройдя через более сложные вещи для ручного преобразования (как указано в вопросах). - person David Thornley; 19.08.2010
comment
@NullUserException: у вас будет некоторая информация, но в основном вы будете выполнять повторную реализацию JavaCC, только вместо Java в качестве языка вывода вы будете делать ‹вставьте здесь язык›. @ Дэвид, именно так. Даже Чертополоху нужна помощь с некоторыми языковыми конструкциями. Если бы я был OP, я бы сначала занялся функциональностью, а затем оптимизировал бы, иначе я бы навсегда застрял, пытаясь заставить C ++ выполнять нарезку строк (с шагами): p - person Wayne Werner; 19.08.2010
comment
@WayneWerner Для записи, такие языки, как C #, вообще не требуют перевода строки. (По крайней мере, не после того, как вы удалили однострочные комментарии.) Таким образом, вы можете написать любую программу на C # в одну строку. Но, конечно, я понимаю, к чему вы клоните. - person leviathanbadger; 16.08.2013
comment
@ aboveyou00: Не думаю, что это правильно. Если вы запрещаете условные выражения препроцессора, возможно, вы правы. - person Ira Baxter; 28.03.2014
comment
@IraBaxter (вы снова ...) синтаксис, который вы говорите, трудно перевести, совсем не сложно перевести, если вы напишете его как myinput .__ getitem __ (Slice (None, None, -1)) или myinput .__ slice __ (None, None , -1). Я не понимаю, что вам кажется трудным. - person amirouche; 04.04.2014
comment
@amirouche: Похоже, вы умышленно неверно истолковываете сказанное. Я просто отметил, в частности, в ответ на вышеизложенное, что C # действительно имеет условные выражения препроцессора, и эти условные выражения требуют новой строки, поэтому вы не можете писать любую программу на C # в одной строке . Откровенно говоря, наличие или отсутствие новых строк никак не влияет на принципиальные трудности перевода. - person Ira Baxter; 04.04.2014
comment
@IraBaxter, это, конечно, вовсе не умышленно, я не приду в ТАК, чтобы дурачить людей, особенно своим настоящим именем. Комментарий был адресован Уэйну Вернеру. - person amirouche; 04.04.2014
comment
@amirouche: если комментарий был предназначен для Уэйна, не добавляйте к нему мое имя. Это только добавляет путаницы. Я не понимаю твоего замечания по поводу настоящего имени. AFAIK, только выше вы00 не предоставил свое настоящее имя, и я не понимаю, какое это имеет значение в этом обсуждении. - person Ira Baxter; 04.04.2014

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

Есть относительно простой способ начать. Сначала получите http://sourceforge.net/projects/lime-php/ ( если вы хотите работать на PHP) или что-то подобное и просмотрите пример кода. Затем вы можете написать лексический анализатор, используя последовательность регулярных выражений, и передать токены в сгенерированный вами синтаксический анализатор. Ваши семантические действия могут либо выводить код непосредственно на другом языке, либо создавать некоторую структуру данных (мыслить объекты, человек), которые вы можете массировать и перемещать для генерации выходного кода.

Вам повезло с PHP и Python, потому что во многих отношениях это один и тот же язык, но с другим синтаксисом. Труднее всего преодолеть семантические различия между грамматическими формами и структурами данных. Например, в Python есть списки и словари, а в PHP - только ассоциативные массивы.

Подход «учащийся» состоит в том, чтобы создать что-то, что нормально работает для ограниченного подмножества языка (например, только операторы печати, простую математику и присвоение переменных), а затем постепенно снимать ограничения. Это в основном то, что делали все "большие" ребята в этой области.

Да, и поскольку у вас нет статических типов в Python, может быть лучше написать и полагаться на функции PHP, такие как «python_add», которые добавляют числа, строки или объекты в соответствии с тем, как это делает Python.

Очевидно, это может стать намного больше, если вы позволите этому.

person Ian    schedule 17.08.2010
comment
На самом деле, я не говорил, не беспокойтесь. Я сказал, что переводить языки в целом очень сложно. Если ОП продолжит свой первоначальный путь использования деревьев Python, чтобы попытаться сгенерировать PHP, он многому научится, и я полностью поддерживаю опыт обучения; Я тоже там начал. Он не сможет легко добавлять новые языки. - person Ira Baxter; 17.08.2010
comment
@IraBaxter Я не могу поддержать ваше утверждение, сделать Python- ›PHP и PHP-› Javascript было бы довольно легко. ср. последняя часть stackoverflow.com/a/22850139/140837 в середине ответа Я также рассматриваю вашу аргументацию - person amirouche; 04.04.2014

Я поддержу точку зрения @EliBendersky относительно использования ast.parse вместо парсера (о котором я раньше не знал). Я также настоятельно рекомендую вам просмотреть его блог. Я использовал ast.parse для перевода Python-> JavaScript (@ https://bitbucket.org/amirouche/pythonium < / а>). Я придумал дизайн Pythonium, немного просмотрев другие реализации и попробовав их самостоятельно. Я раздвоил Pythonium из https://github.com/PythonJS/PythonJS, который я тоже начал. полный переписать. Общий дизайн вдохновлен PyPy и http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-89-1.pdf документ.

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

  • Реализуйте семантику Python в обычном старом JavaScript с использованием наследования прототипов: AFAIK невозможно реализовать множественное наследование Python с использованием объектной системы прототипов JS. Позже я попытался сделать это, используя другие приемы (см. Getattribute). Насколько я знаю, в JavaScript нет реализации множественного наследования Python, лучшее, что существует, - это одиночное наследование + миксины, и я не уверен, что они обрабатывают наследование алмаза. Вроде как Skulpt, но без закрытия Google.

  • Я пробовал использовать Google clojure, как и Skulpt (компилятор), вместо того, чтобы читать код Skulpt #fail. Во всяком случае, из-за объектной системы на основе прототипа JS все еще невозможно. Создание привязки было очень-очень сложным, вам нужно было написать JavaScript и много шаблонного кода (см. https://github.com/skulpt/skulpt/issues/50, где я призрак). В то время не было четкого способа интегрировать привязку в систему сборки. Я думаю, что Skulpt - это библиотека, и вам просто нужно включить свои файлы .py в html для выполнения, разработчик не требует выполнения этапа компиляции.

  • Пробовал pyjaco (компилятор), но создание привязок (вызов кода Javascript из кода Python) было очень сложно, слишком много шаблонного кода для создания каждый раз. Теперь я думаю, что pyjaco - это тот, который больше похож на Pythonium. pyjaco написан на Python (в том числе ast.parse), но многое написано на JavaScript и использует наследование прототипов.

На самом деле мне никогда не удавалось запустить Pyjamas #fail, и я никогда не пытался снова прочитать код #fail. Но на мой взгляд, пижама выполняла перевод API-> API (или фреймворк в фреймворк), а не перевод Python в JavaScript. Платформа JavaScript использует данные, которые уже есть на странице, или данные с сервера. Код Python - это всего лишь «сантехника». После этого я обнаружил, что pajamas на самом деле был настоящим переводчиком python-> js.

Тем не менее, я думаю, что можно сделать перевод API-> API (или framework-> framework), и это в основном то, что я делаю в Pythonium, но на более низком уровне. Вероятно, Pyjamas использует тот же алгоритм, что и Pythonium ...

Затем я обнаружил, что brython полностью написан на Javascript, например Skulpt, не требует компиляции и лишен всякой ерунды ... но написан на JavaScript.

С момента написания начальной строки в ходе этого проекта я знал о PyPy, даже о бэкэнде JavaScript для PyPy. Да, вы можете, если найдете, напрямую сгенерировать интерпретатор Python в JavaScript из PyPy. Говорят, это была катастрофа. Я не читал где почему. Но я думаю, причина в том, что промежуточный язык, который они используют для реализации интерпретатора, RPython, является подмножеством Python, адаптированным для перевода на C (и, возможно, asm). Ира Бакстер говорит, что вы всегда делаете предположения, когда создаете что-то, и, вероятно, вы точно настраиваете его, чтобы он был лучшим для того, что он должен делать в случае перевода PyPy: Python-> C. Эти предположения могут не иметь отношения к другому контексту, хуже того, что они могут привести к накладным расходам, в противном случае прямой перевод, скорее всего, всегда будет лучше.

Написание интерпретатора на Python звучало как (очень) хорошая идея. Но меня больше интересовал компилятор по соображениям производительности. К тому же, на самом деле, компилировать Python в JavaScript проще, чем интерпретировать его.

Я начал PythonJS с идеей собрать подмножество Python, которое я мог бы легко перевести на JavaScript. Сначала я даже не стал внедрять объектно-ориентированную систему из-за прошлого опыта. Подмножество Python, которое мне удалось перевести на JavaScript:

  • функция с полной семантикой параметров как при определении, так и при вызове. Это та часть, которой я горжусь больше всего.
  • а / если / элиф / еще
  • Типы Python были преобразованы в типы JavaScript (никаких типов Python не существует)
  • for может перебирать только массивы Javascript (для массива in)
  • Прозрачный доступ к JavaScript: если вы напишете Array в коде Python, он будет переведен в Array в javascript. Это самое большое достижение с точки зрения удобства использования по сравнению с конкурентами.
  • Вы можете передать функцию, определенную в исходном коде Python, в функции javascript. Аргументы по умолчанию будут приняты во внимание.
  • В нем есть специальная функция под названием new, которая переводится в JavaScript new, например: new (Python) (1, 2, spam, «egg») переводится в «new Python (1, 2, spam,« egg »).
  • "var" автоматически обрабатываются переводчиком. (очень хорошая находка от Бретта (участник PythonJS).
  • глобальное ключевое слово
  • закрытие
  • лямбды
  • понимание списка
  • импорт поддерживается через requirejs
  • наследование одного класса + миксин через classyjs

Это кажется большим, но на самом деле очень узким по сравнению с полноценной семантикой Python. Это действительно JavaScript с синтаксисом Python.

Сгенерированный JS идеален, т.е. нет накладных расходов, его нельзя улучшить по производительности дальнейшим редактированием. Если вы можете улучшить сгенерированный код, вы также можете сделать это из исходного файла Python. Кроме того, компилятор не полагался на какие-либо уловки JS, которые можно найти в .js, написанных http://superherojs.com/, поэтому он очень удобочитаемый.

Прямым потомком этой части PythonJS является режим Pythonium Veloce. Полную реализацию можно найти @ https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/veloce/veloce.py?at=master 793 SLOC + около 100 SLOC общего кода с другим переводчиком.

Адаптированная версия pystones.py может быть переведена в режим Veloce cf. https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pystone/?at=master

После настройки базового перевода Python-> JavaScript я выбрал другой путь для перевода полного Python в JavaScript. Способ glib выполнения объектно-ориентированного кода на основе классов, за исключением того, что целевой язык - это JS, поэтому у вас есть доступ к массивам, объектам, подобным карте, и многим другим трюкам, и вся эта часть была написана на Python. IIRC нет кода javascript, написанного в переводчике Pythonium. Получить единичное наследование несложно, вот те сложные моменты, которые делают Pythonium полностью совместимым с Python:

  • spam.egg в Python всегда переводится на getattribute(spam, "egg") Я не профилировал это в частности, но я думаю, что там, где это теряет много времени, и я не уверен, что смогу улучшить его с помощью asm.js или чего-то еще.
  • порядок разрешения методов: даже с алгоритмом, написанным на Python, перевод его в код, совместимый с Python Veloce, был большой задачей.
  • getattributre: фактический алгоритм разрешения getattribute довольно сложен, и он по-прежнему не поддерживает дескрипторы данных.
  • на основе класса метакласса: я знаю, где вставить код, но все же ...
  • последнее бу не в последнюю очередь: some_callable (...) всегда переводится в "call (some_callable)". AFAIK переводчик вообще не использует логический вывод, поэтому каждый раз, когда вы выполняете вызов, вам нужно проверять, какой тип объекта должен называть его так, как он должен вызываться.

Эта часть учтена в https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/compliant/runtime.py?at=master Он написан на Python, совместимом с Python Veloce.

Фактический совместимый переводчик https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/compliant/compliant.py?at=master не генерирует код JavaScript напрямую и, что наиболее важно, не выполняет преобразование ast-> ast. Я пробовал использовать ast-> ast, и ast, даже если он лучше, чем cst, нехорошо работать даже с ast.NodeTransformer и, что более важно, мне не нужно делать ast-> ast.

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

  • var / global: чтобы иметь возможность что-то var, я должен знать, что мне нужно, а не var. Вместо того, чтобы генерировать блок, отслеживающий, какие переменные созданы в данном блоке, и вставляя их поверх сгенерированного функционального блока, я просто ищу удобное назначение переменных, когда я вхожу в блок, прежде чем фактически посещать дочерний узел для генерации связанного кода.
  • yield, генераторы пока имеют специальный синтаксис в JS, поэтому мне нужно знать, какая функция Python является генератором, когда я хочу написать «var my_generator = function»

Поэтому я не посещаю каждый узел один раз на каждом этапе перевода.

Общий процесс можно описать как:

Python source code -> Python ast -> Python source code compatible with Veloce mode -> Python ast -> JavaScript source code

Встроенные функции Python написаны на коде Python (!), IIRC имеет несколько ограничений, связанных с типами начальной загрузки, но у вас есть доступ ко всему, что может переводить Pythonium в совместимый режим. Взгляните на https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/compliant/builtins/?at=master

Чтение JS-кода, сгенерированного из совместимого с pythonium, можно понять, но карты источников очень помогут.

Ценный совет, который я могу дать вам в свете этого опыта, - это старые добрые пердуны:

  • Подробно изучите тему как в литературе, так и в существующих проектах с закрытым исходным кодом или бесплатно. Когда я просматривал различные существующие проекты, мне следовало уделить им больше времени и мотивации.
  • задавать вопросы! Если бы я знал заранее, что бэкэнд PyPy бесполезен из-за накладных расходов из-за семантического несоответствия C / Javascript. У меня, возможно, была идея Pythonium раньше, чем 6 месяцев назад, может быть, 3 года назад.
  • знайте, что вы хотите делать, имейте цель. В этом проекте у меня были другие цели: немного поработать JavaScript, узнать больше о Python и уметь писать код Python, который будет работать в браузере (подробнее об этом ниже).
  • неудача - это опыт
  • маленький шаг - это шаг
  • начать с малого
  • большая мечта
  • делать демо
  • повторять

Только с режимом Python Veloce, я очень счастлив! Но по пути я обнаружил, что то, что я действительно искал, - это освобождение меня и других от Javascript, но, что более важно, возможность создавать удобным способом. Это привело меня к схемам, DSL, моделям и, в конечном итоге, к моделям, специфичным для предметной области (см. http://dsmforum.org/ ).

О чем отзывается Ира Бакстер:

Оценки совершенно бесполезны. У меня ушло около 6 месяцев свободного времени как на PythonJS, так и на Pythonium. Так что я могу ожидать большего от 6 месяцев полной занятости. Я думаю, все мы знаем, что 100 человеко-лет в контексте предприятия могут означать и вовсе не означать ...

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

Если не доказано, что это невозможно, остается место для воображения:

  • найти доказательство, доказывающее, что это невозможно

и

  • Если это невозможно, может быть «неполная» проблема, у которой есть решение.

or

  • если это не невозможно, найти решение

Это не просто оптимистическое мышление. Когда я начинал Python-> Javascript, все говорили, что это невозможно. PyPy невозможно. Метаклассы слишком сложные. и т. д. Я думаю, что единственная революция, которая привносит PyPy в бумагу Scheme-> C (которой 25 лет), - это автоматическая генерация JIT (на основе подсказок, написанных в интерпретаторе RPython, я думаю).

Большинство людей, которые говорят, что что-то «сложно» или «невозможно», не приводят причин. C ++ сложно разобрать? Я знаю, что это (бесплатный) синтаксический анализатор C ++. Зло в деталях? Я знаю это. Сказать, что это невозможно в одиночку, бесполезно. Это даже хуже, чем «бесполезно», это обескураживает, и некоторые люди хотят отговорить других. Я слышал об этом вопросе через https://stackoverflow.com/questions/22621164/how-to-automatically-generate-a-parser-code-to-code-translator-from-a-corpus.

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

Мне больше интересно знать, какие типы шаблонов я могу применить к коду, чтобы упростить перевод (например, IoC, SOA?) Кода, чем то, как сделать перевод.

Я не вижу шаблонов, которые нельзя было бы перевести с одного языка на другой хотя бы неидеально. Поскольку перевод с языка на язык возможен, вам лучше сначала постараться. Поскольку, я думаю, согласно http://en.wikipedia.org/wiki/Graph_isomorphism_problem, перевод между двумя компьютерными языками - это дерево или изоморфизм DAG. Даже если мы уже знаем, что они оба завершены по Тьюрингу, так что ...

Framework-> Framework, который я лучше визуализирую как перевод API-> API, может быть тем, что вы могли бы иметь в виду как способ улучшить сгенерированный код. Например: Пролог как очень специфический синтаксис, но все же вы можете выполнять Пролог как вычисления, описывая тот же граф в Python ... Если бы мне пришлось реализовать переводчик Пролога в Python, я бы не реализовал унификацию в Python, а в библиотеке C и пришел с "синтаксисом Python", который очень хорошо читается питонистом. В конце концов, синтаксис - это всего лишь «картина», которой мы придаем смысл (поэтому я и начал схему). Зло в деталях языка, и я не говорю о синтаксисе. Концепции, которые используются в хуке языка getattribute (вы можете жить и без него), но с необходимыми функциями виртуальной машины, такими как оптимизация хвостовой рекурсии, может быть трудно справиться. Вам все равно, если исходная программа не использует хвостовую рекурсию, и даже если на целевом языке нет хвостовой рекурсии, вы можете эмулировать ее с помощью гринлетов / цикла событий.

Для целевого и исходного языков ищите:

  • Большие и конкретные идеи
  • Крошечные и общие идеи

Из этого выйдет:

  • Вещи, которые легко перевести
  • Вещи, которые сложно перевести

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

Также есть вопрос о stdlib или любой другой библиотеке, но нет четкого ответа, это зависит от ваших целей.

Идиоматический код или читаемый сгенерированный код также имеют решения ...

Ориентация на такую ​​платформу, как PHP, намного проще, чем на браузеры, поскольку вы можете обеспечить C-реализацию медленного и / или критического пути.

Учитывая, что ваш первый проект - это перевод Python на PHP, по крайней мере, для подмножества PHP3, о котором я знаю, настройка veloce.py - ваш лучший выбор. Если вы можете реализовать veloce.py для PHP, то, вероятно, вы сможете запустить соответствующий режим ... Также, если вы можете перевести PHP в подмножество PHP, которое вы можете сгенерировать с помощью php_veloce.py, это означает, что вы можете перевести PHP в подмножество Python, которое может использовать veloce.py, что означает, что вы можете перевести PHP в Javascript. Просто говорю...

Вы также можете взглянуть на эти библиотеки:

Также вас может заинтересовать это сообщение в блоге (и комментарии): https://www.rfk.id.au/blog/entry/pypy-js-poc-jit/.

person amirouche    schedule 03.04.2014
comment
Единственное, что меня по-прежнему волнует в переводе с компьютерного языка на компьютерный язык один-к-одному, описано в stackoverflow.com/questions/22621164/ - person amirouche; 04.04.2014
comment
Второй ответ о типах данных. В Pythonium я даже не планировал поддерживать правильный тип integer и float в совместимом режиме без asm.js. - person amirouche; 04.04.2014
comment
Итак, если я дам вам пакет Python из 100K SLOC, и вы запустите его через свой переводчик, получу ли я работающую программу? Сколько потребуется ручной работы после перевода, чтобы это исправить? Вы сказали, что с учетом уже существующего хорошего парсера для Python, который строит AST, я могу построить частичный переводчик за 6 месяцев. Никто не удивлен. Шесть месяцев по стандартам большинства людей непросто (цитирую другой ваш комментарий). Решение оставшихся проблем потребует дополнительных усилий. В моем ответе говорилось, что делать это в основном непросто, а делать это в целом сложно. - person Ira Baxter; 05.04.2014
comment
... этот последний пункт в ответ на первоначальное желание OP: в идеале я мог бы добавить другие языки с (относительной) легкостью., что конкретно касается моего ответа. - person Ira Baxter; 05.04.2014
comment
Я прошу не соглашаться, особенно когда вы знаете, что делаете, это легко, а то, что будет дальше, не сложно, это просто вопрос выполнения работы. Я не уверен, где вы имеете дело с чем-то связанным с этим вопросом. Вы говорите в 4 или 5 абзацах, что это делает ваша компания, и это сложно. Но в противном случае вы распространяете FUD по этому вопросу, будучи добрыми не по теме, как будто вы находитесь в stackoverflow.com/questions/22621164/. За 6 месяцев на полную ставку написал бы полноценного переводчика. - person amirouche; 06.04.2014
comment
@IraBaxter anwser не отвечает на вопрос. - person amirouche; 06.04.2014

Вы можете взглянуть на компилятор Vala, который переводит Vala (C # - как язык) в C.

person ptomato    schedule 18.08.2010
comment
Целью разработки Vala было перевести ее на C и упростить разработку с использованием библиотек gnome. - person amirouche; 04.04.2014