温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

怎样理解IronPython 编译器

发布时间:2021-11-02 17:33:06 来源:亿速云 阅读:153 作者:柒染 栏目:编程语言

这篇文章将为大家详细讲解有关怎样理解IronPython 编译器,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

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

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

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

/// <summary> /// 编译  /// </summary> public void Compile() {      string fullPath = Path.GetFullPath(outputAssembly);      string outDir = Path.GetDirectoryName(fullPath);      string fileName = Path.GetFileName(outputAssembly);       // Python 编译器的接受池      PythonCompilerSink sink = new PythonCompilerSink(compilerSink);       // 程序集产生器      assemblyGen = new AssemblyGen(          Path.GetFileNameWithoutExtension(outputAssembly),          outDir, fileName, includeDebugInformation, staticTypes, executable, machine          );       // 是否以设定入口点(entry point)      bool entryPointSet = false;       // 设定默认的主文件(对非 DLL 的输出文件类型而言)      if (mainFile == null && sourceFiles.Count == 1 && targetKind != PEFileKinds.Dll) {          mainFile = sourceFiles[0];      }       // 对每个源文件依次编译      foreach (string sourceFile in sourceFiles) {          // 是否产生 Main 方法          bool createMainMethod = sourceFile == mainFile;          // 每个源代码文件编译为一个模块          CompilePythonModule(sourceFile, sink, createMainMethod);           if (sink.Errors > 0) return;           if (createMainMethod) {              entryPointSet = true;          }      }

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

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

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

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

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

关于怎样理解IronPython 编译器就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI