モテモテコンパイラプラグイン
自己紹介●    @kiris●    アリエルの中の人●    アリエルだと少数派なScalaユーザー    ●        最近はCommon Lisperに押され気味
発表の前に●    簡単な質問させてください
発表の前に●    簡単な質問させてください    ●        ありえるえりあ勉強会の参加は何回目ですか?
発表の前に●    簡単な質問させてください    ●        ありえるえりあ勉強会の参加は何回目ですか?    ●        Scalaプログラムどれくらい書いてますか?
発表の前に●    簡単な質問させてください    ●        ありえるえりあ勉強会の参加は何回目ですか?    ●        Scalaプログラムどれくらい書いてますか?    ●        コンパイラプラグインを書いたことはあ...
発表の前に●    簡単な質問させてください    ●        ありえるえりあ勉強会の参加は何回目ですか?    ●        Scalaプログラムどれくらい書いてますか?    ●        コンパイラプラグインを書いたことはあ...
今日の内容●    コンパイラプラグインを書けるようになって    モテモテになる    ●        ゴール「この勉強会中で    告白される」●    インスパイア モテモテPHP(WEB+DB PRESS)    ●        「...
対象環境●    Scala 2.9.0.fnal 以上●    SBT 0.10.0 以上●    女子 18歳 以上    ●        「スカラちゃん」という処理系があるので代用
本題
コンパイラプラグイン●    コンパイル時に独自の処理(フェーズ)を追加で    きる●    例えば    ●        型や文法以外のチェックを追加する    ●        構文木を変更する    ●        .class以外...
簡単なデモ
実用的そうなの●    Alacs    ●        コンパイル時にバグになりそうな箇所を探す●    ScalaCL    ●        コンパイル時にfor文の最適化    ●        OpenCLによるGPUの利用●   ...
使い方●    scalac -Xplugin:myplugin.jar Hello.scala    ●        $SCALA_HOME/misc/scala-devel/plugins に        pluginのjarを追加する...
コンパイラの流れ
Scalaのコンパイルの流れ●    全部で25+2フェーズ    ●        scalac -Xshow-phases
構文木作成1. parser  ●      parse source into ASTs, perform simple      desugaring  ●      余談だけどreaderの差し替えも可能らしい      –   scal...
名前解決とか2. namer  ●      resolve names, attach symbols to named trees3. packageobjects4. typer  ●      the meat and potatoes...
構文木操作 8. selectiveanf   ●       限定継続用コンパイラプラグイン 9. liftcode10. selectivecps   ●       限定継続用コンパイラプラグイン11. uncurry12. tailca...
中間コード生成21. cleanup  ●      platform-specifc cleanups, generate refective      calls22. icode  ●      generate portable int...
最適化23. inliner   ●       optimization: do inlining24. closelim   ●       optimization: eliminate uncalled closures25. dce ...
JVMコード生成・後処理26. jvm  ●      generate JVM bytecode27. terminal  ●      The last phase in the compiler chain
コンパイラプラグインを使うと$ scalac -Xplugin:myplugin.jar -Xplugin-phases1. parser2. myplugin-phase <- 独自のフェーズを追加3. namer4. packageobje...
書いてみよう
プロジェクト構成(SBT)●    project_root/     ●          build.sbt     ●          src/main           • scala               ●        ...
build.sbtname := "My Plugin"version := "1.0"organization := "localhost"scalaVersion := "2.9.0"libraryDependencies += "org....
scalac-plugin.xml<plugin> <name>myplugin</name> <classname>localhost.MyPlugin</classname></plugin>
Pluginimport scala.tools.nsc.Globalimport scala.tools.nsc.plugins.Pluginclass MyPlugin(val global: Global) extends Plugin ...
Component(1/2)import scala.tools.nsc._import scala.tools.nsc.plugins.PluginComponentclass MyComponent(val global: Global) ...
Component(2/2)class MyComponent(val global: Global) extends PluginComponent {        … // Component(1/2)    def newPhase(p...
どのフェーズを使うべきか?●    わりとケースバイケースですが●   構文木を操作するならparserやnamerの後●   値をチェックするならrefchecksの後●    などがよさそう
参考:各プラグインのフェーズ●    コンパイル時にチェックを追加するタイプ    ●      DivByZero(チュートリアル) / runAfter = refchecks    ●      Var Hunter / runAfter...
構文木を探索するclass MyComponent(val global: Global) extends PluginComponent {        …        def newPhase(prev: Phase): Phase =...
別な構文木に変換するclass MyComponent(val global: Global) extends PluginComponent                                           with Tra...
構文木を調べる●    プログラムの変換結果を表示    ●        scalac -Xprint:refchecks Hello.scala●    シンタックスツリーの表示    ●        scalac -Xprint:ref...
構文木の作成●      case Apply(Select(Select(Select(Ident …      ●          やってらんない●      MkTreeを使おう      ●          http://goo.g...
完成したら●    sbt package    ●        target/scala-2.x.x/myplugin_2.x.x-1.0.jar●    これで君もモテモテだ!m9(°д°)
おまけ
おまけ●    「モテモテになるコンパイラプラグイン」    が欲しいと言われて考えてみた●    loveletter plugin    ●        コンパイルの待ち時間を使って愛の告白    ●        コンパイルの各フェーズ...
君に届けscalatan $ scalac -Xplugin:loveletter-plugin.jar src/test/scala/Hello.scala
君に届けscalatan $ scalac -Xplugin:loveletter-plugin.jar src/test/scala/Hello.scalaスカラ!スカラ!スカラ!スカラぁぁあああわぁあああああああああああああああああああああ...
ご静聴ありがとうございました
告白タイム        質問も一応受けつけます
Upcoming SlideShare
Loading in …5
×

MoteMote Compiler Plugin

1,128 views

Published on

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,128
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
2
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

MoteMote Compiler Plugin

  1. 1. モテモテコンパイラプラグイン
  2. 2. 自己紹介● @kiris● アリエルの中の人● アリエルだと少数派なScalaユーザー ● 最近はCommon Lisperに押され気味
  3. 3. 発表の前に● 簡単な質問させてください
  4. 4. 発表の前に● 簡単な質問させてください ● ありえるえりあ勉強会の参加は何回目ですか?
  5. 5. 発表の前に● 簡単な質問させてください ● ありえるえりあ勉強会の参加は何回目ですか? ● Scalaプログラムどれくらい書いてますか?
  6. 6. 発表の前に● 簡単な質問させてください ● ありえるえりあ勉強会の参加は何回目ですか? ● Scalaプログラムどれくらい書いてますか? ● コンパイラプラグインを書いたことはありますか?
  7. 7. 発表の前に● 簡単な質問させてください ● ありえるえりあ勉強会の参加は何回目ですか? ● Scalaプログラムどれくらい書いてますか? ● コンパイラプラグインを書いたことはありますか? ● コンパイラプラグインが書けると モテそうだと思いませんか?
  8. 8. 今日の内容● コンパイラプラグインを書けるようになって モテモテになる ● ゴール「この勉強会中で 告白される」● インスパイア モテモテPHP(WEB+DB PRESS) ● 「PHP連載を通して モテ を目指す」 という大変アグレッシブな企画 ● http://goo.gl/83fcw
  9. 9. 対象環境● Scala 2.9.0.fnal 以上● SBT 0.10.0 以上● 女子 18歳 以上 ● 「スカラちゃん」という処理系があるので代用
  10. 10. 本題
  11. 11. コンパイラプラグイン● コンパイル時に独自の処理(フェーズ)を追加で きる● 例えば ● 型や文法以外のチェックを追加する ● 構文木を変更する ● .class以外のものを生成する ● etc● IDEやビルドツールへの依存が無いのも嬉しい
  12. 12. 簡単なデモ
  13. 13. 実用的そうなの● Alacs ● コンパイル時にバグになりそうな箇所を探す● ScalaCL ● コンパイル時にfor文の最適化 ● OpenCLによるGPUの利用● Scala enhanced Strings ● 文字列中に直接 Scala の式を書けるようにする ● “Length: #{aString.length}.stuf”
  14. 14. 使い方● scalac -Xplugin:myplugin.jar Hello.scala ● $SCALA_HOME/misc/scala-devel/plugins に pluginのjarを追加するだけでも可● scalac -Xplugin:myplugin.jar -Xplugin-list ● プラグイン一覧の表示
  15. 15. コンパイラの流れ
  16. 16. Scalaのコンパイルの流れ● 全部で25+2フェーズ ● scalac -Xshow-phases
  17. 17. 構文木作成1. parser ● parse source into ASTs, perform simple desugaring ● 余談だけどreaderの差し替えも可能らしい – scalac -Xsource-reader MyReader hoge.scala
  18. 18. 名前解決とか2. namer ● resolve names, attach symbols to named trees3. packageobjects4. typer ● the meat and potatoes: type the trees5. superaccessors6. picker7. refchecks
  19. 19. 構文木操作 8. selectiveanf ● 限定継続用コンパイラプラグイン 9. liftcode10. selectivecps ● 限定継続用コンパイラプラグイン11. uncurry12. tailcalls…20. mixin
  20. 20. 中間コード生成21. cleanup ● platform-specifc cleanups, generate refective calls22. icode ● generate portable intermediate code
  21. 21. 最適化23. inliner ● optimization: do inlining24. closelim ● optimization: eliminate uncalled closures25. dce ● optimization: eliminate dead code
  22. 22. JVMコード生成・後処理26. jvm ● generate JVM bytecode27. terminal ● The last phase in the compiler chain
  23. 23. コンパイラプラグインを使うと$ scalac -Xplugin:myplugin.jar -Xplugin-phases1. parser2. myplugin-phase <- 独自のフェーズを追加3. namer4. packageobjects5. typer...
  24. 24. 書いてみよう
  25. 25. プロジェクト構成(SBT)● project_root/ ● build.sbt ● src/main • scala ● MyPlugin.scala ● MyCompornent.scala – resource ● scalac-plugin.xml ● src/test ...
  26. 26. build.sbtname := "My Plugin"version := "1.0"organization := "localhost"scalaVersion := "2.9.0"libraryDependencies += "org.scala-lang" % "scala-compiler" % "2.9.0"
  27. 27. scalac-plugin.xml<plugin> <name>myplugin</name> <classname>localhost.MyPlugin</classname></plugin>
  28. 28. Pluginimport scala.tools.nsc.Globalimport scala.tools.nsc.plugins.Pluginclass MyPlugin(val global: Global) extends Plugin { override val name = "myplugin" override val description = "myplugin description" override val components = List(new MyComponent(global))}
  29. 29. Component(1/2)import scala.tools.nsc._import scala.tools.nsc.plugins.PluginComponentclass MyComponent(val global: Global) extends PluginComponent { import global._ import global.defnitions._ val runsAfter = List("refchecks") val phaseName = "myplugin-phase" … // Component(2/2)}
  30. 30. 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.") } }}
  31. 31. どのフェーズを使うべきか?● わりとケースバイケースですが● 構文木を操作するならparserやnamerの後● 値をチェックするならrefchecksの後● などがよさそう
  32. 32. 参考:各プラグインのフェーズ● コンパイル時にチェックを追加するタイプ ● 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
  33. 33. 構文木を探索する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 _ => () }}
  34. 34. 別な構文木に変換する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 = ....}
  35. 35. 構文木を調べる● プログラムの変換結果を表示 ● scalac -Xprint:refchecks Hello.scala● シンタックスツリーの表示 ● scalac -Xprint:refchecks -Yshow-trees Hello.scala● シンタックスツリーをGUIで表示 ● scalac -Ybrowse:refchecks Hello.scala
  36. 36. 構文木の作成● 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)))
  37. 37. 完成したら● sbt package ● target/scala-2.x.x/myplugin_2.x.x-1.0.jar● これで君もモテモテだ!m9(°д°)
  38. 38. おまけ
  39. 39. おまけ● 「モテモテになるコンパイラプラグイン」 が欲しいと言われて考えてみた● loveletter plugin ● コンパイルの待ち時間を使って愛の告白 ● コンパイルの各フェーズでメッセージを出力 ● 特定の相手にだけに出力されようにする – java.net.InetAddress.getLocalHost()
  40. 40. 君に届けscalatan $ scalac -Xplugin:loveletter-plugin.jar src/test/scala/Hello.scala
  41. 41. 君に届けscalatan $ scalac -Xplugin:loveletter-plugin.jar src/test/scala/Hello.scalaスカラ!スカラ!スカラ!スカラぁぁあああわぁああああああああああああああああああああああん!!!あぁああああ…ああ…あっあっー!あぁああああああ!!!スカラスカラスカラぁああぁわぁああああ!!!あぁクンカクンカ!クンカクンカ!スーハースーハー!スーハースーハー!いい匂いだなぁ…くんくんんはぁっ!スカラ・オーダスキーたんの黒色の髪をクンカクンカしたいお!クンカクンカ!あぁあ!!間違えた!モフモフしたいお!モフモフ!モフモフ!髪髪モフモフ!カリカリモフモフ…きゅんきゅんきゅい!!型推論が大幅強化されたスカラたんかわいかったよぅ!!あぁぁああ…あああ…あっあぁああああ!!ふぁぁあああんんっ!!拡張可能リテラルScala3.0で決まって良かったねスカラたん!あぁあああああ!かわいい!スカラたん!かわいい!あっああぁああ!爆速コンパイルも新しいジェネリクスも発表されて嬉し…いやぁああああああ!!!にゃああああああああん!!ぎゃああああああああ!!ぐあああああああああああ!!!爆速コンパイルなんて現実じゃない!!!!あ…型推論の大幅強化も拡張可能リテラルもよく考えたら…ス カ ラち ゃ ん は 現実 じ ゃ な い?にゃあああああああああああああん!!うぁああああああああああ!!そんなぁああああああ!!いやぁぁぁあああああああああ!!はぁああああああん!!ローザンヌぅうううう!!この!ちきしょー!やめてやる!!現実なんかやめ…て…え!?見…てる?表紙絵のスカラちゃんが僕を見てる?表紙絵のスカラちゃんが僕を見てるぞ!スカラちゃんが僕を見てるぞ!挿絵のスカラちゃんが僕を見てるぞ!!拡張可能リテラルのスカラちゃんが僕に話しかけてるぞ!!!よかった…世の中まだまだ捨てたモンじゃ
  42. 42. ご静聴ありがとうございました
  43. 43. 告白タイム 質問も一応受けつけます

×