Операционная семантика — это категория формальной семантики языка программирования , в которой определенные желаемые свойства программы , такие как корректность, безопасность или защищенность, проверяются путем построения доказательств из логических утверждений о ее выполнении и процедурах, а не путем придания математических значений ее терминам ( денотационная семантика ). Операционная семантика подразделяется на две категории: структурная операционная семантика (или семантика малых шагов ) формально описывает , как отдельные шаги вычисления происходят в компьютерной системе; противоположная ей естественная семантика (или семантика больших шагов ) описывает, как получаются общие результаты выполнения. Другие подходы к предоставлению формальной семантики языков программирования включают аксиоматическую семантику и денотацию .
Операционная семантика для языка программирования описывает, как допустимая программа интерпретируется как последовательности вычислительных шагов. Эти последовательности затем являются смыслом программы. В контексте функционального программирования последний шаг в завершающей последовательности возвращает значение программы. (В общем случае может быть много возвращаемых значений для одной программы, поскольку программа может быть недетерминированной , и даже для детерминированной программы может быть много вычислительных последовательностей, поскольку семантика может не указывать точно, какая последовательность операций достигает этого значения.)
Возможно, первым формальным воплощением операционной семантики было использование лямбда-исчисления для определения семантики Lisp . [1] Абстрактные машины в традиции машины SECD также тесно связаны.
Концепция операционной семантики была впервые использована при определении семантики Алгола 68. Следующее утверждение является цитатой из пересмотренного отчета Алгола 68:
Значение программы на строгом языке объясняется в терминах гипотетического компьютера, который выполняет набор действий, составляющих разработку этой программы. (Algol68, Раздел 2)
Первое использование термина «операциональная семантика» в его нынешнем значении приписывается Дане Скотту (Plotkin04). Далее следует цитата из основополагающей статьи Скотта о формальной семантике, в которой он упоминает «операциональные» аспекты семантики.
Конечно, очень хорошо стремиться к более «абстрактному» и «чистому» подходу к семантике, но если план должен быть хоть сколько-нибудь хорош, нельзя полностью игнорировать операциональные аспекты. (Scott70)
Гордон Плоткин представил структурную операциональную семантику, Маттиас Феллейзен и Роберт Хиб — редукционную семантику [2] , а Жиль Кан — естественную семантику.
Структурная операционная семантика (SOS, также называемая структурированной операционной семантикой или семантикой малых шагов ) была введена Гордоном Плоткиным в (Plotkin81) как логическое средство определения операционной семантики. Основная идея SOS заключается в определении поведения программы в терминах поведения ее частей, тем самым обеспечивая структурный, т. е. синтаксически-ориентированный и индуктивный , взгляд на операционную семантику. Спецификация SOS определяет поведение программы в терминах (набора) отношений перехода (отношений). Спецификации SOS принимают форму набора правил вывода , которые определяют допустимые переходы составного фрагмента синтаксиса в терминах переходов его компонентов.
Для простого примера рассмотрим часть семантики простого языка программирования; соответствующие иллюстрации даны в Plotkin81 и Hennessy90, а также в других учебниках. Пусть range по программам языка, и пусть range по состояниям (например, функции из ячеек памяти в значения). Если у нас есть выражения (ранжированные по ), значения ( ) и ячейки ( ), то команда обновления памяти будет иметь семантику:
Неформально правило гласит, что « если выражение в состоянии сводится к значению , то программа обновит состояние с помощью присваивания ».
Семантику последовательности можно задать следующими тремя правилами:
Неформально, первое правило гласит, что если программа в состоянии завершается в состоянии , то программа в состоянии сведется к программе в состоянии . (Вы можете думать об этом как о формализующем «Вы можете запустить , а затем запустить с использованием полученного хранилища памяти».) Второе правило гласит, что если программа в состоянии может свестись к программе с состоянием , то программа в состоянии сведется к программе в состоянии . (Вы можете думать об этом как о формализующем принципе для оптимизирующего компилятора: «Вам разрешено преобразовывать так, как если бы это было автономно, даже если это всего лишь первая часть программы».) Семантика структурна, поскольку значение последовательной программы определяется значением и значением .
Если у нас также есть булевы выражения над состоянием, ранжированные по , то мы можем определить семантику команды while :
Такое определение позволяет проводить формальный анализ поведения программ, позволяя изучать отношения между программами. Важные отношения включают предварительные заказы моделирования и бисимуляцию . Они особенно полезны в контексте теории параллелизма .
Благодаря интуитивному виду и простой структуре SOS приобрел большую популярность и стал фактическим стандартом в определении операционной семантики. В качестве признака успеха, оригинальный отчет (так называемый отчет Aarhus) по SOS (Plotkin81) привлек более 1000 ссылок, согласно CiteSeer [1], что сделало его одним из самых цитируемых технических отчетов в области компьютерных наук .
Семантика редукции — это альтернативное представление операционной семантики. Ее ключевые идеи были впервые применены к чисто функциональным вариантам вызова по имени и вызова по значению лямбда-исчисления Гордоном Плоткиным в 1975 году [3] и обобщены на функциональные языки более высокого порядка с императивными функциями Маттиасом Феллейзеном в его диссертации 1987 года. [4] Метод был далее разработан Маттиасом Феллейзеном и Робертом Хибом в 1992 году в полностью эквациональную теорию для управления и состояния . [2] Сама фраза «семантика редукции» была впервые придумана Феллейзеном и Дэниелом П. Фридманом в статье PARLE 1987 года. [5]
Семантика редукции задается как набор правил редукции , каждое из которых определяет один потенциальный шаг редукции. Например, следующее правило редукции гласит, что оператор присваивания может быть редуцирован, если он находится непосредственно рядом с объявлением его переменной:
Чтобы получить оператор присваивания в таком положении, он «всплывает» через применение функций и правую часть операторов присваивания, пока не достигнет нужной точки. Поскольку промежуточные выражения могут объявлять различные переменные, исчисление также требует правила вытеснения для выражений. Большинство опубликованных применений семантики редукции определяют такие «правила пузырька» с удобством контекстов оценки. Например, грамматика контекстов оценки в простом языке вызова по значению может быть задана как
где обозначает произвольные выражения, а обозначает полностью редуцированные значения. Каждый контекст оценки включает ровно одно отверстие , в которое термин вставляется в режиме захвата. Форма контекста указывает с помощью этого отверстия, где может произойти редукция. Для описания «пузырения» с помощью контекстов оценки достаточно одной аксиомы:
Это правило простого сокращения является правилом подъема из лямбда-исчисления Феллейзена и Хиба для операторов присваивания. Контексты оценки ограничивают это правило определенными терминами, но оно свободно применимо к любому термину, включая лямбды.
Следуя Плоткину, демонстрация полезности исчисления, полученного из набора правил редукции, требует (1) леммы Чёрча-Россера для одношагового отношения, которая индуцирует функцию оценки, и (2) леммы стандартизации Карри-Фейса для транзитивно-рефлексивного замыкания одношагового отношения, которая заменяет недетерминированный поиск в функции оценки на детерминированный левый/внешний поиск. Феллейзен показал, что императивные расширения этого исчисления удовлетворяют этим теоремам. Следствия этих теорем заключаются в том, что эквациональная теория — симметрично-транзитивно-рефлексивное замыкание — является обоснованным принципом рассуждения для этих языков. Однако на практике большинство приложений семантики редукции обходятся без исчисления и используют только стандартную редукцию (и оценщик, который может быть выведен из нее).
Семантика сокращения особенно полезна, учитывая легкость, с которой контексты оценки могут моделировать состояние или необычные конструкции управления (например, продолжения первого класса ). Кроме того, семантика сокращения использовалась для моделирования объектно-ориентированных языков, [6] систем контрактов , исключений, фьючерсов, вызова по потребности и многих других языковых функций. Тщательное современное рассмотрение семантики сокращения, в котором подробно обсуждаются несколько таких приложений, дано Маттиасом Феллейзеном, Робертом Брюсом Финдлером и Мэтью Флэттом в Semantics Engineering with PLT Redex . [7]
Крупношаговая структурная операционная семантика также известна под названиями естественная семантика , реляционная семантика и оценочная семантика . [8] Крупношаговая операционная семантика была введена под названием естественная семантика Жилем Каном при представлении Mini-ML, чистого диалекта ML .
Определения с большим шагом можно рассматривать как определения функций или, в более общем смысле, отношений, интерпретирующих каждую языковую конструкцию в соответствующей области. Его интуитивность делает его популярным выбором для спецификации семантики в языках программирования, но у него есть некоторые недостатки, которые делают его неудобным или невозможным для использования во многих ситуациях, таких как языки с функциями, требующими интенсивного управления, или параллелизмом. [9]
Семантика большого шага описывает в манере «разделяй и властвуй», как можно получить окончательные результаты оценки языковых конструкций путем объединения результатов оценки их синтаксических аналогов (подвыражений, подутверждений и т. д.).
Существует ряд различий между семантикой малого и большого шага, которые влияют на то, является ли одна из них более подходящей основой для определения семантики языка программирования.
Семантика с большим шагом имеет то преимущество, что она часто проще (требует меньше правил вывода) и часто напрямую соответствует эффективной реализации интерпретатора для языка (поэтому Кан называет их «естественными»). Оба варианта могут привести к более простым доказательствам, например, при доказательстве сохранения корректности при некотором преобразовании программы . [10]
Основным недостатком семантики большого шага является то, что нетерминированные ( расходящиеся ) вычисления не имеют дерева вывода, что делает невозможным установление и доказательство свойств таких вычислений. [10]
Семантика малых шагов дает больше контроля над деталями и порядком оценки. В случае инструментированной операционной семантики это позволяет операционной семантике отслеживать, а семантику устанавливать и доказывать более точные теоремы о поведении языка во время выполнения. Эти свойства делают семантику малых шагов более удобной при доказательстве надежности типа системы типов против операционной семантики. [10]