2012-07-09 10 views
5

マクロを使って作業しているときに、私はある条件を保持するAST内のノードを更新する必要があるという点に挑戦してきました。たとえば、のは、私は、各ノードを更新したいとしましょう:不変のASTを更新する最も簡単な方法は何ですか?

Literal(Constant(1)) 

値で:

Literal(Constant(2)) 

これらのASTノードは、式ツリー内のどこにでも可能性があり、私はアドホックを使用することはできませんパターンマッチャー。明らかに、私がやりたい最後のことは、すべてのコンパイラプリミティブをカバーできるフルパターンマッチャーをコーディングすることです。私はAPIで検索していましたが、私はのようなメソッドがのトラバーシブルなファミリーを集めているという印象を持っています。ツリーを線形のものとして扱い、全体を更新したいからです。結果としてツリー。ですから、スマートな方法で不変式の式ツリーを更新することは可能ですか?なぜ標準APIにこのような「更新」操作が存在しないのですか?

+0

TreeTransformerがあります。私は、おそらく同じマクロでも同じようなものがなければならないと思います。 – pedrofurla

+0

おそらく、あなたは[zippers](http://anti-xml.org/zippers.html) –

+0

@ NikitaVolkovをチェックしたいと思うでしょう。もし彼がマクロの文脈で質問していなかったら、 – pedrofurla

答えて

3

いくつかがある。ここでScalaのマクロでASTの変圧器を使用する例です:プラグイン用

https://github.com/retronym/macrocosm/blob/171be7e/src/main/scala/com/github/retronym/macrocosm/Macrocosm.scala#L129

+0

私は本当にTransformerのソースコードを調べなければなりません。 XML変換ライブラリのように見え、そのライブラリはツリーの深さに指数関数的な性能を持っています。 –

+0

問題のワイルドショット:これはトップダウンとボトムアップトラバーサルに関連していますか?トップダウントラバーサルでは、葉を変更することは上記のツリーを再構築することを意味します。 上記のリンクの 'traceImpl'の実装は、新しいツリーがボトムアップ(少なくともそこに)構築されていることを示唆しています。しかし、一般的には、 'super.transform'をどのように呼び出すかによって異なります。 – Blaisorblade

2

データ型構造のポリタイプノードを一般的に変更するのは、データ型ジェネリックの古典的なケースです(型コンストラクタによるコードのパラメータ化)。

データタイプ汎用トラバーサル関数を定義する"Scrap Your Boilerplate"アプローチのような、このような操作にはいくつかのアプローチがあります。

Haskellで

、ノード更新機能は、二次元でパラメータ化される:データ型によって、およびコードによって - あなたはどこでも構造において、異なるタイプの異なる更新機能を適用することができるように:

-- | Apply a transformation everywhere in bottom-up manner 
everywhere :: (forall a. Data a => a -> a) 
      -> (forall a. Data a => a -> a) 

ようにすることHaskellは型クラスに大きく依存しています。 Scalaで、ported examples

関連する問題