MoteMote Compiler Plugin
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

MoteMote Compiler Plugin

on

  • 898 views

 

Statistics

Views

Total Views
898
Views on SlideShare
897
Embed Views
1

Actions

Likes
1
Downloads
0
Comments
0

1 Embed 1

http://a0.twimg.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

MoteMote Compiler Plugin Presentation Transcript

  • 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 trees3. packageobjects4. typer ● the meat and potatoes: type the trees5. superaccessors6. picker7. refchecks
  • 19. 構文木操作 8. selectiveanf ● 限定継続用コンパイラプラグイン 9. liftcode10. selectivecps ● 限定継続用コンパイラプラグイン11. uncurry12. tailcalls…20. mixin
  • 20. 中間コード生成21. cleanup ● platform-specifc cleanups, generate refective calls22. icode ● generate portable intermediate code
  • 21. 最適化23. inliner ● optimization: do inlining24. closelim ● optimization: eliminate uncalled closures25. dce ● optimization: eliminate dead code
  • 22. JVMコード生成・後処理26. jvm ● generate JVM bytecode27. terminal ● The last phase in the compiler chain
  • 23. コンパイラプラグインを使うと$ scalac -Xplugin:myplugin.jar -Xplugin-phases1. parser2. myplugin-phase <- 独自のフェーズを追加3. namer4. packageobjects5. typer...
  • 24. 書いてみよう
  • 25. プロジェクト構成(SBT)● project_root/ ● build.sbt ● src/main • scala ● MyPlugin.scala ● MyCompornent.scala – resource ● scalac-plugin.xml ● src/test ...
  • 26. build.sbtname := "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. 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. 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. 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. 告白タイム 質問も一応受けつけます