Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
Groovy基礎勉強会
Groovy実行の基礎~コンパイラ処理系としての
Groovyを読み解く~2013/3/9 @青山オラクルセンター
NTTソフトウェア Grails推進室 上原潤二
113年3月9日土曜日
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日土曜日
Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
お品書きGroovyの実行のしくみANTLRによる構文解析ASMによるコード生成まとめ
313年3月9日土曜日
Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.4
Groovy実行のしくみ
13年3月9日土曜日
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日土曜日
Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.6
JVM
Javaコードの実行Javaソース
.classファイル
javacコマンド
javaコマンド
標準クラスローダ
Javaクラス
13年3月9日土曜日
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日土曜日
Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
Groovyコードの実行
86
JVM
標準クラスローダ
Groovyコード
groovyコマンド
Groovyクラスローダ(オンメモリ実行時コンパイラ)
JavaクラスJavaクラス
.classファイル
groovycコマンド
13年3月9日土曜日
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日土曜日
Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
CompilationUnit
CompilationUnitはコンパイル処理の中核 「コンパイル処理を実行する単位」を表わすと同時にコンパイルのすべての過程を制御している。
10
org.codehaus.groovy.controll.CompilationUnit
13年3月9日土曜日
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日土曜日
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日土曜日
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日土曜日
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日土曜日
Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
GroovyConsoleのGroovy AST Browser
1513年3月9日土曜日
Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
フェイズにもとづいたコンパイル処理
CompilationUnitに、フェイズを指定して種々のphaseOperation(後述)を追加することで処理が制御されるCompilationUnit#addPhaseOperation()あらかじめ決まっているもの以外に、以下が実行時に追加されるAST変換CompilerCustomizerとしてのAST変換
1613年3月9日土曜日
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日土曜日
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日土曜日
今日のテーマ
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日土曜日
Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.19
ANTLRによる構文解析
13年3月9日土曜日
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日土曜日
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日土曜日
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日土曜日
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日土曜日
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日土曜日
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日土曜日
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日土曜日
Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.27
ASMによるコード生成
13年3月9日土曜日
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日土曜日
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日土曜日
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日土曜日
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日土曜日
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日土曜日
Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
まとめGroovyの実行のコアにはいわゆる一つのコンパイラがあるANTLR、ASMなどの既存ライブラリ・ツールを上手くつかって綺麗に制御している構文解析にしろコード生成にしろVisitorだらけである
3313年3月9日土曜日
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日土曜日