Spec-Zone.ru › OCaml 5.0

12.12 Атрибуты

  • 12.12.1 Встроенные атрибуты

(Введены в OCaml 4.02, инфиксные обозначения для конструкций, отличных от выражений, добавлены в 4.03)

Атрибуты — это «декорации» синтаксического дерева, которые в основном игнорируются проверяющим типов, но могут использоваться внешними инструментами. Атрибут состоит из идентификатора и полезной нагрузки, которая может быть структурой, выражением типа (префикс :), сигнатурой (префикс :) или шаблоном (префикс ?), необязательно с последующей частью when:

attr-id ::= lowercase-ident
∣ capitalized-ident
∣ attr-id . attr-id
attr-payload ::= [ module-items ]
∣ : typexpr
∣ : [ specification ]
∣ ? pattern [when expr]

Первый вид атрибутов добавляется с постфиксной записью к «алгебраическим» категориям:

attribute ::= [@ attr-id attr-payload ]
expr ::= ...
∣ expr attribute

Этот вид атрибутов также можно вставить после `tag-name в выражениях типов полиморфных вариантов (tag-spec-first, tag-spec, tag-spec-full) или после method-name в method-type.

Та же синтаксическая форма также используется для добавления атрибутов к меткам и конструкторам в объявлениях типов:

field-decl ::= [mutable] field-name : poly-typexpr { attribute }
constr-decl ::= (constr-name ∣ ()) [ of constr-args ] { attribute }

Примечание: если за объявлением метки следует точка с запятой, атрибуты также можно разместить после точки с запятой (в этом случае они объединяются с теми, что указаны ранее).

Второй вид атрибутов прикрепляется к «блокам», таким как объявления типов, поля классов и т. д.:

item-attribute ::= [@@ attr-id attr-payload ]
typedef ::= ...
∣ typedef item-attribute
exception-definition ::= exception constr-decl
∣ exception constr-name = constr
module-items ::= [;;] ( definition ∣ expr { item-attribute } ) { [;;] definition ∣ ;; expr { item-attribute } } [;;]
class-binding ::= ...
∣ class-binding item-attribute
class-spec ::= ...
∣ class-spec item-attribute
classtype-def ::= ...
∣ classtype-def item-attribute
definition ::= let [rec] let-binding { and let-binding }
∣ external value-name : typexpr = external-declaration { item-attribute }
∣ type-definition
∣ exception-definition { item-attribute }
∣ class-definition
∣ classtype-definition
∣ module module-name { ( module-name : module-type ) } [ : module-type ] = module-expr { item-attribute }
∣ module type modtype-name = module-type { item-attribute }
∣ open module-path { item-attribute }
∣ include module-expr { item-attribute }
∣ module rec module-name : module-type = module-expr { item-attribute } { and module-name : module-type = module-expr { item-attribute } }
specification ::= val value-name : typexpr { item-attribute }
∣ external value-name : typexpr = external-declaration { item-attribute }
∣ type-definition
∣ exception constr-decl { item-attribute }
∣ class-specification
∣ classtype-definition
∣ module module-name : module-type { item-attribute }
∣ модуль module-name { ( module-name : module-type ) } : module-type { item-attribute }
∣ модуль тип modtype-name { item-attribute }
∣ модуль тип modtype-name = module-type { item-attribute }
∣ открытый module-path { item-attribute }
∣ включить module-type { item-attribute }
класс-поле-спец ::= ...
∣ класс-поле-спец item-attribute
класс-поле ::= ...
∣ класс-поле item-attribute

Третья форма атрибутов появляется как самостоятельные структуры или элементы сигнатуры в модулях или классах. Они не прикреплены к какому-либо узлу в синтаксическом дереве:

плавающий-атрибут ::= [@@@ attr-id attr-payload ]
определение ::= ...
∣ плавающий-атрибут
спецификация ::= ...
∣ плавающий-атрибут
класс-поле-спец ::= ...
∣ плавающий-атрибут
класс-поле ::= ...
∣ плавающий-атрибут

(Примечание: вопреки тому, что описывает грамматика выше, item-attributes не могут быть присоединены к этим плавающим атрибутам в класс-поле-спец и класс-поле.)

Также можно указать атрибуты, используя инфиксную синтаксис. Например:

let[@foo] x = 2 in x + 1          === (let x = 2 [@@foo] in x + 1)
begin[@foo][@bar x] ... end       === (begin ... end)[@foo][@bar x]
module[@foo] M = ...              === module M = ... [@@foo]
type[@foo] t = T                  === type t = T [@@foo]
method[@foo] m = ...              === method m = ... [@@foo]

Для let, атрибуты применяются к каждой привязке:

let[@foo] x = 2 and y = 3 in x + y === (let x = 2 [@@foo] and y = 3 in x + y)
let[@foo] x = 2
and[@bar] y = 3 in x + y           === (let x = 2 [@@foo] and y = 3 [@@bar] in x + y)

12.12.1 Встроенные атрибуты

Некоторые атрибуты понимаются проверкой типов:

  • “ocaml.warning” или “warning”, со строковым значением. Это можно использовать как плавающие атрибуты в сигнатуре/структуре/объекте/типе объекта. Строка анализируется и имеет тот же эффект, что и командная опция -w, в области между атрибутом и концом текущей сигнатуры/структуры/объекта/типа объекта. Атрибут также может быть прикреплен к любому типу синтаксического элемента, который поддерживает атрибуты (такому как выражение или выражение типа), в этом случае его область действия ограничена этим элементом. Обратите внимание, что не определено, какая область действия используется для конкретного предупреждения. Это зависит от реализации и может изменяться между версиями. Некоторые предупреждения даже полностью не контролируются «ocaml.warning» (например, предупреждения 1, 2, 14, 29 и 50).
  • “ocaml.warnerror” или “warnerror”, со строковым значением. Аналогично “ocaml.warning”, для командной опции -warn-error.
  • “ocaml.alert” или “alert”: см. раздел 12.21.
  • “ocaml.deprecated” или “deprecated”: псевдоним для предупреждения «deprecated», см. раздел 12.21.
  • “ocaml.deprecated_mutable” или “deprecated_mutable”. Может быть применён к метке мутабельного поля записи. Если метка впоследствии используется для изменения поля (с помощью “expr.l <- expr”), будет сгенерировано предупреждение «deprecated». Если значение атрибута является строковым литералом, сообщение об ошибке включает этот текст.
  • “ocaml.ppwarning” или “ppwarning”, в любом контексте, со строковым значением. Текст сообщается как предупреждение (22) компилятором (в настоящее время местоположение предупреждения — местоположение строкового значения). Это в основном полезно для препроцессоров, которые должны сообщать предупреждения пользователю. Это также можно использовать для явного маркирования некоторых мест кода для дальнейшего анализа.
  • “ocaml.warn_on_literal_pattern” или “warn_on_literal_pattern” аннотируют конструкторы в определении типа. Предупреждение (52) затем генерируется, когда этот конструктор сопоставляется с образцом константного литерала в качестве аргумента. Этот атрибут обозначает конструкторы, аргумент которых является чисто информативным и может измениться в будущем. Поэтому сопоставление с образцом для этого аргумента с константным литералом ненадежно. Например, все встроенные конструкторы исключений помечены как “warn_on_literal_pattern”. Обратите внимание, что из-за ограничения реализации это предупреждение (52) срабатывает только для конструкторов с одним аргументом.
  • “ocaml.tailcall” или “tailcall” может быть применено к применению функции для проверки, что вызов оптимизирован как хвостовой вызов. Если это не так, выдается предупреждение (51).
  • “ocaml.inline” или “inline” принимает “never”, “always” или ничего в качестве значения для определения функции или фукнтора. Если значение не указано, значение по умолчанию — “always”. Это значение определяет, когда приложения анотированных функций должны быть встроены.
  • “ocaml.inlined” или “inlined” можно применять к любому применению функции или фукнтора для проверки, что вызов встраивается компилятором. Если вызов не встраивается, генерируется предупреждение (55).
  • “ocaml.noalloc”, “ocaml.unboxed” и “ocaml.untagged” или “noalloc”, “unboxed” и “untagged” могут использоваться в внешних определениях для более точного управления интерфейсом C-to-OCaml. Для получения более подробной информации см. 22.11.
  • “ocaml.immediate” или “immediate”, применённый к абстрактному типу, помечает тип как имеющий реализацию без указателя (например, «int», «bool», «char» или перечислимые типы). Изменение этих непосредственных типов не активирует барьер записи сборщика мусора, что может значительно повысить производительность программ, сильно полагающихся на мутабельное состояние.
  • “ocaml.immediate64” или “immediate64”, применённый к абстрактному типу, помечает тип как имеющий реализацию без указателя на 64-битных платформах. На других платформах никаких предположений не делается. Для получения типа с атрибутом «immediate64» необходимо использовать функтор «Sys.Immediate64.Make».
  • ocaml.unboxed или unboxed может быть использован для определения типа, если тип является записью с одним полем или конкретным типом с одним конструктором, имеющим один аргумент. Это сообщает компилятору оптимизировать представление типа, удалив блок, представляющий запись или конструктор (т. е. значение этого типа физически равно его аргументу). В случае GADТ существует дополнительное ограничение: аргумент не должен быть переменной существования, представленной переменной существования типа или конструктором абстрактного типа, применённым к переменной существования типа.
  • ocaml.boxed или boxed может быть использован для определений типов, чтобы означать противоположное ocaml.unboxed: сохранить неоптимизированное представление типа. В случае отсутствия аннотации значение по умолчанию в настоящее время — boxed, но оно может измениться в будущем.
  • ocaml.local или local принимают never, always, maybe или ничего в качестве значения для определения функции. Если значение не указано, значение по умолчанию — always. Атрибут управляет оптимизацией, которая заключается в компиляции функции в статическое продолжение. В отличие от встраивания, эта оптимизация не дублирует тело функции. Это возможно, когда все ссылки на функцию являются полными приложениями, все делят одно и то же продолжение (например, возвращаемое значение нескольких ветвей сопоставления с образцом). never отключает оптимизацию, always утверждает, что оптимизация применяется (в противном случае генерируется предупреждение 55), а maybe позволяет оптимизации применяться, когда это возможно (это поведение по умолчанию, когда атрибут не указан). Оптимизация неявно отключена при использовании компилятора байткода в отладочном режиме (-g) и для функций, помеченных атрибутом ocaml.inline always или ocaml.unrolled, которые переопределяют ocaml.local.
module X = struct
  [@@@warning "+9"]  (* locally enable warning 9 in this structure *)
  …
end
[@@deprecated "Please use module 'Y' instead."]

let x = begin[@warning "+9"] […] end

type t = A | B
  [@@deprecated "Please use type 's' instead."]
let fires_warning_22 x =
  assert (x >= 0) [@ppwarning "TODO: remove this later"]

Warning 22 [preprocessor]: TODO: remove this later
let rec is_a_tail_call = function
  | [] -> ()
  | _ :: q -> (is_a_tail_call[@tailcall]) q

let rec not_a_tail_call = function
  | [] -> []
  | x :: q -> x :: (not_a_tail_call[@tailcall]) q

Warning 51 [wrong-tailcall-expectation]: expected tailcall
let f x = x [@@inline]

let () = (f[@inlined]) ()
type fragile =
  | Int of int [@warn_on_literal_pattern]
  | String of string [@warn_on_literal_pattern]
let fragile_match_1 = function
| Int 0 -> ()
| _ -> ()

Warning 52 [fragile-literal-pattern]: Code should not depend on the actual values of
this constructor's arguments. They are only for information
and may change in future versions. (See manual section 13.5)
val fragile_match_1 : fragile -> unit = 
let fragile_match_2 = function
| String "constant" -> ()
| _ -> ()

Warning 52 [fragile-literal-pattern]: Code should not depend on the actual values of
this constructor's arguments. They are only for information
and may change in future versions. (See manual section 13.5)
val fragile_match_2 : fragile -> unit = 
module Immediate: sig
  type t [@@immediate]
  val x: t ref
end = struct
  type t = A | B
  let x = ref A
end
module Int_or_int64 : sig
  type t [@@immediate64]
  val zero : t
  val one : t
  val add : t -> t -> t
end = struct

  include Sys.Immediate64.Make(Int)(Int64)

  module type S = sig
    val zero : t
    val one : t
    val add : t -> t -> t
  end

  let impl : (module S) =
    match repr with
    | Immediate ->
        (module Int : S)
    | Non_immediate ->
        (module Int64 : S)

  include (val impl : S)
end

© 1995-2022 INRIA.
https://v2.ocaml.org/releases/5.0/htmlman/attributes.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API