使用DLR可以开发静态类型语言吗?

6
我需要为.NET开发一个静态类型语言的编译器,考虑使用DLR来代替构建所有部分(Lexer/Parser、语法、语义、代码生成)。
对于这种情况,DLR是否适合?还是直接为.NET构建编译器,并避免所有动态调用更好?
编辑:我已经实现了该语言,而没有使用DLR提供的任何动态表达式,而是使用其他表达式。
在那之后,我可以说,将编译器定位到DLR而不是直接IL更好。生成的代码仍然非常清洁。
如果您想查看一些代码,请访问:tigerconverters.codeplex.com/

3
你将获得什么优势?你必须使用词法分析器和语法分析器,否则你将不知道程序试图做什么。你必须定义语法和语义,并且在执行过程中检查两者,即使你制作了一个源代码解释器——编译器早在此时就可以完成这项工作。而且很可能由于某些原因你需要为生成一些代码,尽管我从未创建过针对CLR或DLR的任何内容,所以无法评判这一点。 - user395760
我对这个非常感兴趣。我已经从头开始创建了几个玩具编译器,包括词法分析器->语法分析器->计划器->编译器。其中一个甚至构建了相当全面的类似C#的表达式树和庞大的方法解析。你在寻找什么样的语法? - Kieren Johnstone
@KierenJohnstone,我正在尝试实现的语言是Tiger,但是一个更简单的版本。 - Ariel
@Ariel:DLR存在的目的是为了实现动态语言。如果它旨在简化静态语言的编译器创建,那么它就不会被称为动态语言运行时。至少这是我所了解到的,因此这只是一条评论而不是答案。 - user395760
@delnan 但是,如果在语义分析阶段执行所有分析,则可以使用DLR编译的静态语言实现。问题在于DLR生成的代码与专门为静态语言生成的代码之间的比较。 - Ariel
显示剩余2条评论
3个回答

4
DLR在这种情况下可以为您提供最好的东西是表达式树。这些表达式树与LINQ引入的相同,但已扩展以支持生成完整程序。与IL相比,生成表达式树要简单得多,并且在生成树时获得了许多有用的检查,而不是在生成无效IL时难以诊断的失败。因此,您应该查看System.Linq.Expressions。要编译并保存到程序集,请使用LambdaExpression.CompileToMethod。
使用它们时唯一动态的是DynamicExpression节点,您可以完全避免它们。

3
DLR提供了很多基础设施,对于静态语言也非常有用。例如,它具有绑定方法调用和重载解析的默认实现。如果您的语言语义与默认行为匹配,则可以使用此功能。
但是,错误处理可能会有些棘手。例如,如果方法查找失败,则默认绑定器仍将返回有效表达式,但其代码将抛出异常...
DLR无法帮助您进行解析或词法分析。
还有其他选择。例如,您可能需要查看由MSR的Herman Vitter创建的Common Compiler Infrastructure项目。这实际上可能是更好的整体匹配。

DLR是建立在CLR之上的,因此在生成代码时提供了更高级别的抽象。CCI也是如此,但我认为DLR提供了更高级别的抽象,但代价是生成动态代码。我想知道的是:这真的值得吗??这将如何影响所生成程序的性能?与知道它是静态的生成代码相比。 - Ariel
此外,在代码生成之前可以进行语义分析,我们可以检查诸如方法M()是否属于类型T等内容,然后使用DLR生成代码。 - Ariel
DLR使用表达式树。任何动态表达式都将在需要时解析(这曾经发生在代码编译时,但现在也有解释器)。如果所有内容都是静态已知的,则可以生成静态表达式树并编译它们。无论如何,您都必须进行绑定。 DLR的优点是可以轻松构建REPL等操作。 - Jeffrey Sax

2
您需要实现自己的解析器来解析您自己的领域特定语言DSL。编译可以依赖于CLR,但不依赖于您的解析器。DLR或CLR对于您实际问题的意义没有区别。
有用的链接:为.NET Framework创建语言编译器

我从未谈论过构建DSL,而且有一些工具可以帮助Lexer和Parser。ANTLR就是其中之一,使用它可以构建AST,然后在编译器的后续阶段使用DLR。 - Ariel
@Ariel:我也是:) 我的意思是你不能避免使用解析器,只能依靠DSL的力量做你想做的事情。我的最后一句话就是这个意思。 - Tigran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接