在编程语言中实现模板的最佳方法是什么?

时间:2009-04-30 21:28:41

标签: templates language-design

我正在设计一个高级,面向对象,垃圾收集的编程语言,我遇到了如何进行模板的问题。我计划创建一个类似于.NET或JVM的VM类型系统(但它将使用LLVM)。问题是我希望拥有强大的,类似C ++的模板,但是使用动态链接(因此我可以替换模板库而无需重新编译使用它的所有内容)。我希望能够在没有模板定义的情况下编译源文件。应尽量减少JIT时代的代码生成。

以下是我正在考虑的选项:

  • 具有静态链接到每个编译单元的模板库的概念。模板库本质上就像一个AST,在实例化模板时要填充空白。这样做的问题是,如果使用不同版本的模板库编译两个文件,它们可能不兼容,或者如果模板库有错误,则必须重新编译所有内容。这就是C ++的用法。
  • 拥有在JIT时间链接的模板库。这解决了大多数问题,但要求IR基本上是AST。我希望IR更低一些。这需要更多的JIT工作。
  • 只有类型作为参数,具有类似C#的泛型。这是非常有限的,但允许简单的代码生成和动态链接。

还有其他好的方法我没想到吗?我倾向于第一种选择,但我并不喜欢任何选择。你认为最好的选择是什么?

4 个答案:

答案 0 :(得分:1)

我想这取决于你想要的专业化程度,即模板编译器的强大程度。

如果你看一下c ++,编译器可以做各种奇特的事情(比如通过递归生成子类,可能会计算分形继承图以及计算动态Pi的数量)。

如果你想要那种力量,你可能需要一个强大的高级JIT。 FWIW,我觉得这很酷。 (只需在运行时中包含完整的编译器。)

答案 1 :(得分:0)

取决于语言的其余部分...如果你有运算符重载,值类型等,那么你真的很复杂(并且可能错过了很好的优化机会)不通过C ++路由:代码使用模板也必须表示为一个AST直到JIT时间,以允许最大化的专业化。

由于C ++模板本质上是一种宏形式,它们允许在生成代码之前减少复制产生的大部分膨胀。

模板类型(至少在C ++中)往往是最核心的类型,它们是所有其他代码的基础,因此,如果它们发生变化,假设其他代码仍然与之兼容,那么除了它之外的所有代码都不会是真的最小的变化。

答案 2 :(得分:0)

你想要达到的目标几乎是不可能的。您必须为模板定义和使用这些模板的代码留下几乎所有语言的高级表示,并从几乎略微处理的源代码级别执行JIT编译。如果您对此感到满意 - 您必须保持编译器的其余部分非常简单,并且您将无法使用任何重量级LLVM优化。没有其他方法,模板元编程依赖于高级信息的可用性。

答案 3 :(得分:0)

想想这些模板有多强大。你必须记住,使用Just In Time编译的语言意味着必须在加载时和运行时完成许多繁重的工作。因此,制作模板的功能越强,从中获得的性能就越低。


如果您真的要去那条路,那么您也可以在运行时将编译器包含在Macke suggested中。事实上,有很多语言可以做到这一点。

通过这样做,您将使语言的实现成为“解释”或部分“解释”的语言。在这些术语中,模板只是匹配替换eval的奇特装扮,并且有任何问题,模板通常在动态语言中工作。请记住,最后它将是Power vs Performance。


注意:面对这样的决定时,可能有必要退一步。确定用例并确定其优先级,从设计中分离如何实现,这样您就可以迭代设计,而不会使实现成为瘫痪的原因,但仍然需要考虑它。

每次迭代都会扩展设计以涵盖更多用例,同时决定什么是最佳设计。当您达到您喜欢的设计时,您可以迭代,然后您也可以迭代实现。这种方法允许您首先涵盖更重要的案例。

是的,我建议使用迭代增量方法。我这样做是因为这个问题是关于语言的设计,但它似乎非常关注实现。有必要保持这些想法的基础,否则你将陷入极端的一个极端(过于强大的怜悯性能或根本没有模板用于高性能解决方案)。