Inside IronPython: IronPython AST语法树(1/2)
.NET平台上早期的各个动态语言的实现相对独立:例如IronPython的1.x实现,基本上都是在.NET CLR的基础上直接构建各自的实现。到了IronPython2.x时,动态语言的架构发生了很大变化,这个变化具有革命意义,就像现在的CLR一样重要和伟大(CLR统一了静态语言,GC,JIT…省去废话x万字)。这个变化就是微软引入了DLR(动态语言运行时:Dynamic Language Runtime),同时又在.NET CLR中添加了一组核心特性以更好地支持动态语言。DLR是建立在CLR之上的,面向所有在.NET平台上运行的动态语言提供服务。当然,DLR也是跨平台的(Mono)!
DLR提供的功能有:一个共享的动态类型系统,一个标准的宿主模型,支持更容易的生成快速动态代码和快速符号表。有了这些附加功能,你就可以轻松的为.NET构建高质量的动态语言实现,这样你就可以使用自己最喜爱的动态语言去编写代码,原有的动态语言编程的经验,思维,技巧,工具等等也得以保留。最重要的一点是:DLR使得所有构建于其上的动态语言之间可以相互共享代码,并且都可以共享基于CLR的静态语言编写的类库。IronPython 和DLR的源代码可以在www.codeplex.com下载到,它们都遵循微软的开源协议。
我们听说DLR也有一些时间了,但是它到底是个什么玩意呢,怎么提供这些功能的呢,又是怎么运转的呢?遵循“源码之前了无秘密”的名言,还是让我们用一些代码来解释吧。我将展示并试图说明:ipy.exe是怎么执行一个代码文件的(怎么去进行语法分析,又是怎么编译的),我们也将看到DLR 是怎样通过缓存方法去提高性能(DLR使用自适应的方法缓存来产生快速动态程序,并且所有在DLR上实现的语言都会从此受益。DLR通过避免重复搜索类优先级列表使得代码运行得更快,它也同样避免了每次调用对象的方法时进行的.NET重载方法解析)。
试验代码:demo.py
text = "hello, "
return text + name
print func("World")
这段代码比经典的“hello world”稍微多那么一点点,这样我们就能讨论更多有趣的IronPython实现。比如说,我们将会遇到标识符的名称绑定和func方法中“+”含义的缓存。在实验前,请到http://www.codeplex.com/IronPython下载2.0 beta 3的源代码:IronPython-2.0B3-Src.zip。我也将介绍怎样在调试器里查看程序的抽象语法树以及怎样在命令行里用一些诊断开关去生成一些我们可以拿来查看代码的.exe/.dll文件。我们先对Visual studio2008进行必要的设置:把IronPythonConsole工程设置成启动项目。并且设置它的启动命令行参数为:“demo.py”(把demo.py复制到工程的生成目录:..\..\Bin\Debug\中)。
启动并调试ipy.exe
现在让我们看看ipy.exe是怎么启动的。DLR提供了几个默认的console类,让语言的实现者可以非常方便的运行一个解释器(仍然需要编写语言的解析器和运行时实现)。Console类处理输入输出,命令行开关,一些DLR实现的共享诊断调试开关。这使得语言的实现者先让一些代码在DLR上运行起来,并且提供了一个测试工具。我们先在…\IronPython-2.0B3-Src\IronPython-2.0B3\Src\IronPython\Runtime\PythonContext.cs文件中的PythonContext类的重载方法ParseSourceCode()中语句:using (Parser parser = Parser.CreateParser(context, PythonContext.GetPythonOptions(null)))处设置一个断点。
按F5运行程序。当对IronPython源代码进行解析的时候便到达我们设置的断点处。这时候我们可以去查看调用堆栈,看是怎么一步步运行到断点处的:
PythonConsoleHost的Main函数是ipy.exe的入口点,接着程序进入到DLR的代码,当程序返回到IronPython的代码去处理命令行参数的时候,我们的脚本代码便开始执行。PythonConsoleHost 类(从DLR提供的ConsoleHost类继承)的代码很少, 它初始化了脚本引擎。 ConsoleHost类让语言的实现者快速创建一个控制台样式的交互式解释器 。PythonConsoleHost类重载了ConsoleHost类的CreateCommandLine()方法,从而返回一个PythonCommandLine 对象。当 ConsoleHost调用 CommandLine的Run()方法时,IronPython代码便得到执行。PythonCommandLine做了一些初始化工作比如:设置了Python加载模块的路径,初始化一些内置模块…