Инструктирование компилятора (механизм :meta)
Иногда может быть необходимо дать указание, что данный блок кода обладает особыми свойствами: вам может требоваться всегда встраивать его или включать специальные проходы оптимизации компилятора. Начиная с версии 0.4, в Julia существует соглашение о том, что эти инструкции могут быть размещены внутри выражения :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...)
добавляет :symbol
в конец выражения :meta
, создавая при необходимости новое выражение :meta
. Если указаны аргументы (args
), добавляется вложенное выражение, содержащее :symbol
и эти аргументы, которое можно использовать для указания дополнительной информации.
Чтобы использовать метаданные, необходимо проанализировать эти выражения :meta
. Если реализация может быть выполнена в Julia, довольно удобно использовать Base.popmeta!
. Base.popmeta!(body, :symbol)
сканирует выражение тела функции (без сигнатуры функции) на предмет первого выражения :meta
, содержащего :symbol
, извлечет все аргументы и возвратит кортеж (found::Bool, args::Array{Any})
. Если метаданные не содержат аргументы или :symbol
не был найден, массив args
будет пустым.
Эффективная инфраструктура для разбора выражений :meta
из C++ пока отсутствует.