自 IronPython 正式发布以来,由于对 Python 语言的喜爱所驱使,同时我想藉此去了解一下编程语言的编译器,分析器等程序是什么原理,如何运作的,所以我开始了对 IronPython 源代码的学习过程。但代码也看了有一段时间了,之前是看一些实现细节,结果越看越糊涂。现在我发现需要改变一下策略了,因为我们了解一个系统总是从对它的使用方法去开始了解,如果直接去了解底层的运作原理,则可能会迷失在代码海洋里面。所以我也准备采取自顶而下的分析方法,捡软柿子捏,从简单的,宏观的入手。至于具体的实现细节,可以慢慢再深入研究。

OK,今天被我抓到的看起来像软柿子的是:

IronPython/Hosting/PythonCompiler.cs

首先我们抓住要点,看这个文件中的主要类: PythonCompiler (Python 编译器)

在这个类中,首先有一堆的属性不用去管,表示的无非是编译器将要输出的文件的类型啊(DLL 还是 EXE),输出路径,引用了哪些程序集啊等等东西。

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

, Severity.Error);
    }

// 最终产生输出的程序集
    assemblyGen.Dump();
}

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

) 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);

// 如果需要创建 Main 方法则创建之
    if (createMain) {
        // 联想前面一个 CodeGen 的例子,观察调用语句可以想到,方法的产生器是
        // CodeGen,而类型的产生器是 TypeGen
        CodeGen main = OutputGenerator.GenerateModuleEntryPoint(tg, init, moduleName, referencedAssemblies);
        // 这里注意到 CodeGen 代码产生器含有一个重要的属性就是代表这个方法
        // 的反射信息的 MethodInfo, 可以通过这个来调用产生的方法。
        assemblyGen.SetEntryPoint(main.MethodInfo, targetKind);
    }

// 因为模块类不是普通的类,需要给他添加一个特殊的标签(Attribute)
    assemblyGen.AddPythonModuleAttribute(tg, moduleName);
    // 产生类型的动作完毕
    tg.FinishType();
}

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

Parser:       分析器
Statement:   语句
GlobalSuite: globals() ??
TypeGen:     类型产生器
CodeGen:     代码产生器(用于产生方法的代码)

在另一个私有方法 CompileModuleUnit 中,主要是进行了一些模块的导入工作,代码很容易懂,这里不详细分析。

现在回头看一下,在 IronPython/Hosting/PythonCompiler.cs 这个文件中,还剩下了两个类没有提到:
ResourceFile: 代表一个资源文件的相关属性。
PythonCompilerSink: 按照字面理解就是 PythonCompiler 的编译结果的接受池。至于它到底如何运作,留待后面再分析。

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

以上的代码分析难免有错误之处,尚有待继续挖掘和梳理。

出处:http://www.cnblogs.com/RChen/archive/2006/10/09/ipysrcstudy1.html

IronPython 源码剖析系列(1):IronPython 编译器的更多相关文章

  1. IronPython 源码剖析系列(2):IronPython 引擎的运作流程

    http://blog.csdn.net/inelm/article/details/4612987 一.入口点 Python 程序的执行是从 hosting 程序 ipy.exe 开始的,而他的入口 ...

  2. 【java集合框架源码剖析系列】java源码剖析之TreeSet

    本博客将从源码的角度带领大家学习TreeSet相关的知识. 一TreeSet类的定义: public class TreeSet<E> extends AbstractSet<E&g ...

  3. 【java集合框架源码剖析系列】java源码剖析之HashSet

    注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本.本博客将从源码角度带领大家学习关于HashSet的知识. 一HashSet的定义: public class HashSet&l ...

  4. 【java集合框架源码剖析系列】java源码剖析之TreeMap

    注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本.本博客将从源码角度带领大家学习关于TreeMap的知识. 一TreeMap的定义: public class TreeMap&l ...

  5. 【java集合框架源码剖析系列】java源码剖析之ArrayList

    注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本. 本博客将从源码角度带领大家学习关于ArrayList的知识. 一ArrayList类的定义: public class Arr ...

  6. 【java集合框架源码剖析系列】java源码剖析之LinkedList

    注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本. 在实际项目中LinkedList也是使用频率非常高的一种集合,本博客将从源码角度带领大家学习关于LinkedList的知识. ...

  7. 【java集合框架源码剖析系列】java源码剖析之HashMap

    前言:之所以打算写java集合框架源码剖析系列博客是因为自己反思了一下阿里内推一面的失败(估计没过,因为写此博客已距阿里巴巴一面一个星期),当时面试完之后感觉自己回答的挺好的,而且据面试官最后说的这几 ...

  8. WorldWind源码剖析系列:星球类World

    星球类World代表通用的星球类,因为可能需要绘制除地球之外的其它星球,如月球.火星等.该类的类图如下. 需要说明的是,在WorldWind中星球球体的渲染和经纬网格的渲染时分别绘制的.经纬网格的渲染 ...

  9. WorldWind源码剖析系列:星球球体的加载与渲染

    WorldWind源码剖析系列:星球球体的加载与渲染 WorldWind中主函数Main()的分析 在文件WorldWind.cs中主函数Main()阐明了WorldWind的初始化运行机制(如图1所 ...

随机推荐

  1. springmvc demo

    [说明]今天上午稍稍偏了一下方向,看了看servlet的相关知识,下午做maven+spring+springMVC的整合,晚上成功实现了一个小demo(可以在jsp动态页面上获得通过地址栏输入的参数 ...

  2. 使用google的GSON解析json格式的数据

    GSON是谷歌提供的开源库,用来解析Json格式的数据,非常好用.如果要使用GSON的话,则要先下载gson-2.2.4.jar这个文件,如果是在Android项目中使用,则在Android项目的li ...

  3. debian安装oracle jdk

    1 去官网下载linux jdk https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.htm ...

  4. Symfony 使用KnpTimeBundle

    使用time_diff时出现:diff.ago.hour; 解决:1:引入"knplabs/knp-time-bundle": "^1.7",https://g ...

  5. jQuery对象转成DOM对象:

    jQuery对象转成DOM对象: 两种转换方式将一个jQuery对象转换成DOM对象:[index]和.get(index); (1)jQuery对象是一个数据对象,可以通过[index]的方法,来得 ...

  6. linux 中sort命令 按照指定列排序

    sort怎样按指定的列排序0000 27189 41925425065f 15 419254250663 7 419254250675 5 419254250691 76 419254250693 2 ...

  7. iOS 基本数据类型 和 指针 特点

    基本数据类型 : 整型int, 字符型char , 浮点型 (float 和 double), 枚举型; -- 构造类型 : 数组类型, 结构体类型, 共用体类型; -- 指针类型 : 最终要的数据类 ...

  8. 手机端适配rem代码片段

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. Android电池驱动【转】

    本文转载自:http://blog.sina.com.cn/s/blog_66a6a5ec0100n6ej.html Android的电池的管理分为三个部分:Java部分,JNI部分以及kenel部分 ...

  10. 剑指offer——求1+2+...+n

    方法一.通过在类的构造函数中执行加的过程. #include <iostream> using namespace std; class Base { public: Base(){n++ ...