コンパイラとの対話 (:meta を使った操作)

特定のコードブロックが特殊な意味を持つというヒントあるいは指令をコンパイラに与えたくなる状況が存在します。例えばコードを必ずインライン化したい場合や、特別なコンパイラ最適化パスを有効にしたい場合です。バージョン 0.4 以降の Julia では、こういった指令は :meta 式に配置するという慣習になっています。通常 :meta は関数本体の最初の式となります (が、そうでなくても構いません)。

:meta 式はマクロを使って作成します。例として @inline マクロの実装を考えます:

macro inline(ex)
    esc(isa(ex, Expr) ? pushmeta!(ex, :inline) : ex)
end

ここで ex には関数を定義する式が与えられると想定しています。このとき式

@inline function myfunction(x)
    x*(x+3)
end

は、次の式に変換されます:

quote
    function myfunction(x)
        Expr(:meta, :inline)
        x*(x+3)
    end
end

Base.pushmeta!(ex, :symbol, args...)ex 内の :meta 式の最後に :symbol を追加します (ex:meta 式を持たなければ新しく作成します)。args が与えられると、:symbol を先頭に持ち以降に引数を持つ式が追加されます。これは追加情報を指定するときに利用できます。

メタデータを使うには、追加した :meta 式をパースする必要があります。行いたい操作が Julia だけで実装できるときは Base.popmeta! を利用できます: Base.popmeta!(body, :symbol) は関数の body 式 (関数シグネチャを持たない式) をスキャンして :symbol を持つ最初の :meta 式を見つけ、引数を取り出し、タプル (found::Bool, args::Array{Any}) を返します。メタデータが引数を持たないときと :symbol が見つからなかったときは args は空になります。

C++ から :meta 式をパースする手軽なインフラはまだ提供されていません。

広告