Advertisement
Advertisement

More Related Content

Advertisement

MoteMote Compiler Plugin

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