Метапрограммирование: писать на одном языке X, кросс-компиляция на нескольких языках, таких как C#, PHP, Java, C


Во всех проектах, которые я делал на протяжении многих лет, я никогда не сталкивался с подобным требованием, хотя на бумаге это кажется таким простым: напишите плагин для многих известных CMS.

Очевидно, что каждая система плагинов (или система расширений) отличается, и для этого требуется определенный код соединения через шаблон адаптера. Но ядро должно быть написано один раз. Я не ожидаю, что пользователи WordPress будут использовать мост PHP-Java, и я не ожидаю, что пользователи DotNetNuke будут использовать собственный мост .NET (хотя это легче понять).

На мой взгляд, ядро должно быть компилируемым в трех основных доменах, которые охватывают большинство систем CMS:

  • родным, промежуточным языком может быть C или C++. Цель может быть использована в качестве расширения PHP.
  • MSIL/CIL для языков, основанных на .NET
  • Байтовый код Java для систем на базе Java

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

Я уверен, что это тоже придумали другие. Каков общий способ решения таких проблем? Должен ли я сначала определить DSL и использовать DMS или аналогичный для преобразования? Другие варианты?

Author: Abel, 2011-03-16

5 answers

Haxe - это своего рода метаязык, который компилируется для разных платформ:

 15
Author: Jakub Hampl, 2017-12-15 20:59:48

Поскольку нет ни одного языка, который компилировался бы непосредственно для всех ваших целей, не упускайте из виду наименьший общий знаменатель. Вы можете создать свой плагин с использованием C, а затем обернуть результат для каждой платформы (PInvoke, JNI, расширение PHP). Если вам не нравится идея написания сложного плагина на C, подумайте о том, чтобы выполнить тяжелую работу, используя небольшой, простой в использовании и встраиваемый язык сценариев. Lua кажется разумным. Вашим конечным результатом будет скелет C, который просто делегирует запросы и ответы хосту и сценариям и от него.

Преобразование программы связано, хотя усилия по созданию эффективной трансформации значительны. Теоретически вы можете переходить от источника к источнику и использовать компилятор, зависящий от платформы. Взгляните на TXL и Stratego/XT, чтобы получить представление о том, что происходит.

 4
Author: Corbin March, 2011-03-16 19:15:18

Я парень, ответственный за DMS, на что, я думаю, вы ссылаетесь в своем вопросе.

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

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

Один из способов сделать это - написать отдельный переводчик для каждого языка вывода. Это работает, ценой большой работы. Другой способ сделать это - перевести язык спецификации на промежуточный язык/представление/домен, в котором было обработано большинство проблем перевода (например, абстрактный процедурный язык), а затем создать переводчики из промежуточного домена в индивидуальные цели. Это, как правило, намного проще. Если у вас есть реальное разнообразие целей, вы можете обнаружить, что некоторые цели имеют некоторые общие черты, но не с другими; в этом случае вам нужно несколько промежуточных представлений, по одному для каждого набора общих черт.

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

Способ, который мне нравится, и причина, по которой я построил DMS (и другие построили TXL и Stratego), заключается в использовании преобразований от источника к источнику , потому что таким образом вы можете записать отображение из вашего ввода язык для вашего языка вывода в виде правил, которые вы можете проверить, которые по существу не зависят от базового механизма преобразования; это большой выигрыш, если вы собираетесь написать, по сути, множество правил, что происходит особенно часто, когда вы ориентируетесь на несколько языков. Механизмы преобразования имеют еще одно важное преимущество перед генераторами кода, которые просто выплевывают текст: вы можете обрабатывать выходные данные одного этапа транслятора, применяя больше преобразований. Это означает, что вы можете оптимизируйте код, вы можете создавать более простые правила (потому что вы можете использовать цепочку правил вместо одного вычисления, представляющего перекрестный продукт, который всегда большой и сложный), и вы можете переводить через несколько уровней промежуточных доменов.

Теперь другая причина, по которой я построил DMS так, как я это сделал, заставляет четко разделять каждый из "доменов" (входные спецификации, выходные домены, промежуточные домены). Вы (и преобразования) НИКОГДА не путаетесь в том, что представляет собой структура. Стратго и TXL ИМХО облажался здесь; они манипулируют только "одним" представлением одновременно. Если вы переводите между двумя обозначениями A и B, вам необходимо настроить домен "объединение" (IMHO), в котором есть как A, так и B. И вам нужно как-то беспокоиться о том, есть ли у вас фрагмент синтаксиса "+" как в A, так и в B, означает ли "+" "+" в домене A или "+" в домене B. Если вы не можете сказать, как вы собираетесь узнать, какие преобразования применить к нему?

Идея совершенствования через несколько доменов и использование преобразований для этого, увы, не мои. Они были предложены Джеймсом Соседями ( источником термина "анализ предметной области") еще в 1980-х годах для его системы Draco. Но мне приходится стоять на плечах гигантов. DMS наследует концепции предметной области соседей и трансформационные основы. Разница в том, что DMS предназначена для масштабируемых произвольных доменов (DSL, а также для текущих языков программирования; в ней есть предопределенные языковые модули для C++, C#, Java, JavaScript,...) и проведение глубокого анализа для поддержки преобразований.

 3
Author: Ira Baxter, 2011-03-21 05:08:47

Fantom компилируется в java и .net clr
Я им не пользовался, просто видел, как он появился в списке рассылки в прошлом месяце.

 1
Author: crowne, 2011-03-16 18:48:40

Я только что работал над проектом, в котором использовался метаязык, скомпилированный как на Java, так и на C. Он использовал синтаксис, подобный Java, и имитировал функциональность класса на C (а часть C очень сильно зависела от макросов для "Преобразования" части кода).

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

 0
Author: Bill K, 2011-03-21 04:18:39