Які типи шаблонів я можу застосувати до коду, щоб полегшити переклад на іншу мову програмування? [зачинено]


95

Я збираюся зробити допоміжний проект, метою якого є переклад коду з однієї мови програмування на іншу. Мовами, з яких я починаю, є PHP та Python (з Python до PHP слід легше починати), але в ідеалі я міг би додавати інші мови з (відносною) легкістю. План:

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

  • Я також розглядаю МОК та ін'єкцію залежностей, оскільки вони можуть полегшити процес перекладу та менш схильні до помилок.

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

  • Відтепер я можу будувати AST, таблиці символів та керувати потоком.

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

Перш ніж запитати "Який біс у цьому сенс?" Відповідь ... Це буде цікавий досвід навчання. Якщо у вас є уявлення про те, як зробити це менш страшним, повідомте мене про це.


Редагувати:

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


6
Ви розглядали такі системи, як .NET CLR або Perl6's Parrot? Вони компілюють набір мов до проміжного подання, яким може керувати загальний перекладач. Якщо ви можете повернутися з проміжного представництва до мови, у вас є перекладач.
Бореалід

1
@Borealid AFAIK в .NET КСС є (відносно) легко зібрати в , але удача отримувати читається код назад від цього. Дивлячись на Папугу зараз.
NullUserException

Є подібні проекти для інших мов; Я не впевнений, наскільки багаті їх автори. І я насправді тут дуже стримуюсь, потребуючи фреймворку та дотримуючись суворих правил кодування.
NullUserException

2
Я не можу додати якихось конкретних знань, але чи розглядали ви піжаму ( pyjs.org ), зокрема translator.py? Це компілятор python для javascript.
Стефан

3
Re EDIT: Якщо у вас є контроль над кодом, який буде перекладено, найочевидніше, що потрібно зробити, це уникати конструкцій, які важко перекласти! Наприклад, C набагато легше перекласти на Java, якщо немає арифметики покажчика. Що стосується Python, я б, напевно, тримався подалі від закриття. Інше, що ви можете зробити, це написати вихідний код таким чином, щоб складніші частини для перекладу завжди кодувались ідіоматично, що полегшує їх розпізнавання та розгляд особливих випадків.
Ira Baxter

Відповіді:


122

Я створюю інструменти (DMS Software Reengineering Toolkit) для маніпуляцій загальними програмами (з особливим випадком перекладу мови), що підтримується потужною командою комп’ютерних вчених. DMS забезпечує загальний синтаксичний аналіз, побудову AST, таблиці символів, управління та аналіз потоків даних, застосування правил перекладу, регенерацію вихідного тексту з коментарями тощо, все параметризується явними визначеннями комп'ютерних мов.

Кількість механізмів, необхідних для того, щоб зробити це добре , величезна (особливо, якщо ви хочете зробити це для багатьох мов загальним чином), і тоді вам потрібні надійні синтаксичні аналізатори для мов з ненадійними визначеннями (PHP є прекрасним прикладом цього ).

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

Люди часто намагаються створити якусь узагальнену техніку, починаючи з якоїсь технології, з якою вони знайомі, яка виконує певну частину роботи. (Чудовим прикладом є Python AST). Хороша новина полягає в тому, що частина роботи виконана. Погана новина полягає в тому, що в машині вбудовано мільйон припущень, більшість з яких ви не відкриєте, доки не спробуєте боротися за щось інше. У цей момент ви дізнаєтесь, що техніка підключена до того, що вона робила спочатку, і дійсно, справді буде протистояти вашій спробі зробити щось інше. (Я підозрюю, що спроба отримати Python AST для моделювання PHP буде дуже веселою).

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

Багато людей також помиляються, вважаючи, що якщо вони можуть проаналізувати (і, можливо, отримати AST), вони на шляху до чогось складного. Одним із важких уроків є те, що вам потрібні таблиці символів та аналіз потоків, щоб зробити хороший аналіз або перетворення програм. АСТ необхідні, але недостатні. Це є причиною того, що книга упорядника Aho & Ullman не зупиняється на розділі 2. (ОП має це право тим, що він планує побудувати додатковий механізм за межами AST). Докладніше про цю тему див. У розділі Життя після розбору .

Зауваження щодо "Мені не потрібен ідеальний переклад" викликає клопоти. Слабкі перекладачі роблять це перетворення "легких" 80% коду, залишаючи важкі 20% робити вручну. Якщо програма, яку ви збираєтеся конвертувати, досить мала, і ви маєте намір конвертувати її лише один раз, тоді ці 20% - це нормально. Якщо ви хочете конвертувати багато програм (або навіть той самий із незначними змінами з часом), це неприємно. Якщо ви намагаєтесь перетворити 100K SLOC, тоді 20% - це 20 000 оригінальних рядків коду, які важко перекласти, зрозуміти та змінити в контексті ще 80 000 рядків перекладеної програми, яку ви вже не розумієте. Це вимагає величезних зусиль. На рівні мільйона ліній це на практиці просто неможливо.складніше, і вони зазвичай це болісно виявляють при великих затримках, великих витратах і часто відвертих збоях.)

Для перекладу великомасштабних систем вам потрібно шукати високі коефіцієнти конверсії у дев'яностих роках, або, ймовірно, ви не можете виконати ручну частину перекладацької діяльності.

Іншим ключовим фактором є розмір коду для перекладу. Щоб створити робочий, надійний перекладач, навіть маючи хороші інструменти, потрібно багато енергії. Незважаючи на те, що створювати перекладач здається сексуальним і крутим, а не просто виконувати ручне перетворення, для невеликих кодових баз (наприклад, до нашого досвіду приблизно до 100 000 SLOC) економіка просто не виправдовує цього. Ця відповідь нікому не подобається, але якщо вам дійсно доведеться перекласти лише 10K SLOC коду, вам, мабуть, краще просто кусати кулю і робити це. І так, це боляче.

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


8
Ви коли-небудь замислювалися над тим, щоб повернути своє "болісно побудоване" визначення PHP назад PHP-спільноті в цілому, або надто тісно пов'язане з вашим власним потоком доходу, щоб зробити це здійсненним?
TML

53
Мене попросили зробити все, що ми робимо, «відкритим кодом» багатьох людей, які не хотіли робити внесок у потік доходу і не мали сил виконувати цю роботу та відкривати її самі. Якщо ви вносите лише невелику частину у дуже великий проект та / або у вас є інше джерело доходу, "відкрите джерело" здається чудовим. Якщо ви виконали всю роботу самостійно, і це єдине джерело вашого доходу, це набагато менш привабливо. [Я не хочу вступати в дискусію щодо відносних достоїнств філософії "вільного програмного забезпечення", тому я не буду брати участь у подальших коментарях у цьому напрямку]
Айра Бакстер,

9
Я погоджуюся з тим, що ви сказали тут, саме тому я сформулював питання так само, як і зробив. Я думаю, ми маємо зрозуміти з цієї реакції, що ви відчуваєте, що вона занадто тісно пов’язана з вашими доходами, і в цьому немає абсолютно нічого поганого - я просто вважав, що варто запитати.
TML

3
@IraBaxter Ви просто говорите загальні ідіоми щодо практик, пов'язаних з комп'ютером, які можна застосувати до багатьох інших практик. Єдине, що цікавить усе, що ви написали, - це посилання на semanticdesigns.com (а це ваша компанія)
amirouche

1
У своїх відповідях ви часто надаєте посилання на сторінки, пов’язані з Clang. Це лише доводить, що хтось інший може створити веб-сторінку. Більшість з нас припускають, що добре написана веб-сторінка означає, що за нами стоїть серйозна, справжня робота, а не просто якась шахрайська спроба обдурити читача, як ви, мабуть, натякаєте у своїй відповіді. Ви насправді вважаєте, що веб-сторінка є шахрайською? Сторінка містить довідкову інформацію до "відповідного" джерела; вона анономізована, тому що контракт на роботу вимагав цього. Що я не можу допомогти.
Айра Бакстер,

13

Моя відповідь стосуватиметься конкретного завдання розбору 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 схожі, ніяких механізмів емуляції там не потрібно.


Віеелл. 2to3це просто АСТ до АСТ. Він не підтримує робити щось, що виходить за рамки можливостей astмодуля. Зверніть увагу, що всі переклади переходять від синтаксису, що підтримується процесом python хоста, до синтаксису, що підтримується процесом python хоста. Немає перекладача, який додає, скажімо, анотації функцій, оскільки 2.6 не підтримує цього.
habnabit

... і питання OP може бути короткостроковим, як перейти з Python 2.6 AST до ... чогось у PHP. Модуль ast, швидше за все, не захоче добре представляти синтаксис PHP, тому навіть не є ast для ast.
Айра Бакстер,

2
@Aaron: 2to3можна розглядати як приклад використання AST, створеного з ast.
Елі Бендерський,

AFAIK, 2to3, можливо, простіший переклад, ніж Python на PHP (зрештою, його Python на Python, так)? І навіть це не працює особливо добре. Зверніть увагу на велику кількість Python 2.6, яку ще не було просунуто через 2to3 ... тому що, мабуть, є купа виправлення рук перекладу публікацій, які ще потрібно зробити. Якби на 100% був автоматизований, Python 2.6 був би мертвим.
Айра Бакстер,

5

Написання перекладача не є неможливим, особливо враховуючи, що стажер Джоела робив це протягом літа.

Якщо ви хочете зробити одну мову, це легко. Якщо ви хочете зробити більше, це трохи складніше, але не надто багато. Найскладніше в тому, що, хоча будь-яка повна мова Тьюрінга може робити те, що робить інша мова Тьюрінга, вбудовані типи даних можуть феноменально змінити те, що робить мова.

Наприклад:

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.


«Ви коли-небудь писали токенізатор / парсер на основі граматики мови?» Я робив це за допомогою JavaCC.
NullUserException

2
Стажер Джоела виконував часткову роботу протягом літа. Його вихідна мова була підмножиною існуючої мови, і, мабуть, цю підмножину можна було дещо скорегувати. Це значно полегшує роботу. Подібним чином, NullPointerException може почати з більш простих частин Python, можливо, проходячи через складніші речі для ручного перетворення (як зазначено у запитаннях).
Девід Торнлі,

@NullUserException: Ви матимете певний вплив, але в основному ви будете робити повторну реалізацію JavaCC, лише замість Java як мови виводу ви будете робити <вставити сюди langauge>. @David, цілком так. Навіть Thistle потребує допомоги у деяких мовних конструкціях. Якби я був оператором, я б спершу вибрав функціонал, а потім оптимізував, інакше я застряг би назавжди, намагаючись змусити C ++ робити нарізання рядків (з кроками): p
Уейн Вернер,

@WayneWerner Для запису, такі мови, як C #, взагалі не потребують нових рядків. (Принаймні, не після того, як ви видалили однорядкові коментарі.) Тож ви можете написати будь-яку програму на C # в один рядок. Але, звичайно, я розумію, до чого ви ставитесь.
leviathanbadger

@ aboveyou00: Я не думаю, що це правильно. Якщо ви забороните умови попереднього процесора, ви можете мати рацію.
Ira Baxter

3

Є кілька відповідей, які говорять вам не турбуватися. Ну, наскільки це корисно? Ви хочете вчитися? Ви можете навчитися. Це компіляція. Так трапляється, що цільовою мовою є не машинний код, а інша мова високого рівня. Це робиться постійно.

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

Вам пощастило з PHP та Python, оскільки багато в чому вони однакові як одна з одною, але з різним синтаксисом. Важкою частиною є подолання семантичних відмінностей між граматичними формами та структурами даних. Наприклад, Python має списки та словники, тоді як PHP має лише допоміжні масиви.

Підхід "учня" полягає в тому, щоб створити щось, що працює нормально для обмеженого підмножини мови (наприклад, лише оператори друку, проста математика та присвоєння змінних), а потім поступово усувати обмеження. Це в основному те, що робили "великі" хлопці на місцях.

О, і оскільки у вас немає статичних типів у Python, можливо, найкраще писати та покладатися на функції PHP, такі як "python_add", яка додає числа, рядки або об'єкти відповідно до того, як це робить Python.

Очевидно, що це може стати набагато більшим, якщо ви дозволите.


3
Власне, я не сказав "не турбуйся". Я сказав: "Перекладати мови загальними способами дуже важко". Якщо ОП піде своїм початковим шляхом використання дерев Python для спроби генерувати PHP, він багато чому навчиться, і я все за досвід навчання; Я теж там почав. Він не зможе легко додавати нові мови.
Айра Бакстер,

@IraBaxter Я не можу підтримати ваше твердження, робити Python-> PHP та PHP-> Javascript було б якось просто. пор. остання частина stackoverflow.com/a/22850139/140837 в середині відповіді, я також маю справу з вашою "аргументацією"
amirouche

2

Я підтримаю точку зору @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 clojure.

  • Я пробував із 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, і він використовує успадкування прототипів.

Насправді мені ніколи не вдається запустити піжаму # fail і ніколи більше не намагався прочитати код # fail. Але, на мою думку, піжама робила трансляцію API-> API (або фреймворк в фреймворк), а не переклад Python в JavaScript. Структура JavaScript використовує дані, які вже є на сторінці, або дані із сервера. Код Python - це лише "сантехніка". Після цього я виявив, що піжама насправді була справжнім перекладачем python-> js.

Тим не менш, я думаю, що можна зробити переклад API-> API (або фреймворк-> фреймворк), і це в основному те, що я роблю в Pythonium, але на нижчому рівні. Ймовірно, піжами використовують той самий алгоритм, що і 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, є:

  • функція з повними семантичними параметрами як у визначенні, так і у виклику. Це та частина, якою я пишаюся найбільше.
  • while / if / elif / else
  • Типи Python були перетворені в типи JavaScript (жодного типу типів python не існує)
  • бо міг перебирати лише масиви Javascript (для масиву in 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
  • успадкування одного класу + mixin через 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 пор. 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. Замість того, щоб генерувати блок відстеження, яка змінна створена в даному блоці, і вставляти його поверх згенерованого функціонального блоку, я просто шукаю присвоєння змінної змінної, коли я ввожу блок перед тим, як фактично відвідати дочірній вузол, щоб сформувати відповідний код.
  • 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 людських років у контексті підприємства ...

Коли хтось каже, що щось важке або частіше неможливе, я відповідаю, що "потрібен час, щоб знайти рішення неможливої ​​проблеми", інакше кажуть, що нічого неможливого є, крім випадків, коли це доведено неможливим у цьому випадку математичним підтвердженням ...

Якщо це не доведено неможливим, це залишає простір для фантазії:

  • знайти доказ, що доводить, що це неможливо

і

  • Якщо це неможливо, може виникнути "неповноцінна" проблема, яка може мати рішення.

або

  • якщо це неможливо, пошук рішення

Це не просто оптимістичне мислення. Коли я запустив Python-> Javascript, усі говорили, що це неможливо. PyPy неможливо. Метакласи занадто важкі. і т.д. ... Я думаю, що єдиною революцією, яка приводить PyPy до паперу Scheme-> C (якому 25 років), є деяке автоматичне генерування JIT (на мої підказки, написані в інтерпретаторі RPython).

Більшість людей, які кажуть, що річ "важка" або "неможлива", не вказують причин. C ++ важко проаналізувати? Я це знаю, все ж вони є (безкоштовними) парсерами C ++. Зло в деталях? Я це знаю. Сказати, що це неможливо поодинці, не корисно, це навіть гірше, ніж "не корисно", це знеохочує, і деякі люди хочуть знеохотити інших. Я чув про це запитання за допомогою /programming/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. Навіть якщо ми вже знаємо, що вони обидва тверді, цілі ...

Фреймворк-> Фреймворк, який я краще візуалізую як API-> Переклад API, все-таки може бути тим, що ви можете мати на увазі як спосіб поліпшити згенерований код. Наприклад: Пролог як дуже конкретний синтаксис, але все одно Ви можете робити Пролог, як обчислення, описуючи той самий графік в Python ... Якби я мав реалізувати перекладач Пролог на Python, я б не реалізував уніфікацію в Python, а в бібліотеці C і прийшов з "синтаксисом Python", який дуже читається для Pythonist. Врешті-решт, синтаксис - це лише «живопис», якому ми надаємо значення (саме тому я розпочав схему). Зло в деталях мови, і я не кажу про синтаксис. Поняття, які використовуються в мові гетатрибутіхук (ви можете жити без нього), але з такими необхідними функціями віртуальної машини, як оптимізація хвостової рекурсії, може бути важко впоратися. Вам байдуже, чи в початковій програмі не використовується рекурсія хвоста, і навіть якщо у цільовій мові немає рекурсії хвоста, ви можете емулювати її, використовуючи цикл greenlets / event.

Для цільової та вихідної мов шукайте:

  • Великі та конкретні ідеї
  • Крихітні спільні ідеї

З цього вийде:

  • Речі, які легко перекласти
  • Речі, які важко перекласти

Ви також, мабуть, зможете знати, що буде перекладено на швидкий і повільний код.

Існує також питання про 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/


Єдине , що залишається хвилюючим для мене про один-до-одній мові програмування на комп'ютерну мову перекладу описані в stackoverflow.com/questions/22621164 / ...
amirouche

Я повторюю іншу відповідь про типи даних. У Pythonium я навіть не планував підтримувати правильний цілочисельний & плаваючий тип у сумісному режимі без asm.js.
amirouche

Добре, отже, якщо я передаю вам пакет Python розміром 100 000 SLOC, а ви запустите його через свого "перекладача", чи отримаю я робочу програму? Скільки ручної роботи після перекладу потрібно, щоб це виправити? Ви сказали тут, "з огляду на вже наявний хороший синтаксичний аналізатор для Python, який створює AST, я можу створити частковий перекладач за 6 місяців". Ніхто не дивується. 6 місяців не є за мірками більшості людей "начебто легким" (цитуючи інший ваш коментар). Вирішення решти проблем вимагатиме більше зусиль. У моїй відповіді було сказано: в основному "зробити це непросто", а "зробити це загалом важко".
Айра Бакстер,

... той останній пункт у відповідь на початкове бажання OP: "в ідеалі я міг би додати інші мови з (відносною) легкістю.", який моя відповідь стосується конкретно.
Айра Бакстер,

Я благаю не погодитись, особливо коли ти знаєш, що робиш, це легко, а те, що далі, не важко, це просто питання того, щоб щось зробити. Я не впевнений, де ви маєте справу з чимось конкретним для цього питання. Ви говорите в абзаці 4 або 5, що ваша компанія це робить, і це важко. Але в іншому випадку ви поширюєте FUD про цю тему, хоч і не любите тему, як у stackoverflow.com/questions/22621164/… . За повний робочий день 6 місяців я б написав повного перекладача.
amirouche

0

Ви можете поглянути на компілятор Vala , який перекладає Vala (мову, подібну до C #) на C.


Метою дизайну Vala було перекласти на C і спростити розробку бібліотек gnome.
amirouche
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.