`
xpenxpen
  • 浏览: 724991 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Groovy实现原理简单研究(2)

阅读更多
上回说到:
groovy负责词法、语法分析groovy文件,然后用asm生成普通的class文件,供jvm使用

这回稍许详细的分析一下源码。
我这里还是选用的最早期的groovy的初版。
整理好的代码可在附件下载,经过改装,可在maven2, maven3下编译通过,并导入到eclipse中。我这里就叫他为groovy0.1吧。

主程序在Compiler里,编译流程为3阶段。stageOne,stageTwo,stageThree。

1.stageOneCompile

代码都在以下3个包里:
  • org.codehaus.groovy.syntax
  • org.codehaus.groovy.syntax.lexer 词法分析
  • org.codehaus.groovy.syntax.parser 语法分析


Compiler.java
    protected CSTNode stageOneCompile(File file)
        throws Exception
    {
        LOG.info( "stage-1 compiling: " + file );

        FileInputStream       fileIn     = new FileInputStream( file );
        BufferedInputStream   bufferedIn = new BufferedInputStream( fileIn );
        InputStreamCharStream charStream = new InputStreamCharStream( bufferedIn );

        try
        {
            Lexer lexer = new Lexer( charStream );
            Parser parser = new Parser( new LexerTokenStream( lexer ) );

            return parser.compilationUnit();
        }
        finally
        {
            charStream.close();
        }
    }

大致就是Lexer负责词法分析,Parser负责语法分析,生成CST。

1.1 词法分析
也就是拆词,或者有点lucene里的分词的意思。
比如 "package cheese.toast"
Lexer.nextToken每次调用返回的Token依次是
package
cheese
.
toast


1.2 语法分析。生成具体语法树(CST)
可参考ParserTest.testPackageDeclaration_OneDot()
比如 "package abc.def.ghi"

调用以下代码,
CSTNode root = parser.packageDeclaration();


解析以后变成一棵树,
package
|--- .(dot)
       |--- .(dot)
       |       |----abc
       |       |----def
       |----ghi

     
以上2步都属于Compiler.stageOneCompile
stageOneCompile会去调用Parser.compilationUnit(),得到一个解析好的语法树。

2.stageTwoCompile
语义合法验证,内容暂时是空的,先略过。

3. stageThreeCompile

这里除了ASTBuilder类在org.codehaus.groovy.syntax.parser以外,
还有代码集中在org.codehaus.groovy.ast包中。

Compiler.java
    protected void stageThreeCompile(CSTNode compilationUnit,
                                     File file )
        throws Exception
    {
        ASTBuilder astBuilder = new ASTBuilder( getClassLoader() );

        ClassNode[] classNodes = astBuilder.build( compilationUnit );

        for ( int i = 0 ; i < classNodes.length ; ++i )
        {
            dumpClass( classNodes[ i ],
                       file );
        }
    }

可以看到2个步骤,先build AST,然后dump class。

3.1  生成抽象语法树(AST)
ASTBuilder.build()

关于CST和AST的区别可以参考
http://eli.thegreenplace.net/2009/02/16/abstract-vs-concrete-syntax-trees
简单来说,AST就是将CST简化了,去掉以及合并了很多没用的节点,比如去掉分号啦,合并abc.def.ghi这种带有好多点的包名等等。

比如包名,CST转成AST以后,大致像下面这般模样:
package
|--- abc.def.ghi

如图,生成的抽象语法树有如下这些节点,所有的节点都是继承自ASTNode。


比如最基本的,一个类的父亲节点是ClassNode,它的儿子有FieldNode和MethodNode分别代表属性和方法。

3.1.1 getter/setter
我们研究下groovy在哪里自动生成getter/setter的。
查看代码ClassNode.addProperty()
    public void addProperty(PropertyNode node) {
        FieldNode field =
            new FieldNode(node.getName(), ACC_PRIVATE, node.getType(), getName(), node.getInitialValueExpression());
        addField(field);

        String name = node.getName();
        String getterName = "get" + capitalize(name);
        String setterName = "set" + capitalize(name);

        Statement getterBlock = node.getGetterBlock();
        if (getterBlock == null) {
            getterBlock = createGetterBlock(node, field);
        }
        Statement setterBlock = node.getGetterBlock();
        if (setterBlock == null) {
            setterBlock = createSetterBlock(node, field);
        }

        MethodNode getter =
            new MethodNode(
                getterName,
                node.getModifiers(),
                node.getType(),
                Parameter.EMPTY_ARRAY,
                getterBlock);
                
        addMethod(getter);

        Parameter[] setterParameterTypes = { new Parameter(node.getType(), "value")};
        MethodNode setter =
            new MethodNode(setterName, node.getModifiers(), "void", setterParameterTypes, setterBlock);
        addMethod(setter);


        properties.add(node);
    }

可以发现在增加属性节点的同时,就给自动生成了2个方法节点,getter和setter。

3.2 dumpClass
这里既是用ASM生成java字节码了,毋庸置疑,用到了有名的visitor模式。
    protected void dumpClass(ClassNode classNode,
                             File file)
        throws Exception
    {
        ClassWriter    classWriter    = new ClassWriter( true );
        ClassGenerator classGenerator = new ClassGenerator( classWriter,
                                                            getClassLoader(),
                                                            file.getName() );

        classGenerator.visitClass( classNode );

        byte[] code = classWriter.toByteArray();

        File outputFile = createOutputFile( classNode.getName() );

        if ( ! outputFile.getParentFile().exists() )
        {
            outputFile.getParentFile().mkdirs();
        }

        LOG.info( "generating class to: " + outputFile );

        FileOutputStream out = new FileOutputStream( outputFile );

        try
        {
            out.write( code );
        }
        finally
        {
            out.close();
        }
    }

ASM和visitor模式暂时不展开了。后面有机会再深入分析。
  • 大小: 27.4 KB
分享到:
评论

相关推荐

    groovy-src-2.3.6.zip 最新稳定版源码

    深入研究Groovy 2.3.6的源码,不仅可以帮助我们理解语言的内部工作原理,还可以为开发人员提供灵感,如何在自己的项目中应用这些设计理念和技巧。无论是为了学习、调试还是扩展Groovy,源码都是一个宝贵的资源。

    rxjava-groovy-0.7.0.zip

    通过研究这个项目,我们可以深入理解RxJava在Groovy环境下的工作原理,学习如何优雅地处理异步流程,以及如何利用Groovy的特性来优化代码。这对于提升我们的并发编程能力和理解反应式编程模型都大有裨益。对于想要在...

    groovy+spring在web中的应用

    通过研究这些示例,读者可以更好地理解Groovy在Spring环境中的工作原理和最佳实践。 总的来说,Groovy与Spring的结合为Web开发提供了一种新的可能性,它使得开发过程更加高效、灵活,并且富有表现力。无论是从配置...

    groovy-src-1.7.0

    通过查看源代码,开发者可以深入理解Groovy语言的实现细节,包括其解释器、编译器、类加载器以及其他关键组件的工作原理。 Groovy 1.7.0版本引入了一些关键特性,例如: 1. 改进了类型推断:这使得在不声明类型的...

    XStream Deserializable Vulnerablity And Groovy CVE-2015-3253漏洞分析

    本文将深入探讨XStream组件的反序列化漏洞,并结合Groovy的CVE-2015-3253漏洞进行分析,以揭示其中的原理和影响。 XStream是一款流行的Java库,用于XML和对象之间的序列化和反序列化。近期,XStream反序列化漏洞...

    基于Grails的办公自动化系统的研究与实现.rar

    本研究聚焦于采用Groovy on Grails(简称Grails)框架开发的办公自动化系统,探讨其设计原理、实施方法以及在实际应用中的优势。 Grails是一个开源的Web应用程序框架,基于Groovy语言,它充分利用了Java平台的灵活...

    Drools5规则引擎学习研究

    例如,给出的代码段展示了两个简单的规则:"rule1"和"rule2"。这些规则会在满足条件(当有一个`Customer`对象时)时触发,设置订单数量并打印出订单的数量。这种声明式的编程方式让业务逻辑更加清晰。 学习Drools...

    grails app

    2. **Groovy语言基础** Groovy是运行在Java虚拟机上的动态语言,它是Grails的基础。Groovy语法简洁,支持闭包,能与Java无缝集成,使得开发更高效。在压缩包中的代码,我们可以看到Groovy的特性如何体现在Grails...

    使用SlidingMenu方法实现侧滑栏菜单_android源码下载.zip

    现在也有一些替代方案,如Android Design Support Library中的`NavigationView`或使用现代框架如Jetpack Compose的`Scaffold`组件,但SlidingMenu仍然适用于学习和理解侧滑栏菜单的基本实现原理。

    Android教你如何一分钟实现下拉刷新功能项目完整实例代码

    以上就是一个简单的下拉刷新功能的实现步骤。在实际应用中,你可能需要考虑更多细节,比如在网络错误时的处理、离线模式下的显示,以及优化用户体验等。 在提供的"PullToRefreshTest"项目中,你应该能够找到完整的...

    grails-1.3.0.RC2

    在研究 `grails-1.3.0.RC2` 源代码时,开发者可以深入了解Grails框架的架构,学习如何实现MVC模式,以及如何利用Groovy语言的特性来优化Web应用的开发。此外,还可以探索框架的内部工作原理,比如GORM是如何处理...

    Spring 3.0 就这么简单(源码)

    这个"Spring 3.0 就这么简单(源码)"压缩包文件包含了Spring 3.0的核心源码,为深入理解Spring的工作原理和学习其设计思想提供了宝贵的资源。 Spring 框架是一个全面的企业应用框架,它的核心特性包括依赖注入...

    智慧事物

    2. **API集成**:许多物联网设备提供了RESTful API,Groovy可以方便地调用这些API,实现设备间的通信和数据交换。 3. **数据分析**:Groovy可以处理从物联网设备收集的大量数据,进行实时分析和处理,以提供更智能的...

    killbill-overdue-0.1.44.zip

    2. **Groovy 语言**:Ratpack 用 Groovy 语言编写,Groovy 是一种简洁、动态的 JVM 语言,具有丰富的语法糖,使代码更易读写。 3. **简单API**:Ratpack 提供了一套简单的API来处理HTTP请求和响应,使得开发者可以...

    JVFloatingDrawer Demo

    本文将深入探讨JVFloatingDrawer的核心概念、使用方法以及其实现原理。 首先,抽屉效果在Android应用中通常通过`android.support.v4.widget.DrawerLayout`来实现,它是Android Support Library的一部分。然而,...

    javaSE代码实例

    第2章 基本数据类型——构建Java 大厦的基础 12 2.1 源代码注释 12 2.1.1 单行注释 12 2.1.2 区域注释 12 2.1.3 文档注释 13 2.2 基本数据类型 14 2.2.1 整型 15 2.2.2 浮点型 17 2.2.3 char型 17...

    java源码:Java开发的SHELL CRaSH.gz

    3. **脚本支持**:除了基本的命令执行,CRaSH还支持通过JavaScript或Groovy编写脚本,增强了交互性,使得自动化任务变得简单。 4. **集成Spring框架**:CRaSH通常与Spring框架紧密集成,可以轻松地注入到Spring管理...

    超简单实现图片裁切功能

    通过研究Android-CropView-master源代码,开发者可以更深入地理解图片裁剪的实现原理,为自己的项目定制更多功能,比如添加更多裁剪形状、滤镜效果等。 总之,Android-CropView是一个强大的图像裁剪工具,它简化了...

    DSLs实战-DSLs in Action

    ### DSLs实战——深入探索领域特定语言 #### 引言 《DSLs实战》是一本由Debasish Ghosh撰写...通过系统地学习书中提供的理论知识和实践案例,读者将能够更好地理解DSL的原理,并掌握设计和实现各种类型的DSL的技术。

    MQTT客户端示例

    通过研究这个示例,开发者可以快速上手在Android应用中集成MQTT协议,实现物联网设备的数据交互。 总结来说,MQTT是物联网领域常用的通信协议,尤其适用于资源有限的设备。在Android平台上,借助Paho MQTT库,我们...

Global site tag (gtag.js) - Google Analytics