【问题标题】:Meta-programming: write in one language X, cross-compile in multiple languages like C#, PHP, Java, C元编程:用一种语言 X 编写,用多种语言交叉编译,如 C#、PHP、Java、C
【发布时间】:2011-07-16 20:11:42
【问题描述】:

在我多年来完成的所有项目中,我从未遇到过这样的要求,尽管在纸面上看起来很容易:为许多知名 CMS 编写插件。

显然,每个插件系统(或扩展系统)都是不同的,这需要通过适配器模式进行特定的桥接代码。但是核心应该写一次。我不希望 WordPress 用户使用 PHP-Java 桥接器,也不希望 DotNetNuke 用户使用 .NET-Native 桥接器(尽管这更容易构思)。

在我看来,核心应该可以在涵盖大多数 CMS 系统的三个主要领域中编译:

  • 本机、中间语言可以是 C 或 C++。 Target 可用作 PHP 扩展。
  • 基于 .NET 的语言的 MSIL/CIL
  • 基于 Java 的系统的 Java 字节码

C# 和 Java 可以很好地相互转换,但 C 和 C# 更难。最终,最好添加其他目标,以免强迫 WordPress 或 WikiMedia 用户在使用插件之前安装扩展。

我相信这也是其他人的想法。解决此类问题的常用方法是什么?我应该先定义一个 DSL 并使用 DMS 或类似方法进行转换吗?其他选择?

【问题讨论】:

  • 就针对多种语言而言,您可能正在寻找haxe.org/doc/intro(尽管尚不支持.NET 和JVM)
  • @mario:这似乎非常接近,非常有趣的语言!我会调查的。
  • 性能应该如何?可能一个 WS 解决方案可能是有序的或类似于 protobuf 的东西..
  • @mario 现在在 Haxe 中提供了对 C# 和 Java 的实验性支持。

标签: c# java php metaprogramming cross-compiling


【解决方案1】:

Haxe 是一种针对不同平台编译的元语言:

  • JavaScript
  • C++
  • C#
  • HashLink
  • Java
  • 卢阿
  • PHP
  • Python 3
  • NekoVM
  • 闪光
  • 动作脚本 3

【讨论】:

  • 功劳实际上应该归马里奥所有,马里奥之前曾提出过这样的评论;)。但 HaXe 的前提是有希望的。
  • 较早但独立 ;) 我正在写我的答案(并试图提供更多细节,然后只是一个链接,我也在研究 Java 和 C# 的进展是否有任何更新;其中没有,Java 原定于 1 月进行,但显然它滑落了)。
  • 我认为 Javascript 目标并不是那么无用。毕竟你可以在 PHP 和 Java 中嵌入和使用 Mozilla Spidermonkey / Rhino,可能还有 C#。
  • 或者你可以部署到 Node.js!
  • 深入研究 HaXe,它看起来更像是一种元编程工作,您仍然通过包装器使用原始库,例如从 flash 到 js 的转换效果不佳。我可以理解通用功能是有限的。也很遗憾 C# 和 Java 不被支持(目前)。
【解决方案2】:

我是负责DMS 的人,我认为这就是您在问题中所指的内容。

当尝试为多个目标域生成代码时,您必须以某种方式表达如何将规范映射到各个目标,无论您使用什么机器来执行此操作。

当每个目标的规范语言之间的语义差距不同时,就会出现难题。 (我遇到的最常见的多目标代码生成器倾向于生成相同类型的输出语言,这可以避免这个问题)。

一种方法是为每种输出语言编写单独的翻译器。这行得通,但要付出很多工作的代价。另一种方法是将规范语言翻译成中间语言/表示/领域,其中大部分翻译问题都已处理(例如,抽象过程语言),然后构建从中间领域到各个目标的翻译器.这往往容易得多。如果你有各种各样的目标,你可能会发现一些目标有一些共同点,但与其他目标没有共同点;在这种情况下,您需要的是多个中间表示,每组共性一个。

所有这些都与您实际表达这些翻译者的方式是正交的。您可以将它们编写为经典编译器;你会忙很长时间。您可以将它们编写为某种类型的语法导向翻译,来自捕获为图形的输入规范(“抓取图形并为每个节点吐出文本”),这似乎很常见(大多数“模型驱动”代码生成器似乎是这种类型),但除了以这种方式做事的洞察力之外,这样做并没有提供太多帮助。

我喜欢的方式,以及我构建 DMS(以及其他人构建 TXL 和 Stratego)的原因是使用源到源 transformations,因为这样你可以写下从输入语言到你的映射输出语言作为您可以检查的规则,这些规则基本上独立于底层转换机制;如果您实际上要编写大量规则,这将是一个巨大的胜利,这在您针对多种语言时尤其常见。与只吐出文本的代码生成器相比,转换引擎有另一个主要优势:您可以通过应用更多转换来处理翻译器一个阶段的输出。这意味着您可以优化代码,您可以构建更简单的规则(因为您可以使用一系列规则而不是一个代表叉积的计算,这总是很大而且很麻烦),并且您可以翻译多个级别的中间域。

现在,我按照我的方式构建 DMS 的另一个原因是强制明确分离每个“域”(输入规范、输出域、中间域)。您(和转换)永远不会对结构代表的内容感到困惑。 Stratgo 和 TXL 恕我直言,这里搞砸了;他们有时只操纵“一个”表示。如果您在两个符号 A 和 B 之间进行转换,则必须设置一个(恕我直言)“联合”域,其中包含 A 和 B。而且您必须以某种方式担心,如果在 A 和 B 中都有“+”句法,“+”是指 A 域中的“+”,还是 B 域中的“+”。如果你不知道,你怎么知道要应用哪些转换?

跨多个域进行精炼并使用转换来实现它的想法不是我的。早在 1980 年代,James Neighbors(“域分析”一词的来源)就为他的Draco 系统提出了它们。但我要站在巨人的肩膀上。 DMS 继承了 Neighbors 的领域概念和转型基础。不同之处在于,DMS 专为规模化、任意领域(DSL 以及当前编程语言;它为 C++、C#、Java、JavaScript 等预定义语言模块)而设计,并执行深度分析以支持转换。

【讨论】:

    【解决方案3】:

    我刚刚在一个项目中使用了一种元语言,该元语言可以编译成 Java 和 C。它使用类似 java 的语法并模拟 C 中的类功能(并且 C 部分非常依赖宏来“转换”部分代码)。

    这太可怕了。有了这堆维护,我们只是将它分成两个代码库并从那里开始。我知道最初的公司有一些很棒的人,但这太难了(尤其是因为他们都编译到嵌入式平台)。

    【讨论】:

      【解决方案4】:

      由于没有一种语言可以直接编译为所有目标,因此请不要忽视最低公分母。您可以使用 C 构建插件,然后为每个平台(PInvoke、JNI、PHP 扩展)包装结果。如果您不喜欢用 C 编写复杂插件的想法,请考虑使用一种小型、易于使用且可嵌入的脚本语言来完成繁重的工作。 Lua 似乎是合理的。您的最终结果将是一个 C 框架,它简单地将请求和响应委托给主机和脚本。

      Program Transformation 是相关的,尽管构建有效转换的努力意义重大。理论上,您可以从源代码转换为源代码并使用特定于平台的编译器。查看TXLStratego / XT 以了解所涉及的内容。

      【讨论】:

      • 我知道Stratego,但它需要我自己编写转换,这需要相当大的努力。我会看看TXL。 Lua 方法很有趣,但老实说,最后我宁愿没有字节码到本机的桥梁(它本质上需要包含 PHP 的目标,而不是我在问题中建议的本机库)。
      • @Abel - 哎呀,没有仔细阅读这个问题。鉴于您的完整要求,我猜您需要做很多工作。程序转换路线,无论使用 DMS、TXL 还是 Stratego/XT,都可能与针对 Haxe 或 Fantom 中的新后端一样糟糕。直接使用您的需求作为共享源来编写三个平台插件可能会更快、更容易、更正确。
      • @Abel:如果您想要自己的自定义翻译器,则必须以某种方式编写代码翻译。临时编码(例如,程序上)实际上比使用转换编码更难/更慢,更难维护。查看我的回复。
      【解决方案5】:

      fantom 编译为 java 和 .net clr
      我没用过,上个月才看到它出现在邮件列表中。

      【讨论】:

      • 是的,但是 Java 到/从 .NET 不是挑战,有多种工具和翻译器可以做到这一点。
      • +1 因为它还生成正确的 JavaScript。但不是我原来的问题的解决方案......
      猜你喜欢
      • 2015-02-15
      • 1970-01-01
      • 2011-03-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-11
      • 2010-11-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多