接上篇: Inside IronPython: IronPython AST语法树(1/2)
ASTs简介:
当 ipy.exe 执行demo.py的时候,IronPython语言自身的实现和DLR共同参与源代码的编译处理。从基本层面上来讲,编译器是流水化作业的:从语法解析器生成描述源代码的特定数据结构开始。这个数据结构是个抽象语法树(abstract syntax tree),简称为AST。编译器在完成代码分析阶段后将转换AST或者建立新的数据结构,然后再基于此结果,编译器产生机器码或者虚拟机的中间语言(IL)。
IronPython首先产生一个特定于IronPython的抽象语法树,然后再把这个语法树转换成DLR的语法树。一些语言有自己的语法树的原因是这样可以更好的支持对代码进行分析,也能更好的支持一些基于自有AST的工具(工具需要一个更接近于源代码的AST。许多语言的AST也许和DLR的AST比较相似,但是DLR的AST包含更多关于确切语义含义的信息。你可以认为DLR AST是编译器需要的多个转换中较晚阶段需要的那个。
非常有趣的是DLR使用了和CLR Jit编译技术相似的缓式编译技术:并不是一下子编译全部的代码。这样在第一次运行的时候我们会有一点点的性能损耗,但是以后执行时可以运行的更快。
查看IronPython的AST
回到VS IDE中,按F5执行程序,在断点处暂停(其实在你安装的IronPython中,第一次到达断点时,并不是处理demo.py文件,而是一个名叫site.py的文件。因为在我们的...\Bin\Debug目录下根本没有这个文件,所以就直接处理demo.py文件了)。接下来我们按F10单步执行程序,直到执行了:ast = parser.ParseFile(true);。现在我们就可以在“监视”窗口中查看IronPython的AST了。
由于空间问题, 我只在图中展开了ast.Body的部分成员。AST的根节点是SuiteStatement,表示了一系列的语句,它有一个成员:Statements。展开Statements中的第一个成员,将看到这个成员是个FunctionDefinition类型的节点,它有一个Body成员(又是一个SuiteStatement类型):表示函数的定义,我们可以看到它有一个Name 成员,并且最后它的名字将绑定到结果函数对象。我们展开demo.py中所有元素,它们之间的关系如下图所示: