自 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. 【BZOJ4128】Matrix BSGS+hash

    [BZOJ4128]Matrix Description 给定矩阵A,B和模数p,求最小的x满足 A^x = B (mod p) Input 第一行两个整数n和p,表示矩阵的阶和模数,接下来一个n * ...

  2. js apply / call 函数

    这两个函数的作用是: 将函数绑定到另外一个对象上去运行 用call和apply应用另一个函数(类)以后,当前的函数(类)就具备了另一个函数(类)的方法或是属性,这也能够称之为“继承”. functio ...

  3. 【转载】解决Apache2+PHP上传文件大小限制的问题

    原文出处:http://evol1216.blog.163.com/blog/static/13019958020106783623528/ 在用PHP进行文件上传的操作中,需要知道怎么控制上传文件大 ...

  4. RockerMQ connect to<:10009>fail

    producer端发送报错 com.alibaba.rocketmq.client.exception.MQClientException: Send [] times, still failed, ...

  5. Android蓝牙串口通讯【转】

    本文转载自:http://blog.sina.com.cn/s/blog_631e3f2601012ixi.html Android蓝牙串口通讯 闲着无聊玩起了Android蓝牙模块与单片机蓝牙模块的 ...

  6. Spring Cloud之Ribbon与Nginx区别

    客户端负载均衡器 在SpringCloud中Ribbon负载均衡客户端,会从eureka注册中心服务器端上获取服务注册信息列表,缓存到本地. 让后在本地实现轮训负载均衡策略. Ribbon与Nginx ...

  7. SpringBoot2.0之整合RabbitMQ

    案例: Springboot 对RabbitMQ的支持 公共的pom: <project xmlns="http://maven.apache.org/POM/4.0.0" ...

  8. 剑指offer之 数组中出现次数超过一半的数字

    public class Solution { public int MoreThanHalfNum_Solution(int [] array) { if(array==null||array.le ...

  9. The Quantum L3 router and floating IPs

    This post shows how the Quantum L3 Agent uses the Linux IP stack to implement the Quantum L3 Routing ...

  10. Keep DNS Nameserver Order Consistency In Neutron

    一个subnet有多个dns server时,dns server在创建时就定好了,但可以update: neutron subnet-update 1a2d261b-b233-3ab9-902e-8 ...