2017-10-31 6 views
2

Crystalプロジェクトが異なるシャードを使用しているとします。そして、各シャードは、プロジェクト全体の編集の最後にクリーンアップを行いたいと思っています。マクロを使用することは可能ですか?例えば、このようなコンパイルの最後に実行する命令を定義することはできますか? (Crystal lang)

何か:あなたは複数のマクロの間でデータを共有する必要がある場合

{% at_end %} 
    {% system("rm 'tmp files'") %} 
{% end %} 
+0

これについての特定の用途を説明できますか? –

+1

@JohannesMüllerマクロ間でデータを共有する必要があることがあります。だから私はそれらを一時ファイルに書きます。私がしなければ、私はヒープメモリを使用し、ブロック/ Procsケマルがそれを行う方法をキャプチャする必要があります。もし私が一時的なものを削除することができれば、それはもっと良いものになるでしょう。コンパイル後のファイル –

+0

おもしろいアイデア...しかし、一時ファイルがヒープ割り当てよりもパフォーマンスが良いと考える理由は何ですか? :D –

答えて

0

、あなたがHashArrayを使用して、関連するASTノードは、マクロからアクセス可能であるConstantを介してそれらにアクセスすることができます。ここで重要な部分

STORAGE = [] of _ 

macro add(node) 
    {% STORAGE << node %} 
end 

macro list 
    {% for elem in STORAGE %} 
    {% puts "Elem: #{elem}" %} 
    {% end %} 
end 

add 1 
add 2 
add "hello" 
add :world 
add({a: 1, b: 2}) 
add 3 + 4 
add a_call(arg1, 2) 

list 

である:ここで

はこれを実証する例(https://carc.in/#/r/372kでのライブ)です

ここ
STORAGE = [] of _ 

私がある(特定の型の配列を宣言していますこの場合は関連しません。配列はマクロを介してのみアクセスされるため、通常のコードではこのタイプ(_)を使用できません。マクロシステムは、それが配列であることだけを知る必要があります。

macro add(node) 
    {% STORAGE << node %} 
end 

次に、アレイASTノード(マクロシステムのArrayLiteral型)を変更できるマクロを作成します。 NumberLiteralSymbolLiteralのような単純なノードからCallDef、さらにはClassDefのような複雑なノードに、あらゆる種類のASTノードを格納できることに注意してください。

macro list 
    {% for elem in STORAGE %} 
    {% puts "Elem: #{elem}" %} 
    {% end %} 
end 

そして最後に、私は単純に(コンパイル時に)STORAGE配列の内容を印刷しますマクロを作成します。

同じことがHashLiteralで行うことができます。

と同じように、あなたがキーまたは値としてASTノードのいずれかの種類を使用することができ、上述したように。あなたがマクロシステムで使用Constantsも通常のコードで見ることができ、それが名前の衝突を持つことが可能だということ


注意(ユーザーが自分自身のコードのためにあまりにも一定のSTORAGEを使用することを望んでいますか?) 。 MyShard::MacroStorage::SomeInterestingNodesのような特別なモジュールに定数を入れたり、M____ACRO_Storage____のような複雑な命名パターンを使用することをお勧めします(< - これはユーザーが使用することはほとんどありません))

+0

うわー。マクロで '[] of _'を使うことは決して考えなかったでしょう。あなたはどうやってそれについて知りましたか? (この回答に感謝します) –

+0

他のコード、コンパイラのコードを読んで、言語の端を試してみてください:D – bew

関連する問題