記事を読んだ: JavaScript Source Transformation: Non-Destructive vs Regenerative

Node.jsの非同期処理を同期っぽく書けるようにするasyncblockというモジュールのreadmeを読んでいて、
その中に Source Transformationという言葉が出てきたので、なんじゃこれとググって次の記事を参照した。

http://ariya.ofilabs.com/2013/06/javascript-source-transformation-non-destructive-vs-regenerative.html

英語力に乏しいため全訳とかは無理だけれど、なんとか意味はつかめたと思うので残しておく。

source transformationとは

JavaScript構文解析を行った後、その構文解析木に対して何か操作を行うことをSource Transformationと言う。(この時点で大分ギーク、、)
Source Transformationは、構文解析木へ操作する方法によって、Non-DestructiveとRegenerativeの2種類に分けられる。

Non-Destrucrive

例えば、ソースの" "でくくられている文字列をすべて' 'に直したいとき、変更したいのはそれだけで、それ以外のインデントやコメントや変数名などは全てそのままであってほしい。そのときは、構文解析木上の各ノードの位置+トークンの情報が必要になる??(原文ではwe use the location information of the syntax nodes and/or tokens to find out what needs to be tweaked と書いてあるんだけど、僕の英語力と(ソースの)構文解析に関する知識がないため、どこからどこまでandで比較されてて to find out..がどこにかかってるのか分からないorz)
※多分ですが、構文解析後のトークンの字句まで残して置く必要があるという意味だと思います。

Regenerative

元のソースの字句がどうだったかに興味がなければ、変数名やインデント等の情報は不要となるため、その辺気にする必要がない。その場合単にregenerateすれば良いから簡単とある。
(regenerateは構文解析木からソースを再生成することなんだと思うけど、Non-Destructiveでもソースの生成自体は必要だと思うのでその辺の違いは良く分からないので勉強してからまた。。)
例えば、ソースをminifyしたい時は、minify後は元のソースの構造だけ分かっていれば良く、変数名やインデント・スペース等は全て失われてしまってよい。
また、変換後にソースを出力する必要などなく、そのまま実行すればよいのであれば、なおさらである。
その例として、テストに使うIstanbulモジュールが挙げられている。

自分はIstanbulは使ったことがなかったが、shouldとexpectは使った事がある。
たとえばxが1であることをテストしたいとき、expectの方は

expect(x).equal(1)

と書く。これはexpect関数でxをラップしてExpectのオブジェクトを作っているわけだから、そのオブジェクトにequalメソッドが追加されていても何の不思議はない。
一方shouldの方は

x.should.equal(1)

と書く。これは普通の方法では達成できないはずだ。なぜならxはただのテストしたい値なのであって、shouldなんていうメンバを持っているわけはないからだ。したがって、source transformationの技術が必要である。この場合テストを実行したいだけで、変換後のソースを奇麗に保ったりする必要はないため、Regenerativeな方法でよいということになる。

2/20夜追記: 上の記述は間違えてました。Objectのプロトタイプにshouldを突っ込んでるという情報を頂きました。確かにそれで達成できますね…。全く気付きませんでした。
ソースを確認したところ確かにそうなっていました。lib/shoud.jsの107行目です。
なおnullやundefinedはObjectを継承しないため、xがnullのときはテストのエラーでなくjsの実行時エラーになります。

※一応expectの名誉のために追記すると、上の例では

expect(x).to.equal(1)

と、英語っぽく書くことができる。
Expectオブジェクトのtoは自分自身への参照ということだろうし、特に技術的な困難さはないと思う。

おわりに

ざっくりは理解したつもりだけど細かいところが分かっていないので、これから勉強していきます。
とりあえず、挙動を知っているshouldのソースから読んでいこうかと思います。興味もったきっかけのasyncblockを読むに変更。