Swift にはランタイムにおける動的な振る舞いがほとんどありません。コード注入の実現方法や、AST を用いたアスペクト指向プログラミングについてお話します。
AST メタプログラミング
こんにちは、フリーランスでデベロッパーです。メタプログラミングの手法の話をしたいと思います。 メタプログラミングは興味深いと思います。
ASTとは、通常見られません。ですが開発ツールを通してみなさん利用していると思います。幾つか種類があります。違いを説明していきます。
ASTは抽象型シンタックスツリーのことです。プログラムの構造を表します。
Xcodeもリファクタリングのために使っています。 開発ツールの中でプロウグラマティックに扱うことを可能にしています
メトリクス分析は典型例です。
これらはSourceKitがつくるASTを利用して実現しています
ASTを入手する方法です
それぞれ違うものが入手できます
SourceKitで生成されたもの
外部ツールで使いやすいJSONフォーマット。
文字列表現をASTで、Swiftコンパイラに使われているASTを見ることができます。
こちらにはより多くの情報が含まれています。 このASTの一番大きな優位性はすべての型情報が解決された状態であるということです。メタプログラミングにはとても使われやすい。
しかしながらこのようなASTのパーサーはありません。
みなさん自身がパースする必要があります。
こちらは4.1から追加されました。libSyntaxで生成されています。元のソースコードのすべての情報が入っています。ホワイトスペースやブランク業まで入っています。 ASTからリストアできます。ソース変換、コードフォーマッターのようなものに有効です。
libSyntaxのラッパーでSwiftSyntaxが公開されています。
新しいノードを生成するAPIを提供しています。
比較表です
SourceKitは始めて使って見るには良いと思います。 SwiftSyntaxは二つ目にやりやすいです。でもまだ積極開発中で変わっていきますのでOSSで使っているところは殆どありません。-dumb-astが非常に強力ですが使うのはこんなんでしょう。
習うより慣れろ言うことで
使うツールを作ってみましょう
SwiftSourceCodeをHTMLシンタックスハイライトしてみましょう。
すべてのノードをVisitorPatternというのを使って辿っていくことができます。
どこを書き換えるかで変わってきます。今回はすべてのトークンを辿っていきたいと思います。
トークンシンタックスを使っていきます。Tokenというのはそれ以上分割できない、if, else, (), :などです。
ASTプログラミングの最初のステップとしては良さそうです。
ハイライトの目的は達成されました。しかしツリー構造はなくなってしまいました。
この問題を解決するためにより複雑なコードを書く必要があります。
visitpre, postで事前に処理をしたりできます。
作ってみたもののデモです
コードを書くと、サーバーに送られて、ハイライトされて帰ってきます。
次により実践的な例を紹介したいと思いますアスペクト指向プログラミングです。
ロギングとか。
ViweControllerにログのメソッドを付け加えるなど。
CodeblockSyntaxは{}で囲まれたところで呼ばれる
重複したコードが何度も挿入されないように、
変換されたASTを後続処理に直接渡せたら良いけど、それは今は無理なので
コード生成して、再ビルドする仕組みを作りました
アプリケーションを通常通り起動します。 PDFリーダーのようなアプリケーションを起動します。
outputがありません。printメソッドが入ったコードがないからですね。
ではアスペクト主導型のプログラミングで、お見せします。
viewXxxx系のfunctionからログが出力されるようになりました。
挿入されたコードはコンパイルが終わるとなくなります。
御覧頂いたようにアスペクト指向型プログラミングで元のコードを汚すことなく変更を加えることができます。
こちらはより高度な例になるでしょう
XCTAssertのコンディションを判定している箇所
デモです
幾つかのテストが失敗しています
なぜテストが失敗したのかわかりません。 SwiftPowerAssertを使います。
テストコマンドをラップしていきます。コード挿入して、コンパイルして、、、
なぜテストがFailしたのか分かるようになりました。値が理解できる形で表示されているからです。 オンラインでも展開されています。
どのようなコードでもエディタの中に書いていくことができます。
コードとサーバーサイドのSwiftのコード挿入、結果表示ができます
終わったらやってみて下さい。
つぎにSwiftFmt
空白の場所などルールをカスタマイズできる
ASTを使うとボイラープレートコードをなくすことができます。Swiftをダイナミックに利用できます。
興味を持っていただけたでしょうか。マニアックな趣味のような世界ではありますけれども、Swiftコミュニティにも役に立つものだと思います。
これらが有益なリソースですのでチェックしてみて下さい。
紹介したものはすべてGithubにあります
以上です、ご清聴ありがとうございました。