motemote compiler plugin

43
モテモテコンパイラプラグイン

Upload: yoshiaki-iwanaga

Post on 26-May-2015

747 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: MoteMote Compiler Plugin

モテモテコンパイラプラグイン

Page 2: MoteMote Compiler Plugin

自己紹介● @kiris● アリエルの中の人● アリエルだと少数派なScalaユーザー

● 最近はCommon Lisperに押され気味

Page 3: MoteMote Compiler Plugin

発表の前に● 簡単な質問させてください

Page 4: MoteMote Compiler Plugin

発表の前に● 簡単な質問させてください

● ありえるえりあ勉強会の参加は何回目ですか?

Page 5: MoteMote Compiler Plugin

発表の前に● 簡単な質問させてください

● ありえるえりあ勉強会の参加は何回目ですか?● Scalaプログラムどれくらい書いてますか?

Page 6: MoteMote Compiler Plugin

発表の前に● 簡単な質問させてください

● ありえるえりあ勉強会の参加は何回目ですか?● Scalaプログラムどれくらい書いてますか?● コンパイラプラグインを書いたことはありますか?

Page 7: MoteMote Compiler Plugin

発表の前に● 簡単な質問させてください

● ありえるえりあ勉強会の参加は何回目ですか?● Scalaプログラムどれくらい書いてますか?● コンパイラプラグインを書いたことはありますか?

● コンパイラプラグインが書けるとモテそうだと思いませんか?

Page 8: MoteMote Compiler Plugin

今日の内容● コンパイラプラグインを書けるようになってモテモテになる● ゴール「この勉強会中で告白される」

● インスパイア モテモテPHP(WEB+DB PRESS)● 「PHP連載を通してモテを目指す」

という大変アグレッシブな企画● http://goo.gl/83fcw

Page 9: MoteMote Compiler Plugin

対象環境● Scala 2.9.0.fnal 以上● SBT 0.10.0 以上● 女子 18歳 以上

● 「スカラちゃん」という処理系があるので代用

Page 10: MoteMote Compiler Plugin

本題

Page 11: MoteMote Compiler Plugin

コンパイラプラグイン● コンパイル時に独自の処理(フェーズ)を追加で

きる

● 例えば● 型や文法以外のチェックを追加する● 構文木を変更する● .class以外のものを生成する● etc

● IDEやビルドツールへの依存が無いのも嬉しい

Page 12: MoteMote Compiler Plugin

簡単なデモ

Page 13: MoteMote Compiler Plugin

実用的そうなの● Alacs

● コンパイル時にバグになりそうな箇所を探す● ScalaCL

● コンパイル時にfor文の最適化● OpenCLによるGPUの利用

● Scala enhanced Strings● 文字列中に直接 Scala の式を書けるようにする● “Length: #{aString.length}.stuf”

Page 14: MoteMote Compiler Plugin

使い方● scalac -Xplugin:myplugin.jar Hello.scala

● $SCALA_HOME/misc/scala-devel/plugins にpluginのjarを追加するだけでも可

● scalac -Xplugin:myplugin.jar -Xplugin-list● プラグイン一覧の表示

Page 15: MoteMote Compiler Plugin

コンパイラの流れ

Page 16: MoteMote Compiler Plugin

Scalaのコンパイルの流れ● 全部で25+2フェーズ

● scalac -Xshow-phases

Page 17: MoteMote Compiler Plugin

構文木作成 1. parser

● parse source into ASTs, perform simple desugaring

● 余談だけどreaderの差し替えも可能らしい– scalac -Xsource-reader MyReader hoge.scala

Page 18: MoteMote Compiler Plugin

名前解決とか 2. namer

● resolve names, attach symbols to named trees 3. packageobjects 4. typer

● the meat and potatoes: type the trees 5. superaccessors 6. picker 7. refchecks

Page 19: MoteMote Compiler Plugin

構文木操作 8. selectiveanf

● 限定継続用コンパイラプラグイン 9. liftcode10. selectivecps

● 限定継続用コンパイラプラグイン11. uncurry12. tailcalls…20. mixin

Page 20: MoteMote Compiler Plugin

中間コード生成21. cleanup

● platform-specifc cleanups, generate refective calls

22. icode● generate portable intermediate code

Page 21: MoteMote Compiler Plugin

最適化23. inliner

● optimization: do inlining24. closelim

● optimization: eliminate uncalled closures25. dce

● optimization: eliminate dead code

Page 22: MoteMote Compiler Plugin

JVMコード生成・後処理26. jvm

● generate JVM bytecode27. terminal

● The last phase in the compiler chain

Page 23: MoteMote Compiler Plugin

コンパイラプラグインを使うと$ scalac -Xplugin:myplugin.jar -Xplugin-phases

1. parser 2. myplugin-phase <- 独自のフェーズを追加 3. namer 4. packageobjects 5. typer ...

Page 24: MoteMote Compiler Plugin

書いてみよう

Page 25: MoteMote Compiler Plugin

プロジェクト構成(SBT)● project_root/

● build.sbt● src/main

• scala● MyPlugin.scala● MyCompornent.scala

– resource● scalac-plugin.xml

● src/test...

Page 26: MoteMote Compiler Plugin

build.sbtname := "My Plugin"version := "1.0"organization := "localhost"scalaVersion := "2.9.0"libraryDependencies += "org.scala-lang" % "scala-compiler" % "2.9.0"

Page 27: MoteMote Compiler Plugin

scalac-plugin.xml<plugin> <name>myplugin</name> <classname>localhost.MyPlugin</classname></plugin>

Page 28: MoteMote Compiler Plugin

Pluginimport scala.tools.nsc.Globalimport scala.tools.nsc.plugins.Plugin

class MyPlugin(val global: Global) extends Plugin { override val name = "myplugin" override val description = "myplugin description" override val components = List(new MyComponent(global))}

Page 29: MoteMote Compiler Plugin

Component(1/2)import scala.tools.nsc._import scala.tools.nsc.plugins.PluginComponent

class MyComponent(val global: Global) extends PluginComponent { import global._ import global.defnitions._

val runsAfter = List("refchecks") val phaseName = "myplugin-phase"

… // Component(2/2)}

Page 30: MoteMote Compiler Plugin

Component(2/2)class MyComponent(val global: Global) extends PluginComponent { … // Component(1/2)

def newPhase(prev: Phase) = new StdPhase(prev) { def name = phaseName

override def apply(unit: CompilationUnit): Unit = { printf("Hello, motemote world.") } }}

Page 31: MoteMote Compiler Plugin

どのフェーズを使うべきか?● わりとケースバイケースですが● 構文木を操作するならparserやnamerの後● 値をチェックするならrefchecksの後

● などがよさそう

Page 32: MoteMote Compiler Plugin

参考:各プラグインのフェーズ● コンパイル時にチェックを追加するタイプ

● DivByZero(チュートリアル) / runAfter = refchecks● Var Hunter / runAfter = refchecks● WarnBoxingPlugin / runAfter = refchecks

● コンパイル時にコードを追加するタイプ● atuoproxy-plugin / runAfter = parser● Notnull-check generator / runAfter = parser● Scala enhanced Strings / runAfter = parser

● コンパイル時に別なコードを生成するタイプ● ScalaCL / runAfter = namer● s2js / runAfter = refchecks

Page 33: MoteMote Compiler Plugin

構文木を探索するclass MyComponent(val global: Global) extends PluginComponent { … def newPhase(prev: Phase): Phase = new StdPhase(prev) { override def apply(unit: CompilationUnit): Unit = { new ForeachTreeTraverser(onTraverse).traverse(unit.body) } } def onTraverse(tree: Tree): Unit = tree match { case Apply(fun, args) => println("traversing application of "+ fun) case _ => () }}

Page 34: MoteMote Compiler Plugin

別な構文木に変換するclass MyComponent(val global: Global) extends PluginComponent with Transform { def newTransformer(unit: CompilationUnit) = new MyTransformer class MyTransformer extends Transformer { override def transform(tree: Tree): Tree = { postTransform(super.transform(preTransform(tree))) }

def preTransform(tree: Tree): Tree = tree match { case _ => tree } def postTransform(tree: Tree): Tree = ....}

Page 35: MoteMote Compiler Plugin

構文木を調べる● プログラムの変換結果を表示

● scalac -Xprint:refchecks Hello.scala● シンタックスツリーの表示

● scalac -Xprint:refchecks -Yshow-trees Hello.scala● シンタックスツリーをGUIで表示

● scalac -Ybrowse:refchecks Hello.scala

Page 36: MoteMote Compiler Plugin

構文木の作成● case Apply(Select(Select(Select(Ident …

● やってらんない● MkTreeを使おう

● http://goo.gl/O3oeh

$ scala MkTree "if (b) 3 else 5"If( Ident("b") // sym=<none>, sym.tpe=<notype>, tpe=null Literal(Constant(3)) Literal(Constant(5)))

Page 37: MoteMote Compiler Plugin

完成したら● sbt package

● target/scala-2.x.x/myplugin_2.x.x-1.0.jar

● これで君もモテモテだ!m9(°д°)

Page 38: MoteMote Compiler Plugin

おまけ

Page 39: MoteMote Compiler Plugin

おまけ● 「モテモテになるコンパイラプラグイン」

が欲しいと言われて考えてみた

● loveletter plugin● コンパイルの待ち時間を使って愛の告白● コンパイルの各フェーズでメッセージを出力● 特定の相手にだけに出力されようにする

– java.net.InetAddress.getLocalHost()

Page 40: MoteMote Compiler Plugin

君に届けscalatan $ scalac -Xplugin:loveletter-plugin.jar src/test/scala/Hello.scala

Page 41: MoteMote Compiler Plugin

君に届けscalatan $ scalac -Xplugin:loveletter-plugin.jar src/test/scala/Hello.scalaスカラ!スカラ!スカラ!スカラぁぁあああわぁああああああああああああああああああああああん!!!あぁああああ…ああ…あっあっー!あぁああああああ!!!スカラスカラスカラぁああぁわぁああああ!!!あぁクンカクンカ!クンカクンカ!スーハースーハー!スーハースーハー!いい匂いだなぁ…くんくんんはぁっ!スカラ・オーダスキーたんの黒色の髪をクンカクンカしたいお!クンカクンカ!あぁあ!!間違えた!モフモフしたいお!モフモフ!モフモフ!髪髪モフモフ!カリカリモフモフ…きゅんきゅんきゅい!!型推論が大幅強化されたスカラたんかわいかったよぅ!!あぁぁああ…あああ…あっあぁああああ!!ふぁぁあああんんっ!!拡張可能リテラルScala3.0で決まって良かったねスカラたん!あぁあああああ!かわいい!スカラたん!かわいい!あっああぁああ!爆速コンパイルも新しいジェネリクスも発表されて嬉し…いやぁああああああ!!!にゃああああああああん!!ぎゃああああああああ!!ぐあああああああああああ!!!爆速コンパイルなんて現実じゃない!!!!あ…型推論の大幅強化も拡張可能リテラルもよく考えたら…ス カ ラ ち ゃ ん は 現実 じ ゃ な い?にゃあああああああああああああん!!うぁああああああああああ!!そんなぁああああああ!!いやぁぁぁあああああああああ!!はぁああああああん!!ローザンヌぅうううう!!この!ちきしょー!やめてやる!!現実なんかやめ…て…え!?見…てる?表紙絵のスカラちゃんが僕を見てる?表紙絵のスカラちゃんが僕を見てるぞ!スカラちゃんが僕を見てるぞ!挿絵のスカラちゃんが僕を見てるぞ!!拡張可能リテラルのスカラちゃんが僕に話しかけてるぞ!!!よかった…世の中まだまだ捨てたモンじゃないんだねっ!いやっほぉおおおおおおお!!!僕にはスカラちゃんがいる!!やったよマーティン!!ひとりでできるもん!!!あ、爆速コンパイルのスカラちゃああああああああああああああん!!いやぁあああああああああああああああ!!!!あっあんああっああんあビルぅう!!ジ、ジョナス!!リーナスぅうううううう!!!レックスぅううう!!ううっうぅうう!!俺の想いよスカラへ届け!!ローザンヌのスカラへ届け!

Page 42: MoteMote Compiler Plugin

ご静聴ありがとうございました

Page 43: MoteMote Compiler Plugin

告白タイム

質問も一応受けつけます