Más contenido relacionado La actualidad más candente (20) Similar a Groovy kisobenkyoukai20130309 (20) Groovy kisobenkyoukai201303091. Groovy
基礎勉強会
Groovy実行の基礎
∼コンパイラ処理系としての
Groovyを読み解く∼
2013/3/9 @青山オラクルセンター
NTTソフトウェア Grails推進室 上原潤二
Slide # 1 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
2. 自己紹介
上原潤二(@uehaj)
NTTソフトウェア株式会社Grails推進室
JGGUG(日本Grails/Groovyユーザグループ)運営委員
書籍執筆:
プログラミングGROOVY(技術評論社)
Grails徹底入門(翔泳社)
G*Magazine Vol 6記事書きました →
ブログ「Grな日々」
GroovyServ, LispBuilder,
GVM(Groovy JVM),
Staticalizer開発者
Slide # Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
3. お品書き
Groovyの実行のしくみ
ANTLRによる構文解析
ASMによるコード生成
まとめ
Slide # 3 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
4. Groovy実行
のしくみ
Slide # 4 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
5. Groovyソースツリー
src/main │ ├─builder │ ├─typehandling
├─groovy │ ├─expr │ └─wrappers
│ ├─beans │ ├─stmt ├─syntax
│ ├─grape │ └─tools ├─tools
│ ├─inspect 今日の ├─classgen │ ├─ast
│ ├─io │ └─asm │ ├─gse
│ ├─lang テーマ │ ├─indy │ ├─javac
│ ├─security │ └─sc │ ├─shell
│ ├─time ├─cli │ │ └─util
│ ├─transform ├─control │ └─xml
│ ├─ui │ ├─customizers ├─transform
│ ├─util │ │ └─builder │ ├─sc
│ │ └─logging │ ├─io │ │ └─transformers
│ └─xml │ └─messages │ └─stc
└─org ├─plugin ├─util
├─apache ├─reflection └─vmplugin
│ └─commons │ └─stdclasses ├─v5
│ └─cli ├─runtime ├─v6
└─codehaus │ ├─callsite └─v7
└─groovy │ ├─dgmimpl
├─antlr │ │ └─arrays
│ ├─java │ ├─m12n
│ ├─parser │ ├─memoize
│ └─treewalker │ ├─metaclass
├─ast │ ├─powerassert
Slide # 5 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
6. Javaコードの実行
Javaソース
javacコマンド
.classファイル
javaコマンド
JVM
標準クラスローダ
Javaクラス
Slide # 6 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
7. Groovyコードの実行
Javaソース Groovyコード
javacコマンド groovycコマンド
.classファイル .classファイル
javaコマンド groovyコマンド
JVM
Groovyクラスローダ
標準クラスローダ (オンメモリ実行時コンパイラ)
Javaクラス Javaクラス Javaクラス
Slide # 7 Groovy基礎勉強会 2011
Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
8. Groovyコードの実行
Groovyコード
groovycコマンド
.classファイル
groovyコマンド
JVM
標準クラスローダ Groovyクラスローダ
(オンメモリ実行時コンパイラ)
Javaクラス Javaクラス
Slide # 8
6 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
9. Groovyコード実行のためのコマンドとクラス
groovycコマンド groovyコマンド groovysh
groovy.ui.GroovyMain
o.c.g.tools.FileS groovyConsole
ystemCompiler groovy.lang.GroovyShell
groovy.util.Groo
vyScriptEngine
groovy.lang.GroovyClass
Loader
org.codehaus.groovy.controll.CompilationUnit
Slide # 9 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
10. CompilationUnit
org.codehaus.groovy.controll.CompilationUnit
CompilationUnitはコンパイル処理の中核
「コンパイル処理を実行する単位」を表わすと同時
にコンパイルのすべての過程を制御している。
Slide # 10 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
11. JavaAwareCompilationUnit extends CompilationUnit
(余談)JavaAwareCompilationUnit
extends CompilationUnit
ジョイントコンパイルオプション(-j,
--jointCompilation)を指定した場合に発動
Groovyソースに加えJavaソースをコンパイル
する能力を持つ
-jをつけないと、拡張子.javaのファイルは
Groovyコードとして解釈/コンパイルされる(!!)
Slide # 11 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
12. CompilationUnit#compile()
public
void
compile()
..
{
compile(Phases.ALL);
//全フェイズのコンパ
イル処理を実行
}
public
void
compile(int
throughPhase)
..
{
//
指定したフェイズ「まで」コンパイル処理実行
:
}
Slide # 12 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
13. フェイズとは何か?
CompilationUnitが保持するコンパイルの進行
状態である。
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)
//後始末まですべて実行
Slide # 13 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
14. (参考) ASTとは?
AST…Abstract Syntax Tree,抽象構文木
構文木の一種で、論理的な構造を表わす
CST(Concrete Syntax Tree, 具象構文木)
例えば「a.foo(b,c)」を構文解析すると…
CST . AST
.
a foo
a foo
()
, b c
b c
Slide # 14 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
16. フェイズにもとづいたコンパイル処理
CompilationUnitに、フェイズを指定して種々
のphaseOperation(後述)を追加することで処
理が制御される
CompilationUnit#addPhaseOperation()
あらかじめ決まっているもの以外に、以下が実
行時に追加される
AST変換
CompilerCustomizerとしてのAST変換
Slide # 16 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
17. (参考)フェイズとAST変換
AST変換は、それぞれ適用されるフェイズを
指定して定義されている
フェイズ 実行されるAST変換
INITIALIZATION -
PARSING -
CONVERSION @Grab
SEMANTIC_ANALYSIS @Field, @Log, @PackageScope,
CANONICALIZATION ほとんどのAST変換がここに所属
INSTRUCTION_SELECTIO @TypeChecked, @CompileStatic
CategoryASTTransformation
CLASS_GENERATION
N -
DelegateASTTransformation
OUTPUT -
FINALIZATION -
ImmutableASTTransformation
Slide # 17 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
18. phaseOperations
PARSING: AnnotationCollectorTransform
SourceUnit#parse() StaticVerifier
AntlrParserPlugin#parseCST()// InnerClassCompletionVisitor
CSTを作る EnumCompletionVisitor
CONVERSION: CANONICALIZATION:
convert(SourceUnit#convert() // compileCompleteCheck
Generates an AST from the CST), CLASS_GENERATION:
AntlrParserPlugin.buildAST()//
classgen(OptimizerVisitor,Generics
ANTLR ASTからGroovyのASTを生成
Visitor, LabelVerifier,
EnumVisitor ClassCompletionVerifier,
SEMANTIC_ANALYSIS: ExtendedVerifier, ClassVisitor,
resolve(VariableScopeVisitor, AsmClassGenerator)
ResolveVisitor) OUTPUT:
staticImport(StaticImportVisitor) output
InnerClassVisitor
Slide # 18 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
19. phaseOperations
PARSING: AnnotationCollectorTransform
SourceUnit#parse() StaticVerifier
AntlrParserPlugin#parseCST()// InnerClassCompletionVisitor
CSTを作る EnumCompletionVisitor
CONVERSION: CANONICALIZATION:
convert(SourceUnit#convert() // compileCompleteCheck
Generates an AST from the CST), CLASS_GENERATION:
AntlrParserPlugin.buildAST()//
classgen(OptimizerVisitor,Generics
ANTLR ASTからGroovyのASTを生成
Visitor, LabelVerifier,
EnumVisitor ClassCompletionVerifier,
SEMANTIC_ANALYSIS: 今日の ExtendedVerifier, ClassVisitor,
resolve(VariableScopeVisitor, AsmClassGenerator)
ResolveVisitor)
テーマ OUTPUT:
staticImport(StaticImportVisitor) output
InnerClassVisitor
Slide # 18 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
20. ANTLRによる
構文解析
Slide # 19 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
21. ANTLRによる構文解析処理
ANTLRって何?
Wikipediaより
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に似た形式となっている。
再帰下降構文解析のコードを自動生成する
Groovy 2.1が使っているのはANTLR 2.7.7
3もしくは4への移行も企画されているらしい
Slide # 20 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
22. AntlrParserPlugin.java
パーサ(構文解析器)のメイン処理
parseCST() …以下を呼び出してCSTを作った上
で、ANTLRのASTに変換
o.c.g.antlr.parser.GroovyLexer
o.c.g.antlr.parser.GroovyRecognizer
buildAST() …ANTLRのASTをGroovyのASTに変換
Slide # 21 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
23. GroovyLexer.java, GroovyRecognizer.java
groovy.gから自動生成されるのでGroovyソー
スコードには含まれていない
Groovyソースコードをコンパイルすると
target/generated-sources配下にJavaソース
が生成される。
groovy.g GroovyLexer.java
(Groovy構文定義) ANTLR
GroovyRecognizer.java
Slide # 22 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
24. groovy.g
ANTLR 2.7用のGroovy構文定義ファイル
4324行あり、groovy中の最大級ソースの一つ
./src/main/org/codehaus/groovy/runtime/ 14239行
DefaultGroovyMethods.java
./src/main/org/codehaus/groovy/antlr/ 4323行
groovy.g
./subprojects/groovy-sql/src/main/java/groovy/sql/ 4229行
Sql.java
./src/main/org/codehaus/groovy/runtime/ 3865行
StringGroovyMethods.java
Slide # 23 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
25. groovy.gを覗いてみる
ANTLRによるCompilationUnitの定義
//
Compilation
Unit:
Groovyでは単一ファイルもしくはスクリプト。
//
このパーサの開始ルールです。
compilationUnit
:
//
ファイル冒頭文字列が"#!"の場合最初の行を無視
(SH_COMMENT!)?
//
ファイル冒頭にコメントがあっても良い
nls!
//
compilation
unitはopitionalなパッケージ定義から開始される
(
(annotationsOpt
"package")=>
packageDefinition
|
(statement[EOF])?
)
//
スクリプト本体は任意個数の文のシーケンス。
//
セミコロンand/or改行をセパレータとして扱う
(
sep!
(statement[sepToken])?
)*
EOF!
;
Slide # 24 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
26. do-whileはどうなっている?
/*OBS*
no
do-‐while
statement
in
Groovy
(too
ambiguous)
//
do-‐while
statement
|
"do"^
statement
"while"!
LPAREN!
strictContextExpression
RPAREN!
SEMI!
*OBS*/
Slide # 25 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
27. (余談)AntlrPerserPluginを
CompilerlerConfigrationで差し替える
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
arg
end
foo("hello
pascal!")
""")
Slide # 26 Groovy基礎勉強会 参考: http://groovyconsole.appspot.com/script/3
Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
28. ASMによる
コード生成
Slide # 27 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
29. ASMって何?
Wikipediaより
ObjectWeb ASM
The 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.).
Groovy 2.1が使っているのはASM 4.0
Slide # 28 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
30. CompilatoinUnit#classgen
CLASS_GENERATIONフェイズのphaseOperation
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フェーズでバイトコード列を出力する
Slide # 29 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
31. AsmClassGenerator
以下を定義するVisitor visitSynchronizedStatement()
visitClass() visitThrowStatement()
visitClass() visitReturnStatement()
visitGenericType() visitExpressionStatement()
visitConstructor() visitTernaryExpression()
visitMethod() visitDeclarationExpression()
visitField() visitBinaryExpression()
visitProperty() visitPostfixExpression()
visitCatchStatement() visitPrefixExpression()
visitBlockStatement() visitClosureExpression()
visitForLoop() visitConstantExpression()
visitWhileLoop() visitSpreadExpression()
visitDoWhileLoop() visitSpreadMapExpression()
visitIfElse() visitMethodPointerExpression()
visitAssertStatement() visitUnaryMinusExpression()
visitTryCatchFinally() visitUnaryPlusExpression()
visitSwitch() visitBitwiseNegationExpression()
visitCaseStatement() visitCastExpression()
visitBreakStatement() visitNotExpression()
visitContinueStatement() (以下略)
Slide # 30 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
32. コード生成の例(whileループ)
public
void
visitWhileLoop(WhileStatement
loop)
{
controller.getStatementWriter().writeWhileLoop(loop);
}
StatementWriter#writeWhileLoop(WhileStatement loop):
生成バイトコード(予想)
mv.visitLabel(continueLabel)
continueLabel:
Expression
bool
=
loop.getBooleanExpression();
bool.visit(controller.getAcg());
<bool式>
controller.getOperandStack().jump(IFEQ, IFEQ
breaklabel1
breakLabel);
<loopBlock>
loop.getLoopBlock().visit(controller.getAcg());
GOTO
continueLabel
breakLabel
mv.visitJumpInsn(GOTO,
continueLabel);
mv.visitLabel(breakLabel);
IFEQ: スタックトップの値が0の場合にジャンプする命令
Slide # 31 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
33. (おまけ)Bytecode DSL
@Bytecode
int
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
Slide # 32 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
34. まとめ
Groovyの実行のコアにはいわゆる一つのコン
パイラがある
ANTLR、ASMなどの既存ライブラリ・ツール
を上手くつかって綺麗に制御している
構文解析にしろコード生成にしろVisitorだらけ
である
Slide # 33 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日
35. 参考URL・商標
http://www.antlr.org/
http://asm.ow2.org/
OracleとJavaは、Oracle Corporation 及びその子会社、関連会社の米国及びその他の国
における登録商標です。文中の社名、商品名等は各社の商標または登録商標である場合
があります。
記載されているロゴ、システム名、製品名は各社及び商標権者の登録商標あるいは商標
です
Slide # 34 Groovy基礎勉強会 Copyright(C) 2013 NTT Software Corporation All rights reserved.
13年3月9日土曜日