jjug ccc 2017 fall オレオレjvm言語を作ってみる

88
オレオレJVM言語を 作ってみる (四則演算するだけだけど) 関西Javaエンジニアの会 / ポノス株式会社 阪田 浩一 @jyukutyo #ccc_c5

Upload: koichi-sakata

Post on 21-Jan-2018

651 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

オレオレJVM言語を作ってみる

(四則演算するだけだけど)

関西Javaエンジニアの会 /

ポノス株式会社

阪田浩一 @jyukutyo

#ccc_c5

Page 2: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

会長だけどじゅくちょー

阪田浩一 @jyukutyo

通称: じゅくちょー

関ジャバ会長

JVMが大好き

ポノス株式会社(スマホゲーム会社)

Page 3: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

CCCと僕

• JJUG CCC 5回目となりました

–2017 Fall

–2017 Spring

–2016 Fall

–2016 Spring

–2015 Spring

Page 4: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ハッシュタグ

#ccc_c5ガンガンツイートを

お願いします!!

Page 5: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

今日のゴール

JVMプログラミング言語

の作り方を持って帰る

Page 6: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

実装対象として

四則演算

Page 7: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

言語のデモ

Page 8: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

今日のソースコード

• https://github.com/jyukutyo/JVM-Math-Language

Page 9: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

構造の説明

Page 10: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

サンプル

(1 + 2) * 3

( 1 + 2 ) * 3

レキサー

パーサー

Page 11: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

サンプル

(1 + 2) * 3

( 1 + 2 ) * 3

テキスト

トークン

ツリー

Page 12: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

サンプル

(1 + 2) * 3

( 1 + 2 ) * 3

言語認識器

Page 13: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

サンプル

(1 + 2) * 3

( 1 + 2 ) * 3

ツリーをインタプリタに渡し、

定義した処理を実行させる

Page 14: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

モジュール 入力 出力

レキサー(字句解析)

テキスト(コード)

トークン

パーサー(構文解析)

トークン AST(抽象構文木)

ASTインタプリタ

AST 実行結果

構成

Page 15: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

モジュール ライブラリ

レキサー ANTLR 4.7

パーサー ANTLR 4.7

ASTインタプリタ Truffle 0.29

ライブラリの役割

Page 16: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ANTLR

Page 17: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ANTLR

Page 18: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ANTLR

• パーサージェネレータ– http://www.antlr.org/

Page 19: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ツリーを構築するために

“文法”を定義する

Page 20: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ANTLRがしてくれること

“文法”から

レキサー/パーサーの

コードを生成してくれる

Page 21: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

“文法”を定義する

方法は?

Page 22: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

BNF (EBNF)

(Extended)

Backus–Naur Form

Page 23: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

たとえば

ScalaのBNFは

Scalaの仕様にある

Page 24: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

The lexical syntax of Scala is given by the following grammar in EBNF form...Expr ::= (Bindings | [‘implicit’] id | ‘_’) ‘=>’ Expr| Expr1Expr1 ::= ‘if’ ‘(’ Expr ‘)’ {nl} Expr [[semi] else Expr]| ‘while’ ‘(’ Expr ‘)’ {nl} Expr| ‘try’ ‘{’ Block ‘}’ [‘catch’ ‘{’ CaseClauses ‘}’][‘finally’ Expr]| ‘do’ Expr [semi] ‘while’ ‘(’ Expr ’)’| ‘for’ (‘(’ Enumerators ‘)’ | ‘{’ Enumerators ‘}’){nl} [‘yield’] Expr| ‘throw’ Expr| ‘return’ [Expr]| [SimpleExpr ‘.’] id ‘=’ Expr| SimpleExpr1 ArgumentExprs ‘=’ Expr| PostfixExpr| PostfixExpr Ascription| PostfixExpr ‘match’ ‘{’ CaseClauses ‘}’…The Scala Language Specification Version 2.9http://www.scala-lang.org/docu/files/ScalaReference.pdf

Page 25: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

今回のBNF

Math.g4

表示します

Page 26: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ANTLRは

.g4ファイルから

レキサー/パーサーを

生成する

Page 27: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

$ antlr4 Math.g4

(このコマンドはANTLRのJARにあるToolクラスの実行)

Page 28: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

定義した文法を

テストできる

Page 29: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

$ antlr4 Math.g4

$ javac -cp antlr-4.7-

complete.jar Math*.java

$ grun Math prog –gui

(1 + 2) * 3

^D

Page 30: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ツリーとノードクラス

ProgContext

ExprContext

ExprContext ExprContext

NumberExprContextParensExprContext

NumberExprContext NumberExprContext

ExprContext ExprContextInfixExprContext

InfixExprContext

ExprContext

Page 31: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ただ、ANTLRの

ツリーのままでは

次のTruffleに

渡せない

Page 32: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ツリーの

移し替えをする

Page 33: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ANTLRは

tree walkingメカニズム

を提供している

Page 34: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

tree walk

enterExpr()ProgContext

ExprContext

ExprContext ExprContext

NumberExprContextParensExprContext

NumberExprContext NumberExprContext

ExprContext ExprContextInfixExprContext

InfixExprContext

ExprContext

exitExpr()

Page 35: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

リスナーを実装し、

ParseTreeWalkerに

渡すだけ

Page 36: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ParseTreeWalker

enterProg(ProgContext)

exitProg(ProgContext)

enterInfixExpr(InfixExprContext)

exitInfixExpr(InfixExprContext)

enterParensExpr(ParensExprContext)

exitParensExpr(ParensExprContext)

enterNumberExpr(NumberExprContext)exitNumberExpr(NumberExprContext)

Walker

リスナーのメソッド

Page 37: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

リスナーのベースクラスもコマンドで

自動生成されている

Page 38: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

MathBaseListener

表示します

Page 39: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

今回は各ルールから

exitするタイミングで

各ノードを移す

(詳細は後述)

Page 40: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

小まとめ

• BNFを定義し、ANTLRにパーサーを生成させた

• ANTLRのツリーをTruffleでのツリーに移し替えるため、リスナーを実装する

Page 41: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

よりANTLRを学ぶには

Page 42: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

モジュール ライブラリ

レキサー ANTLR 4.7

パーサー ANTLR 4.7

ASTインタプリタ Truffle 0.29

ライブラリの役割

Page 43: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

Truffle

Page 44: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

Truffle

Page 45: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

Truffle

• トラフル(トリュフ)

• 言語実装用フレームワーク– ASTインタプリタ構築の基盤を提供

• Graalプロジェクトの一部– Graal自体は新しいJITコンパイラ

– Graal/Truffleを含むGraalVMは多言語実行環境となるJVM(polyglot)

– Oracle Labs主導– https://github.com/graalvm/graal/tree/master/truffle

Page 46: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

Truffleでの多言語環境

HotSpot VM

JVMCI

Graal

JVM lang Truffle

LLVMJS R Ruby

C C++ Fortran

インタープリタ

Page 47: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

Truffleでの言語実装

• TruffleRuby (Ruby)– https://github.com/graalvm/truffleruby

• FastR (GNU R)– https://github.com/graalvm/fastr

• Graal.js (JavaScript)– ECMAScript 262 Version 6/Node.js

• SimpleLanguage (オレオレ言語)– https://github.com/graalvm/simplelanguage

– 学習用

Page 48: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

オレオレJVM言語の実装

HotSpot VM

JVMCI

Graal

JVM lang Truffle

オレオレJVM言語

インタープリタ

Page 49: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

(余談)Eclipse OMR

https://www.slideshare.net/MarkStoodley/javaone-2017-mark-stoodley-open-sourcing-ibm-j9-jvm

Page 50: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

(余談)Graal & Truffle

• Graalは言語実装そのものは知らない– Truffleを間に挟んでいる(JVM言語以外)

• JITコンパイルでは(結果として)複数言語にまたがったコンパイルができる

Page 51: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

call call

call many times

Page 52: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

プロファイリングし

ホットな部分を

JITコンパイル

Page 53: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

call call

Page 54: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

もちろん

必要に応じて

Deoptimization

する

Page 55: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

Truffleを使った言語

Graalは

必須ではなく

通常のHotSpotでも

動作はする(している)

Page 56: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

Truffleでの言語実装

1. Truffleでのノードクラスを実装

2. ANTLRのノードからこのノードに移し替えるANTLRのリスナを実装

3. Truffleでの言語実装に必須のクラスを実装

4. (入出力などの実装)

Page 57: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

Truffleでの言語実装

1. Truffleでのノードクラスを実装

2.

3.

4.

Page 58: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ノードクラス

• Truffle DSL APIを使う

–提供されるアノテーションを実装コードに付与する

–Truffleのアノテーションプロセッサがコードを生成する

–アノテーションの種類、意味はJavadocを読むしかない• ドキュメントは整備されていない

Page 59: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

今回のノード

• 数値ノード(子ノードなし)– Long– BigDecimal(これだけでもよかったがあえて2種類)

• 演算子ノード(子ノード:2つ)– Add(+)– Subtract(-)– Multiply(*)– Divide(/)

• 括弧ノード

今回は”-1”といった書き方はサポートしない

Page 60: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

演算子ノードのクラス図

Page 61: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ノードのクラス図

Page 62: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ノードのクラス図

かっこに対応するノード

Page 63: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

実際のコードを

表示します

Binary/Add/BigDecimal/JVMMathLang

Page 64: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

子ノードを持つノードの

処理は、

自動生成される

Page 65: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ノードのクラス図

Page 66: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

自動生成コードを

表示します

Page 67: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

Truffleでの言語実装

1.

2. ANTLRのノードからこのノードに移し替えるANTLRのリスナを実装

3.

4.

Page 68: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ANTLR Truffle

NumberExprLongNode(整数)

BigDecimalNode(それ以外)

InfixExpr

AddNodeGen(+)SubNodeGen(-)MulNodeGen(*)DivNodeGen(/)

ノードクラスの対応づけ

Page 69: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ParseTreeWalker

enterProg(ProgContext)

exitProg(ProgContext)

enterInfixExpr(InfixExprContext)

exitInfixExpr(InfixExprContext)

enterParensExpr(ParensExprContext)

exitParensExpr(ParensExprContext)

enterNumberExpr(NumberExprContext)exitNumberExpr(NumberExprContext)

Walker

リスナーのメソッド

Page 70: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

MathParseTreeListener

表示します

Page 71: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

Truffleでの言語実装

1.

2.

3. Truffleでの言語実装に必須のクラスを実装

4.

Page 72: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

com.oracle.truffle.api.

TruffleLanguage

を継承して実装する

Page 73: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

CallTarget parse(ParsingRequest r)

実装は1メソッドのみ

Page 74: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

CallTarget parse(ParsingRequest r)

Truffleのエンジンが

呼び出すメソッド

Page 75: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

CallTarget parse(ParsingRequest r)

コードをパースし、

AST表現を返す

メソッド

Page 76: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

クラス 説明

ParsingRequestgetSource().getInputStream()で実際のコードを取得する

CallTargetTruffle.getRuntime().createCallTarget(RootNode)で生成できる

CallTarget parse(ParsingRequest r)

Page 77: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

CallTarget parse(ParsingRequest r)

1. ParsingRequest#getSource() .getInputStream()でInputStreamを取得

2. IuputStreamをANTLRのレキサー/パーサーに渡す

3. ANTLRのツリーをリスナでTruffleのノードツリーに変換する

4. ルートノードを

Truffle.getRuntime() .createCallTarget(RootNode)に渡す

Page 78: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

JvmMathLang

表示します

Page 79: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

Truffleでの言語実装

1.

2.

3.

4. (入出力などの実装)

Page 80: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

最後

テキストを

Truffleのエンジンに

どのように渡し、

結果をどのように

受け取るか?

Page 81: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

PolyglotEngine#eval(Source)

すると

PolyglotEngine.Value

で結果が返ってくる

あとはValueからget()する

Page 82: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

JvmMathLangMain

表示します

Page 83: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

よりTruffleを学ぶには

• コードを読むしかありません

Page 84: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

そもそも阪田はどうやったのか?

https://www.youtube.com/watch?v=8Lt8au76emA

Page 85: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

このセッションのコード

は公開されていないので、

何度も見て、

見えないコードは

調べて書いて試した

Page 86: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

Devoxxセッションのコードも

• SimpleLanguage (オレオレ言語)– https://github.com/graalvm/simplelanguage

– 学習用

ベースだった

Page 87: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

まとめ

• ANTLR+TruffleであなたもJVM言語が作れる!

• https://github.com/jyukutyo/JVM-Math-Language

Page 88: JJUG CCC 2017 Fall オレオレJVM言語を作ってみる

ご清聴

ありがとうございました