5

クラス定義に適用することを意図したマクロ注釈があります。その目的は、ほぼシリアル化ツールですが、完全ではありません。クラスのコンストラクター パラメーターを調べてから、コンパニオン オブジェクトにファクトリ メソッドを作成し、パラメーターの値を提供します。これを行うには、パラメーターの型を知る必要があるため、それらに対して Context.typeCheck を呼び出しています。

この問題は、注釈付きクラスのコンストラクターがそれ自体と同じ型のパラメーターを取る場合、または他の同様の状況 (たとえば、型 A と型 B の両方に注釈が付けられ、A に B のパラメーターがあり、B にパラメーターがある場合) で発生します。仮パラメータに適用される型パラメータもカウントされます)。これらの状況では、StackOverflowError が発生するまで、アノテーションが再帰的に呼び出されます。

c.typeCheck の引数として「withMacrosDisabled=true」を使用してみました。これで問題は解決しますが、別の問題が発生します。チェックされている型が以前に見られなかった場合、コンパイラはその定義を覚えており、そのマクロはまったく呼び出されません。これは、自己参照の場合には問題になりませんが、相互参照の場合には発生します。

だから私は立ち往生しています。回避策はありますか? これを c.openMacros で解決できますか?

もう 1 つの選択肢として、型の完全な定義を厳密に必要としないというものがあります。完全修飾名 (NodeSeq ではなく scala.xml.NodeSeq) だけで十分です。AST で TypeName を取得しますが、これらが完全修飾されることはめったになく、完全な typeCheck を実行せずに完全修飾名を取得する方法がわかりません。

補足質問として、「withMacrosDisabled」は何に適していますか? それを使用すると、現在の c.typeCheck だけでなく、渡されたツリーで見つかった型ですべてのマクロ展開が永遠に防止される場合、それはハンマーが大きすぎるように思えます。そして、それが実際に必要な場合でも、実際には使用できません。マクロの評価は、型が独自のソースで検出される順序に依存するためです。

編集:考えてみると、コンパイラは各マクロが1回だけ展開されるようにする必要があると思います。循環の場合、私の例のように、関連するマクロの少なくとも 1 つが不完全に処理されたクラスを参照します。これは、事実上、循環依存であるため、このような場合には避けられないように思われます。結果の Type にフラグを付けて、マクロ処理が最終的なものではないことを示すのが最善の方法だと思いますが、それはおそらくパラダイスでは実行できません。

4

2 に答える 2

4

これは、マクロ注釈を処理しているときに親のメンバーにアクセスできないで開始された議論に非常に関連しているようです(そこの私の回答のより長い説明へのリンクも参照してください)。

可能であれば、混乱の可能性を減らすために、マクロが半分展開された型または半分入力された型を参照する状況を回避したいと考えています。先月、私はそれを回避する方法を考えてきましたが、優先度の高い気晴らしがいくつかあったため、まだ十分には進んでいません.

私が考えている 2 つの考えられるアイデアは次のとおりです。1) マクロ注釈の効果を指定する表記法を考え出すことで、プログラムを構成するクラスとメンバーを知るためにマクロを展開する必要がなくなります (うまくいけば)。 、次にマクロエンジンは最初にメンバーのリストを事前計算してからマクロ展開を起動できます)、2) 展開が正しく順序付けられるように、マクロがプログラム要素にどのように依存するかを指定するメカニズムを理解します。ちょうど昨日、Backstage Java と David Herman の型付き衛生マクロに関する研究についても学びました。これも関連があるはずです。これらの考え方についてどう思いますか?

その間、依存関係の問題に対する原則的な解決策を見つけようとしていますが、すぐに役立つ回避策または楽園へのパッチを提供することで、ユースケースのブロックを解除することにも関心があります. 修正を考えられるように、プロジェクトについて詳しく説明していただけますか?

于 2013-11-14T19:32:47.223 に答える