Node.jsの抽象構文木を操作してソースコードを生成する

ソースコード生成してみたい!けど、そういや1年くらい前にASTって言葉を知ってから何もしてなかったな」、と思ってASTを書いてそいつを食わせてソースを生成してみた。

もともとはさいきょうのスタブサーバーを作りたいねって話から始まったからそういう感じのリポジトリ名の以下リポジトリに実際に今夜書いたコードが乗っかってる。

github.com

構文木ってなに?

プログラムの構造を、(Javascriptの場合)JSON形式にパースしたもの。 何段階かに分かれているっぽい。

詳しくは以下のブログエントリーで。詳しい記事ありがとうございます。

efcl.info

どうやってASTを生成するの?

ASTの仕様を知ってそれを満たすJSONを構築すれば、それをASTからソースに変換するライブラリに食わせればコード生成できる。 ソースコード ⇔ ASTのライブラリはJS界にいくつかあるみたいで、今回はEsprimaを使うことにした。 Babelもトランスパイラー?だから同じような機構を持ってるみたいだけど、特に理由なくEsprimaにした。

JavascriptのASTの構造はestreeという標準があるらしい。

github.com

けど、それを読むより実際にソースコードから生成されるASTを見たほうが早いなってことで以下で試す。

http://esprima.org/demo/parse.html

こいつに

let express = require('express');

みたいなのを食わせると

{
    "type": "Program",
    "body": [
        {
            "type": "VariableDeclaration",
            "declarations": [
                {
                    "type": "VariableDeclarator",
                    "id": {
                        "type": "Identifier",
                        "name": "express"
                    },
                    "init": {
                        "type": "CallExpression",
                        "callee": {
                            "type": "Identifier",
                            "name": "require"
                        },
                        "arguments": [
                            {
                                "type": "Literal",
                                "value": "express",
                                "raw": "'express'"
                            }
                        ]
                    }
                }
            ],
            "kind": "let"
        }
    ],
    "sourceType": "script"
}

みたいな木構造にバラしてくれる。 逆にこいつを、対応したコード生成機に食わせればソースコードが生成されるってわけよ。

github.com

これを使えば、カッコとかカンマとかシングルクォートとか改行とか気にせずに、オブジェクトをガツガツ組み立てていけば思うままのソースを生成できる。

これを世に出してGithubのStarを稼ぐんだ、という野望を胸に書くコードは、心なしかいつもよりギラギラして見えた。