漫谈IronPython 编译器讲述说明

开发 后端
本文向大家介绍IronPython 编译器,可能好多人还不了解IronPython 编译器,没有关系,看完本文你肯定有不少收获,希望本文能教会你更多东西。

自 IronPython 正式发布以来,由于对 Python 语言的喜爱所驱使,同时我想藉此去了解一下编程语言的IronPython 编译器,分析器等程序是什么原理,如何运作的,于是就开始进行IronPython 编译器的学习了。

但代码也看了有一段时间了,之前是看一些实现细节,结果越看越糊涂。现在我发现需要改变一下策略了,因为我们了解一个系统总是从对它的使用方法去开始了解,如果直接去了解底层的运作原理,则可能会迷失在代码海洋里面。所以我也准备采取自顶而下的分析方法,捡软柿子捏,从简单的,宏观的入手。至于具体的实现细节,可以慢慢再深入研究。

直奔主题,我们看到 Compile() 方法,这是负责编译的主控制方法。这个方法不难理解,我读了一遍,注释如下:

  1. /// <summary> 
  2. /// 编译  
  3. /// </summary> 
  4. public void Compile() {  
  5.     string fullPath = Path.GetFullPath(outputAssembly);  
  6.     string outDir = Path.GetDirectoryName(fullPath);  
  7.     string fileName = Path.GetFileName(outputAssembly);  
  8.  
  9.     // Python 编译器的接受池  
  10.     PythonCompilerSink sink = new PythonCompilerSink(compilerSink);  
  11.  
  12.     // 程序集产生器  
  13.     assemblyGen = new AssemblyGen(  
  14.         Path.GetFileNameWithoutExtension(outputAssembly),  
  15.         outDir, fileName, includeDebugInformation, staticTypes, executable, machine  
  16.         );  
  17.  
  18.     // 是否以设定入口点(entry point)  
  19.     bool entryPointSet = false;  
  20.  
  21.     // 设定默认的主文件(对非 DLL 的输出文件类型而言)  
  22.     if (mainFile == null && sourceFiles.Count == 1 && targetKind != PEFileKinds.Dll) {  
  23.         mainFile = sourceFiles[0];  
  24.     }  
  25.  
  26.     // 对每个源文件依次编译  
  27.     foreach (string sourceFile in sourceFiles) {  
  28.         // 是否产生 Main 方法  
  29.         bool createMainMethod = sourceFile == mainFile;  
  30.         // 每个源代码文件编译为一个模块  
  31.         CompilePythonModule(sourceFile, sink, createMainMethod);  
  32.  
  33.         if (sink.Errors > 0) return;  
  34.  
  35.         if (createMainMethod) {  
  36.             entryPointSet = true;  
  37.         }  
  38.     } 

这段代码中,调用到了 IronPython 编译器自身的私有方法 CompilePythonModule() 来完成编译模块的功能。下面我们来看一下这个方法在做什么:

  1.     // 依次将所有资源文件添加到程序集中  
  2.     if (resourceFiles != null) {  
  3.         foreach (ResourceFile rf in resourceFiles) {  
  4.             assemblyGen.AddResourceFile(rf.Name, rf.File, rf.PublicResource ? ResourceAttributes.Public : ResourceAttributes.Private);  
  5.         }  
  6.     }  
  7.  
  8.     // 对非 DLL 的目标文件,必须要求有一个入口点  
  9.     if (targetKind != PEFileKinds.Dll && !entryPointSet) {  
  10.         sink.AddError("", string.Format("Need an entry point for target kind {0}", targetKind), String.Empty, CodeSpan.Empty, -1, Severity.Error);  
  11.     }  
  12.  
  13.     // 最终产生输出的程序集  
  14.     assemblyGen.Dump();  
  15. }  
  16.  
  17. 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/inelm/archive/2006/10/09/4612996.aspx 

在上述两个方法中,我们看到,出现了几个重要的类,它们将是我们下面接着分析的重点线索:

  1. // 编译模块  
  2. private void CompilePythonModule(string fileName, PythonCompilerSink sink, bool createMain) {  
  3.     // 设定当前要编译的源文件  
  4.     assemblyGen.SetPythonSourceFile(fileName);  
  5.     // 创建编译器环境对象  
  6.     CompilerContext context = new CompilerContext(fileName, sink);  
  7.     // 创建分析器  
  8.     Parser p = Parser.FromFile(state, context);  
  9.     // 调用分析器的分析方法,得到一个语句对象(语句应该是利用了组合模式的一个嵌套的概念,这个语句代表整个文件里的一个大语句)  
  10.     Statement body = p.ParseFileInput();  
  11.  
  12.     if (sink.Errors > 0) return;  
  13.  
  14.     // 创建一个全局套件??有可能是指 globals() 这个字典对象。有待分析。。。  
  15.     // 这里面的 Binder 是干什么的也有待研究。  
  16.     GlobalSuite gs = Compiler.Ast.Binder.Bind(body, context);  
  17.     string moduleName = GetModuleFromFilename(fileName);  
  18.     // 这里看到了 TypeGen,该类代表一个类型产生器  
  19.     // tg 指向了一个模块类型(IronPython 中,每一个模块产生为一个对应的类。)  
  20.     TypeGen tg = OutputGenerator.GenerateModuleType(moduleName, assemblyGen);  
  21.     // 编译模块的 __init__ 方法??(猜测)  
  22.     CodeGen init = CompileModuleInit(context, gs, tg, moduleName); 

到这里为止,我们大致上看到了 IronPython 编译器的工作流程,从一系列源代码文件,资源文件,以及其他一些配置属性出发,经过 Parser, 各种 Generator 的运作,最终到达 AssemblyGenerator 的 Dump() 方法,输出编译结果程序集。

【编辑推荐】

  1. 如何使Python嵌入C++应用程序?
  2. 深入探讨Ruby与Python语法比较
  3. Python学习资料介绍分享
  4. Python学习经验谈:版本、IDE选择及编码解决方案
  5. 浅析Python的GIL和线程安全
责任编辑:chenqingxiang 来源: CSDN
相关推荐

2010-01-18 10:34:21

C++编译器

2010-02-02 17:08:26

Python静态编译器

2010-02-02 17:08:26

Python静态编译器

2010-01-28 15:56:38

VC++ 6.0编译

2010-01-13 17:12:26

C++编译器

2010-01-13 13:58:49

C++编译模式

2017-03-20 18:01:55

编译器汇编

2009-08-10 17:12:54

C#编译器

2013-03-29 10:02:37

编译器语言编译开发

2010-01-21 09:11:38

C++编译器

2010-03-23 11:17:16

Python 动态编译

2009-12-11 15:38:40

VS2008编译器

2010-10-20 13:43:37

C++编译器

2019-08-06 08:20:07

编译器工具开发者

2010-01-19 18:24:53

C++编译环境

2011-05-18 11:06:25

java编译器

2013-12-30 11:21:31

Go编译器

2010-09-16 15:57:25

Java编译器

2022-03-28 10:25:27

前端文件编译器

2009-08-06 14:59:36

C#编译器
点赞
收藏

51CTO技术栈公众号