35
Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved. Groovy 基礎勉強会 Groovy実行の基礎 ~コンパイラ処理系としての Groovyを読み解く~ 2013/3/9 @青山オラクルセンター NTTソフトウェア Grails推進室 上原潤二 1 1339日土曜日

Read Groovy Compile process(Groovy Benkyoukai 2013)

Embed Size (px)

DESCRIPTION

Outline of groovy compilation process

Citation preview

Page 1: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

Groovy基礎勉強会

Groovy実行の基礎~コンパイラ処理系としての

Groovyを読み解く~2013/3/9 @青山オラクルセンター

NTTソフトウェア Grails推進室 上原潤二

113年3月9日土曜日

Page 2: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

自己紹介上原潤二(@uehaj)NTTソフトウェア株式会社Grails推進室JGGUG(日本Grails/Groovyユーザグループ)運営委員書籍執筆:プログラミングGROOVY(技術評論社)Grails徹底入門(翔泳社)

G*Magazine Vol 6記事書きました →ブログ「Grな日々」GroovyServ, LispBuilder, GVM(Groovy JVM),Staticalizer開発者

13年3月9日土曜日

Page 3: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

お品書きGroovyの実行のしくみANTLRによる構文解析ASMによるコード生成まとめ

313年3月9日土曜日

Page 4: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.4

Groovy実行のしくみ

13年3月9日土曜日

Page 5: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.5

今日のテーマ

Groovyソースツリーsrc/main├─groovy│ ├─beans│ ├─grape│ ├─inspect│ ├─io│ ├─lang│ ├─security│ ├─time│ ├─transform│ ├─ui│ ├─util│ │ └─logging│ └─xml└─org ├─apache │ └─commons │ └─cli └─codehaus └─groovy ├─antlr │ ├─java │ ├─parser │ └─treewalker ├─ast

│ ├─builder │ ├─expr │ ├─stmt │ └─tools ├─classgen │ └─asm │ ├─indy │ └─sc ├─cli ├─control │ ├─customizers │ │ └─builder │ ├─io │ └─messages ├─plugin ├─reflection │ └─stdclasses ├─runtime │ ├─callsite │ ├─dgmimpl │ │ └─arrays │ ├─m12n │ ├─memoize │ ├─metaclass │ ├─powerassert

│ ├─typehandling │ └─wrappers ├─syntax ├─tools │ ├─ast │ ├─gse │ ├─javac │ ├─shell │ │ └─util │ └─xml ├─transform │ ├─sc │ │ └─transformers │ └─stc ├─util └─vmplugin ├─v5 ├─v6 └─v7

13年3月9日土曜日

Page 6: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.6

JVM

Javaコードの実行Javaソース

.classファイル

javacコマンド

javaコマンド

標準クラスローダ

Javaクラス

13年3月9日土曜日

Page 7: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.7

JVM

2011

Groovyコードの実行Javaソース

.classファイル

javacコマンド

javaコマンド

標準クラスローダ

Javaクラス

Groovyコード

groovyコマンド

Groovyクラスローダ(オンメモリ実行時コンパイラ)

JavaクラスJavaクラス

.classファイル

groovycコマンド

13年3月9日土曜日

Page 8: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

Groovyコードの実行

86

JVM

標準クラスローダ

Groovyコード

groovyコマンド

Groovyクラスローダ(オンメモリ実行時コンパイラ)

JavaクラスJavaクラス

.classファイル

groovycコマンド

13年3月9日土曜日

Page 9: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.9

Groovyコード実行のためのコマンドとクラス

groovyコマンド

groovy.lang.GroovyClassLoader

groovycコマンド

groovy.ui.GroovyMain

o.c.g.tools.FileSystemCompiler groovy.lang.GroovyShell

org.codehaus.groovy.controll.CompilationUnit

groovysh

groovyConsole

groovy.util.GroovyScriptEngine

13年3月9日土曜日

Page 10: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

CompilationUnit

CompilationUnitはコンパイル処理の中核 「コンパイル処理を実行する単位」を表わすと同時にコンパイルのすべての過程を制御している。

10

org.codehaus.groovy.controll.CompilationUnit

13年3月9日土曜日

Page 11: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

JavaAwareCompilationUnit extends CompilationUnit

(余談)JavaAwareCompilationUnitextends CompilationUnit ジョイントコンパイルオプション(-j,--jointCompilation)を指定した場合に発動Groovyソースに加えJavaソースをコンパイルする能力を持つ-jをつけないと、拡張子.javaのファイルはGroovyコードとして解釈/コンパイルされる(!!)

1113年3月9日土曜日

Page 12: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

CompilationUnit#compile()

12

public  void  compile()  ..  {        compile(Phases.ALL);  //全フェイズのコンパイル処理を実行}

public  void  compile(int  throughPhase)  ..  {//  指定したフェイズ「まで」コンパイル処理実行    :}

13年3月9日土曜日

Page 13: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

フェイズとは何か?CompilationUnitが保持するコンパイルの進行状態である。

13

INITIALIZATION(1)                //ファイルを開いたりPARSING(2)                  //字句・構文解析、ANTLRのAST構築CONVERSION(3)                        //CSTからASTへの変換SEMANTIC_ANALYSIS(4)          //ASTの意味解析と解明CANONICALIZATION(5)            //ASTの補完INSTRUCTION_SELECTION(6)  //クラス生成(フェーズ1)CLASS_GENERATION(7)            //クラス生成(フェーズ2)OUTPUT(8)                                //クラスをファイルに出力FINALIZATION(9)                    //後始末ALL(9)                                      //後始末まですべて実行

13年3月9日土曜日

Page 14: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

(参考) ASTとは?AST…Abstract Syntax Tree,抽象構文木構文木の一種で、論理的な構造を表わす⇔ CST(Concrete Syntax Tree, 具象構文木)

14

例えば「a.foo(b,c)」を構文解析すると…

b

()

a foo

.

,

c

b

a foo

.

c

ASTCST

13年3月9日土曜日

Page 15: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

GroovyConsoleのGroovy AST Browser

1513年3月9日土曜日

Page 16: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

フェイズにもとづいたコンパイル処理

CompilationUnitに、フェイズを指定して種々のphaseOperation(後述)を追加することで処理が制御されるCompilationUnit#addPhaseOperation()あらかじめ決まっているもの以外に、以下が実行時に追加されるAST変換CompilerCustomizerとしてのAST変換

1613年3月9日土曜日

Page 17: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

(参考)フェイズとAST変換 AST変換は、それぞれ適用されるフェイズを指定して定義されている

17

フェイズ 実行されるAST変換INITIALIZATION -PARSING -CONVERSION @GrabSEMANTIC_ANALYSIS @Field, @Log, @PackageScope,CANONICALIZATION ほとんどのAST変換がここに所属

CategoryASTTransformation DelegateASTTransformation ImmutableASTTransformation

INSTRUCTION_SELECTION

@TypeChecked, @CompileStaticCLASS_GENERATION -OUTPUT -FINALIZATION -

13年3月9日土曜日

Page 18: Read Groovy Compile process(Groovy Benkyoukai 2013)

PARSING:SourceUnit#parse()AntlrParserPlugin#parseCST()// CSTを作る

CONVERSION:convert(SourceUnit#convert() // Generates an AST from the CST),AntlrParserPlugin.buildAST()//ANTLR ASTからGroovyのASTを生成EnumVisitor

SEMANTIC_ANALYSIS:resolve(VariableScopeVisitor, ResolveVisitor)staticImport(StaticImportVisitor)InnerClassVisitor

AnnotationCollectorTransformStaticVerifierInnerClassCompletionVisitorEnumCompletionVisitor

CANONICALIZATION:compileCompleteCheck

CLASS_GENERATION:classgen(OptimizerVisitor,GenericsVisitor, LabelVerifier, ClassCompletionVerifier, ExtendedVerifier, ClassVisitor, AsmClassGenerator)

OUTPUT:output

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

phaseOperations

1813年3月9日土曜日

Page 19: Read Groovy Compile process(Groovy Benkyoukai 2013)

今日のテーマ

PARSING:SourceUnit#parse()AntlrParserPlugin#parseCST()// CSTを作る

CONVERSION:convert(SourceUnit#convert() // Generates an AST from the CST),AntlrParserPlugin.buildAST()//ANTLR ASTからGroovyのASTを生成EnumVisitor

SEMANTIC_ANALYSIS:resolve(VariableScopeVisitor, ResolveVisitor)staticImport(StaticImportVisitor)InnerClassVisitor

AnnotationCollectorTransformStaticVerifierInnerClassCompletionVisitorEnumCompletionVisitor

CANONICALIZATION:compileCompleteCheck

CLASS_GENERATION:classgen(OptimizerVisitor,GenericsVisitor, LabelVerifier, ClassCompletionVerifier, ExtendedVerifier, ClassVisitor, AsmClassGenerator)

OUTPUT:output

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

phaseOperations

1813年3月9日土曜日

Page 20: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.19

ANTLRによる構文解析

13年3月9日土曜日

Page 21: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

ANTLRによる構文解析処理

ANTLRって何?Wikipediaより

再帰下降構文解析のコードを自動生成するGroovy 2.1が使っているのはANTLR 2.7.73もしくは4への移行も企画されているらしい

20

ANTLR(ANother Tool for Language Recognition)とは、LL(*)構文解析に基づくパーサジェネレータである(バージョン3.xはLL(*)、2.xまではLL(k))。PCCTS(Purdue Compiler Construction Tool Set)の後継として1989年に開発され、現在も活発に開発が続いている。中心となっているのは、サンフランシスコ大学の Terence Parr 教授である。ANTLR はLR法に基づいたパーサジェネレータと競合関係にあり、"ANT(i)-LR"(反LR)と読めるのも偶然ではない[要出典]。ANTLR はパーサだけでなくレキサーおよびツリーパーサも生成可能である。 文法の記述方法は、EBNFに似た形式となっている。

13年3月9日土曜日

Page 22: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

AntlrParserPlugin.javaパーサ(構文解析器)のメイン処理parseCST() …以下を呼び出してCSTを作った上で、ANTLRのASTに変換o.c.g.antlr.parser.GroovyLexero.c.g.antlr.parser.GroovyRecognizerbuildAST() …ANTLRのASTをGroovyのASTに変換

2113年3月9日土曜日

Page 23: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

GroovyLexer.java, GroovyRecognizer.java

groovy.gから自動生成されるのでGroovyソースコードには含まれていないGroovyソースコードをコンパイルするとtarget/generated-sources配下にJavaソースが生成される。

22

groovy.g(Groovy構文定義) ANTLR

GroovyLexer.java

GroovyRecognizer.java

13年3月9日土曜日

Page 24: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

ANTLR 2.7用のGroovy構文定義ファイル4324行あり、groovy中の最大級ソースの一つ

23

./src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java

14239行

./src/main/org/codehaus/groovy/antlr/groovy.g

4323行

./subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java

4229行

./src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java

3865行

groovy.g

13年3月9日土曜日

Page 25: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

groovy.gを覗いてみるANTLRによるCompilationUnitの定義

24

//  Compilation  Unit:  Groovyでは単一ファイルもしくはスクリプト。  //  このパーサの開始ルールです。compilationUnit              ://  ファイル冒頭文字列が"#!"の場合最初の行を無視                (SH_COMMENT!)?//  ファイル冒頭にコメントがあっても良い                nls!//  compilation  unitはopitionalなパッケージ定義から開始される                (      (annotationsOpt  "package")=>  packageDefinition                |      (statement[EOF])?                )//  スクリプト本体は任意個数の文のシーケンス。//  セミコロンand/or改行をセパレータとして扱う                (  sep!  (statement[sepToken])?  )*                EOF!        ;

13年3月9日土曜日

Page 26: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

do-whileはどうなっている?

25

/*OBS*  no  do-­‐while  statement  in  Groovy  (too  ambiguous)//  do-­‐while  statement    |      "do"^  statement  "while"!  LPAREN!  strictContextExpression  RPAREN!  SEMI!*OBS*/

13年3月9日土曜日

Page 27: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

(余談)AntlrPerserPluginをCompilerlerConfigrationで差し替える

26

import  org.codehaus.groovy.control.*import  org.codehaus.groovy.antlr.*import  org.codehaus.groovy.syntax.*  class  Pascalizer  extends  ParserPluginFactory  {    ParserPlugin  createParserPlugin()  {        new  AntlrParserPlugin()  {            Reduction  parseCST(SourceUnit  sourceUnit,  Reader  reader)  {                def  s  =  reader.text.replaceAll('begin',  '{').replaceAll('end',  '}')                s  =  s.replaceAll(/\(\*/,  '/*').replaceAll(/\*\)/,  '*/')                super.parseCST(sourceUnit,  new  StringReader(s))            }        }    }}  def  conf  =  new  CompilerConfiguration(pluginFactory:  new  Pascalizer())new  GroovyShell(binding,  conf).evaluate("""def  foo(arg)  begin  (*  コメントです  *)  println  argend

foo("hello  pascal!")""")

参考: http://groovyconsole.appspot.com/script/313年3月9日土曜日

Page 28: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.27

ASMによるコード生成

13年3月9日土曜日

Page 29: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

ASMって何?

28

Wikipediaより

Groovy 2.1が使っているのはASM 4.0

ObjectWeb ASMThe ASM library is a project of the ObjectWeb consortium. It provides a simple API for decomposing, modifying, and recomposing binary Java classes (i.e. bytecode). The project was originally conceived and developed by Eric Bruneton. ASM is Java-centric at present, and does not currently have a backend that exposes other bytecode implementations (such as .NET bytecode,Python bytecode, etc.).

13年3月9日土曜日

Page 30: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

CompilatoinUnit#classgenCLASS_GENERATIONフェイズのphaseOperation

29

new OptimizerVisitor(this).visitClass(classNode, source)new GenericsVisitor(source).visitClass(classNode)new Verifier().visitClass(classNode)new LabelVerifier(source).visitClass(classNode)new ClassCompletionVerifier(source).visitClass(classNode)new ExtendedVerifier(source).visitClass(classNode)

ClassVisitor visitor = createClassVisitor()new AsmClassGenerator(source, context, visitor, sourceName) .visitClass(classNode)byte[] bytes = visitor.toByteArray();generatedClasses.add(new GroovyClass(classNode.getName(), bytes))// bytesに出力されたバイトコード列をGroovyクラス実体として結び付ける// 次のoutputフェーズでバイトコード列を出力する

13年3月9日土曜日

Page 31: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

AsmClassGenerator以下を定義するVisitorvisitClass()visitClass()visitGenericType()visitConstructor()visitMethod()visitField()visitProperty()visitCatchStatement()visitBlockStatement()visitForLoop()visitWhileLoop()visitDoWhileLoop()visitIfElse()visitAssertStatement()visitTryCatchFinally()visitSwitch()visitCaseStatement()visitBreakStatement()visitContinueStatement()

visitSynchronizedStatement()visitThrowStatement()visitReturnStatement()visitExpressionStatement()visitTernaryExpression()visitDeclarationExpression()visitBinaryExpression()visitPostfixExpression()visitPrefixExpression()visitClosureExpression()visitConstantExpression()visitSpreadExpression()visitSpreadMapExpression()visitMethodPointerExpression()visitUnaryMinusExpression()visitUnaryPlusExpression()visitBitwiseNegationExpression()visitCastExpression()visitNotExpression()(以下略)

3013年3月9日土曜日

Page 32: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

コード生成の例(whileループ)

StatementWriter#writeWhileLoop(WhileStatement loop):

31

public  void  visitWhileLoop(WhileStatement  loop)  {    controller.getStatementWriter().writeWhileLoop(loop);}

mv.visitLabel(continueLabel)

Expression  bool  =  loop.getBooleanExpression();bool.visit(controller.getAcg());

controller.getOperandStack().jump(IFEQ,                                                                    breakLabel);

loop.getLoopBlock().visit(controller.getAcg());

mv.visitJumpInsn(GOTO,  continueLabel);mv.visitLabel(breakLabel);

continueLabel:

 <bool式>

IFEQ    breaklabel1

 <loopBlock>

GOTO  continueLabelbreakLabel

生成バイトコード(予想)

IFEQ: スタックトップの値が0の場合にジャンプする命令

13年3月9日土曜日

Page 33: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

(おまけ)Bytecode DSL

32

@Bytecodeint  foo()  {        aload  0        invokedynamic  'experiment',  '(LMain;)I',  [H_INVOKESTATIC,  'Main',  'bootstrap',  [CallSite,  Lookup,  String,  MethodType]]        ireturn}

ASMより簡単にbytecodeが生成できるyo!参考URL

https://github.com/melix/groovy-bytecode-ast.git

http://www.jroller.com/melix/entry/using_groovy_to_play_with

13年3月9日土曜日

Page 34: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

まとめGroovyの実行のコアにはいわゆる一つのコンパイラがあるANTLR、ASMなどの既存ライブラリ・ツールを上手くつかって綺麗に制御している構文解析にしろコード生成にしろVisitorだらけである

3313年3月9日土曜日

Page 35: Read Groovy Compile process(Groovy Benkyoukai 2013)

Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.

参考URL・商標http://www.antlr.org/http://asm.ow2.org/OracleとJavaは、Oracle Corporation 及びその子会社、関連会社の米国及びその他の国における登録商標です。文中の社名、商品名等は各社の商標または登録商標である場合があります。記載されているロゴ、システム名、製品名は各社及び商標権者の登録商標あるいは商標です

3413年3月9日土曜日