I guess it depends on the amount of specialization you want, i.e. how powerful the compiler of templates has to be.
If you look at c++, the compiler can do all sorts of fancy stuff (like generate subclasses via recursion, probably compute a fractal inheritance graph as well as computing the numbers of Pi on the fly).
If you want that power, you probably need a powerful high-level JIT. FWIW, I think that would be cool. (Just include the full compiler in the runtime.)
有点取决于语言的其余部分...如果您有运算符重载、值类型等,那么如果不走 C++ 路线,您确实会使事情变得复杂(并且可能会错过很好的优化机会):使用模板的代码还必须表示为 JIT 时间以内的 AST,以允许最大程度的专业化。
由于 C++ 模板本质上是宏的一种形式,因此它们允许在生成代码之前减少由重复产生的大部分膨胀。
模板类型(至少在 C++ 中)往往是所有其他代码的最核心类型,因此,如果它们发生更改,则假设其他代码仍然与其兼容,但对于除了最小的更改之外的所有更改都不会成立。
Depends a bit on the rest of the language... if you have operator overloading, value types etc, then you are really complicating matters (and possibly missing out on great optimisation opportunities) by not going the C++ route: the code using the template would also have to be represented as an AST up to JIT time to allow maximum specialization.
Since C++ templates are essentially a form of macros, they allow much of all the bloat produced by duplication to be reduced before you get generate code.
Template types (at least in C++) tend to be the most core types that underly all other code, as such, if they change, assuming other code will still be compatible with it is not going to be true for all but the smallest changes.
What you're trying to achieve is nearly impossible. You have to leave pretty much all of the high level representation of your language for both the templates definitions and the code using those templates, and perform your JIT compilation from almost the level of slightly processed source code. If you're ok with that - you'd have to keep the rest of your compiler really trivial, and you won't be able to use any of the heavyweight LLVM optimisations. There are no other ways around, template metaprogramming relies on the availability of the high level information.
Think about how powerful are these templates going to be. You must remember that having a language that is compiled Just In Time, means that a lot of the heavy lifting will have to be done at load time and at run time. So, the more powerful you make your templates the less performance you will get from them.
If you are really going to that path, you may also include the compiler in the run time as Macke suggested. In fact there are plenty of languages that do this.
By doing this you are making your implementation of the language an "interpreted" or partially "interpreted" one. In those terms a template is just a fancy dress for match-replace-eval, and there is anything wrong with that, templates often work like that in dynamic languages. Just remember that at the end it will be Power vs Performance.
Note: when facing this kind of decisions it may be worth to step back a little. Identify the use cases and prioritize them, separate how to implement from the design so you can iterate the design without having the implementation be a cause of paralysis, yet still having it into consideration.
Each iteration you extend the design to cover more use cases while deciding what will be the best design. When you reach a design you like you can iterate then you can iterate on the implementation too. This methodology allows you to cover the more important cases first.
Yes, I'm suggesting an iterative incremental methodology. And I do this because this question is about the design of a language yet it seems much concerned about the implementation. It is necessary to keep the ideas grounded or you will end up in one of the extremes (too much powerful with pity performance or no templates at all for a high performance solution).
发布评论
评论(4)
我想这取决于您想要的专业化程度,即模板编译器必须有多强大。
如果你看看 C++,编译器可以做各种奇特的事情(比如通过递归生成子类,可能计算分形继承图以及动态计算 Pi 的数量)。
如果您想要这种能力,您可能需要一个强大的高级 JIT。 FWIW,我认为那会很酷。 (只需在运行时包含完整的编译器即可。)
I guess it depends on the amount of specialization you want, i.e. how powerful the compiler of templates has to be.
If you look at c++, the compiler can do all sorts of fancy stuff (like generate subclasses via recursion, probably compute a fractal inheritance graph as well as computing the numbers of Pi on the fly).
If you want that power, you probably need a powerful high-level JIT. FWIW, I think that would be cool. (Just include the full compiler in the runtime.)
有点取决于语言的其余部分...如果您有运算符重载、值类型等,那么如果不走 C++ 路线,您确实会使事情变得复杂(并且可能会错过很好的优化机会):使用模板的代码还必须表示为 JIT 时间以内的 AST,以允许最大程度的专业化。
由于 C++ 模板本质上是宏的一种形式,因此它们允许在生成代码之前减少由重复产生的大部分膨胀。
模板类型(至少在 C++ 中)往往是所有其他代码的最核心类型,因此,如果它们发生更改,则假设其他代码仍然与其兼容,但对于除了最小的更改之外的所有更改都不会成立。
Depends a bit on the rest of the language... if you have operator overloading, value types etc, then you are really complicating matters (and possibly missing out on great optimisation opportunities) by not going the C++ route: the code using the template would also have to be represented as an AST up to JIT time to allow maximum specialization.
Since C++ templates are essentially a form of macros, they allow much of all the bloat produced by duplication to be reduced before you get generate code.
Template types (at least in C++) tend to be the most core types that underly all other code, as such, if they change, assuming other code will still be compatible with it is not going to be true for all but the smallest changes.
你想要实现的目标几乎是不可能的。 您必须为模板定义和使用这些模板的代码保留几乎所有语言的高级表示,并从几乎经过轻微处理的源代码级别执行 JIT 编译。 如果您对此表示同意 - 您必须保持编译器的其余部分非常简单,并且您将无法使用任何重量级 LLVM 优化。 没有其他方法,模板元编程依赖于高级信息的可用性。
What you're trying to achieve is nearly impossible. You have to leave pretty much all of the high level representation of your language for both the templates definitions and the code using those templates, and perform your JIT compilation from almost the level of slightly processed source code. If you're ok with that - you'd have to keep the rest of your compiler really trivial, and you won't be able to use any of the heavyweight LLVM optimisations. There are no other ways around, template metaprogramming relies on the availability of the high level information.
想想这些模板会有多强大。 您必须记住,拥有一种即时编译的语言意味着必须在加载时和运行时完成大量繁重的工作。 因此,您的模板越强大,您从它们中获得的性能就越差。
如果您确实要走这条路,您还可以按照 Macke 建议 在运行时中包含编译器。 事实上,有很多语言可以做到这一点。
通过这样做,您可以使该语言的实现成为“解释的”或部分“解释的”语言。 用这些术语来说,模板只是匹配-替换-评估的化装,这有什么问题,模板通常像动态语言中那样工作。 请记住,最后将是功率与性能。
注意:当面临此类决定时,可能值得退一步。 确定用例并确定它们的优先级,将如何实现与设计分开,这样您就可以迭代设计,而不会导致实现瘫痪,但仍将其考虑在内。
每次迭代,您都会扩展设计以覆盖更多用例,同时决定什么是最佳设计。 当您达到您喜欢的设计时,您可以迭代,然后您也可以迭代实现。 这种方法允许您首先涵盖更重要的案例。
是的,我建议采用迭代增量方法。 我这样做是因为这个问题是关于一种语言的设计,但它似乎非常关心实现。 有必要让想法扎根,否则您将最终陷入极端之一(功能过于强大而性能不佳或根本没有高性能解决方案的模板)。
Think about how powerful are these templates going to be. You must remember that having a language that is compiled Just In Time, means that a lot of the heavy lifting will have to be done at load time and at run time. So, the more powerful you make your templates the less performance you will get from them.
If you are really going to that path, you may also include the compiler in the run time as Macke suggested. In fact there are plenty of languages that do this.
By doing this you are making your implementation of the language an "interpreted" or partially "interpreted" one. In those terms a template is just a fancy dress for match-replace-eval, and there is anything wrong with that, templates often work like that in dynamic languages. Just remember that at the end it will be Power vs Performance.
Note: when facing this kind of decisions it may be worth to step back a little. Identify the use cases and prioritize them, separate how to implement from the design so you can iterate the design without having the implementation be a cause of paralysis, yet still having it into consideration.
Each iteration you extend the design to cover more use cases while deciding what will be the best design. When you reach a design you like you can iterate then you can iterate on the implementation too. This methodology allows you to cover the more important cases first.
Yes, I'm suggesting an iterative incremental methodology. And I do this because this question is about the design of a language yet it seems much concerned about the implementation. It is necessary to keep the ideas grounded or you will end up in one of the extremes (too much powerful with pity performance or no templates at all for a high performance solution).