Spec-Zone.ru › OCaml
☰Язык программирования OCaml
  • Язык программирования OCaml
  • Расширения языка

Глава 12 Расширения языка

13 Узлы расширений

  • 13.1 Встроенные узлы расширений

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

Узлы расширений — это универсальные заглушки в синтаксическом дереве. Они отклоняются проверкой типов и предназначены для «расширения» внешними инструментами, такими как переписыватели -ppx.

Узлы расширений используют ту же концепцию идентификатора и полезной нагрузки, что и атрибуты ‍12.12.

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

extension ::= [% attr-id attr-payload ]
expr ::= ...
∣ extension
typexpr ::= ...
∣ extension
pattern ::= ...
∣ extension
module-expr ::= ...
∣ extension
module-type ::= ...
∣ extension
class-expr ::= ...
∣ extension
class-type ::= ...
∣ extension

Второй вид узла расширения может быть использован в структурах и сигнатурах, как в модульном, так и в объектно-ориентированном языках:

item-extension ::= [%% attr-id attr-payload ]
definition ::= ...
∣ item-extension
specification ::= ...
∣ item-extension
class-field-spec ::= ...
∣ item-extension
class-field ::= ...
∣ item-extension

При использовании инфиксной формы для узлов расширений, когда полезная нагрузка имеет тот же тип (выражение с выражением, шаблон с шаблоном ...), доступна инфиксная форма.

Примеры:

let%foo x = 2 in x + 1     === [%foo let x = 2 in x + 1]
begin%foo ... end          === [%foo begin ... end]
x ;%foo 2                  === [%foo x; 2]
module%foo M = ..          === [%%foo module M = ... ]
val%foo x : t              === [%%foo: val x : t]

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

fun%foo[@bar] x -> x + 1 === [%foo (fun x -> x + 1)[@bar ] ];

Для удобства доступен дополнительный сокращенный вариант let%foo x in ..., когда узлы расширений используются для реализации операторов связывания (см. 12.23.4).

Кроме того, строковые литералы {|...|} можно комбинировать с узлами расширений для встраивания фрагментов чужого синтаксиса. Эти фрагменты могут интерпретироваться препроцессором и преобразовываться в код OCaml без необходимости экранирования кавычек. Для них доступен синтаксический ярлык:

{%%foo|...|}               === [%%foo{|...|}]
let x = {%foo|...|}        === let x = [%foo{|...|}]
let y = {%foo bar|...|bar} === let y = [%foo{bar|...|bar}]

Например, можно использовать {%sql|...|} для представления произвольных SQL-запросов — при условии, что у вас есть ppx-переписыватель, распознающий расширение %sql.

Обратите внимание, что разделитель слов, например {sql|...|sql}, не следует использовать для обозначения того, что расширение используется. Действительно, из кода нельзя понять, имеет ли этот строковый литерал другие семантические значения, чем ожидается. Кроме того, присвоение семантики определенному разделителю ограничивает возможность изменения разделителя для избегания проблем с экранированием.

13.1 Встроенные узлы расширений

(Введены в OCaml 4.03)

Некоторые узлы расширений понимаются самим компилятором:

  • «ocaml.extension_constructor» или «extension_constructor» принимают в качестве полезной нагрузки конструктор из расширяемого типа варианта (см. 12.14) и возвращают его слот конструктора расширения.
type t = ..
type t += X of int | Y of string
let x = [%extension_constructor X]
let y = [%extension_constructor Y]
#  x <> y;;

- : bool = true
« АтрибутыРасширяемые типы вариантов »
Авторские права © 2024 Institut National de Recherche en Informatique et en Automatique

© 1995-2024 INRIA.
https://ocaml.org/manual/5.2/extensionnodes.html

Spec-Zone.ru

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