Spec-Zone.ru › Elisp

Нелокальные выходы в модулях

Emacs Lisp поддерживает нелокальные выходы, при которых управление программой передается из одной точки программы в другую удалённую точку. См. Нелокальные выходы. Таким образом, функции Lisp, вызываемые вашим модулем, могут выйти нелокально, вызвав signal или throw, и ваши функции модуля должны должным образом обработать такие нелокальные выходы. Такая обработка необходима, потому что программы C не будут автоматически освобождать ресурсы и выполнять другие очистки в этих случаях; код вашего модуля должен сам это сделать. Модульный API предоставляет для этого средства, описанные в этом подразделе. Они в целом доступны с Emacs 25; те из них, которые стали доступны в более поздних выпусках, явно указывают первую версию Emacs, где они стали частью API.

Когда некоторый код Lisp, вызываемый функцией модуля, сигнализирует об ошибке или выбрасывает исключение, нелокальный выход перехватывается, и ожидающий выход и связанные с ним данные хранятся в среде. Всякий раз, когда в среде ожидается нелокальный выход, любая функция модульного API, вызываемая с указателем на эту среду, вернётся немедленно без обработки (функции non_local_exit_check, non_local_exit_get, и non_local_exit_clear являются исключениями из этого правила). Если ваша функция модуля затем ничего не делает и возвращается в Emacs, ожидающий нелокальный выход заставит Emacs выполнить соответствующее действие: сигнализировать об ошибке или выбросить исключение в соответствующую catch.

Итак, простейшая «обработка» нелокальных выходов в функциях модуля заключается в том, чтобы ничего особенного не делать и позволить остальной части вашего кода работать так, как будто ничего не произошло. Однако это может привести к двум типам проблем:

  • - Ваша функция модуля может использовать неинициализированные или неопределённые значения, поскольку функции API возвращаются немедленно без производства ожидаемых результатов.
  • - Ваш модуль может утечка ресурсов, поскольку у него может не быть возможности их освободить.

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

Функция: enum emacs_funcall_exit non_local_exit_check (emacs_env *env)

Эта функция возвращает вид условия нелокального выхода, хранящегося в env. Возможные значения:

emacs_funcall_exit_return

Последняя функция API завершилась нормально.

emacs_funcall_exit_signal

Последняя функция API сигнализировала об ошибке.

emacs_funcall_exit_throw

Последняя функция API вышла через throw.

Функция: enum emacs_funcall_exit non_local_exit_get (emacs_env *env, emacs_value *symbol, emacs_value *data)

Эта функция возвращает вид условия нелокального выхода, хранящегося в env, как и non_local_exit_check, но также возвращает полную информацию о нелокальном выходе, если таковой имеется. Если возвращаемое значение равно emacs_funcall_exit_signal, функция сохраняет символ ошибки в *symbol и данные об ошибке в *data (см. Сигнализация об ошибках). Если возвращаемое значение равно emacs_funcall_exit_throw, функция сохраняет символ метки catch в *symbol и значение throw в *data. Функция ничего не сохраняет в памяти, на которую указывают эти аргументы, когда возвращаемое значение равно emacs_funcall_exit_return.

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

После того, как ваша функция модуля обнаружила, что ожидается нелокальный выход, она может либо вернуться в Emacs (после выполнения необходимой локальной очистки), либо попытаться восстановиться от нелокального выхода. Следующие функции API помогут в этих задачах.

Функция: void non_local_exit_clear (emacs_env *env)

Эта функция очищает условия и данные ожидающего нелокального выхода из env. После её вызова функции модульного API будут работать нормально. Используйте эту функцию, если ваша функция модуля может восстановиться от нелокальных выходов вызываемых функций Lisp и продолжить работу, а также перед вызовом любой из следующих двух функций (или любых других функций API, если вы хотите, чтобы они выполняли своё задуманное действие, когда ожидается нелокальный выход).

Функция: void non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value)

Эта функция выбрасывает исключение в символ Lisp catch, представленный tag, передавая ему value в качестве возвращаемого значения. Ваша функция модуля, как правило, должна вернуться вскоре после вызова этой функции. Одно из применений этой функции – повторный выброс нелокального выхода из одной из вызываемых функций API или Lisp.

Функция: void non_local_exit_signal (emacs_env *env, emacs_value symbol, emacs_value data)

Эта функция сигнализирует об ошибке, представленной символом ошибки symbol, с указанными данными об ошибке data. Функция модуля должна вернуться вскоре после вызова этой функции. Эта функция может быть полезной, например, для сигнализации об ошибках от функций модуля в Emacs.

Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Module-Nonlocal.html

Spec-Zone.ru

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