Украина |
Семантика основных конструкций языка программирования C#
В соответствии с намеченной схемой рассуждений, перейдем к описанию синтаксических доменов, которые в полной мере определяют синтаксис языка C#:
Ide ={I|I - идентификатор}; Com ={C|C - команда}; Exp ={E|E - выражение}.
Совокупность всех возможных идентификаторов языка C# организуем в домен Ide, команд - в домен Com, и, наконец, выражений - в домен Exp.
Далее, сформулируем вычислительную модель на основе состояний программы языка C#, для наглядности систематизировав ее в виде следующей таблицы:
Параметр | Домен | Соотношение |
---|---|---|
Состояние | State | (s) State = Memory |
Память | Memory | (m) Memory = Ide -> [Value + (unbound)] |
Значение | Value | (v) Value = Int + Bool |
Заметим, что состояние программы в произвольный момент времени определяется состоянием "памяти" абстрактной машины той или иной формы. При этом под памятью понимается отображение из домена идентификаторов в домен значений (т.е. аналог связывания переменной со значением в ламбда-исчислении). Для корректной обработки исключительных ситуаций, возникающих в случае свободных переменных, вводится дополнительный элемент unbound. Домен значений представляет собой дизъюнктную сумму доменов, содержащих существующие в языке C# типы Int и Bool.
В соответствии с намеченной схемой рассуждений, перейдем к описанию семантических предложений, которые описывают значение денотатов (т.е. правильно построенных конструкций) языка C#.
Приведем семантические предложения для выражений языка программирования C#:
E : Exp -> [State -> [[Value ( State] + {error}]]; E[E]s = (v,s'),
если
s' - состояние после означивания ;
E[E]s = error,
если возникает ошибка несоответствия типов.
Из приведенных соотношений следует, что вычисление значения выражения языка программирования C# приводит к такому изменению состояния, что происходит связывание переменной со значением, либо (в случае невозможности связывания по причине несоответствия типов переменной и значения ) вырабатывается ошибка. При этом состояние программы изменяется с s на s'.
Приведем семантическое предложение для команд языка программирования C#:
С:Com->[State->[State+{error}]].
Из приведенного соотношения следует, что вычисление значения команды языка программирования C# приводит, вообще говоря, к изменению состояния, причем возможно возникновение ситуации (например, несоответствия типов в ходе присваивания), при которой вырабатывается ошибка.
В соответствии с намеченной схемой рассуждений, перейдем к описанию семантических предложений, которые описывают значение конкретных денотатов (т.е. правильно построенных конструкций) языка C#. Рассмотрим семантические предложения для денотатов констант целочисленного типа языка C#:
E[0]s=(0,s); E[1]s=(1,s);
Как видно из приведенных соотношений, денотатами констант целочисленного типа являются значения этих констант (в форме упорядоченных пар вида " значение "-" состояние "), причем смены состояния программы не происходит. Рассмотрим семантические предложения для денотатов констант логического типа языка C#:
E[true]s=(true,s); E[false]s=(false,s);
Как видно из приведенных соотношений, денотатами констант логического типа являются значения этих констант (в форме упорядоченных пар вида " значение "-" состояние "), причем смены состояния программы не происходит. Рассмотрим семантическое предложение для денотатов идентификаторов языка C#:
E[I]s=(m,I=unbound) error, -> (m,I,s).
Как видно из приведенного соотношения, при возможности связывания денотатами идентификаторов являются идентификаторы, связанные со значениями (в форме упорядоченных троек вида " значение в памяти "-" идентификатор "-" состояние "), причем смены состояния программы не происходит, а при невозможности - выдается сообщение об ошибке.
Рассмотрим семантические предложения для денотатов выражений языка C#:
E[!E]s = (E [E] s=(v, s')) (isBool -> (not v, s'), error), error; E [E1=E2] s = (E [E1]s = (v1, s1)) -> (E [E2] s1 = (v2, s2)) -> (v1 = v2, s2), error), error; E [E1+E2] s = (E [E1] s=(v1, s1)) -> (E [E2] s1 = (v2, s2)) -> (IsNum v1 and IsNum v2 -> v1 + v2, s2), error),error),error.
Проанализируем полученные соотношения.
Денотатом отрицания выражения является отрицание его значения ; причем состояние программы изменяется. В случае несоответствия типов или небулевости выражения генерируется сообщение об ошибке.
Денотатом присваивания является присвоенное значение в новом состоянии. В случае несоответствия типов генерируется сообщение об ошибке.
Денотатом сложения является значение суммы в новом состоянии. В случае несоответствия типов генерируется сообщение об ошибке.
В качестве упражнения предлагается самостоятельно разработать семантические предложения для денотатов команд языка программирования C#.
В ходе лекции была представлена классификация подходов к семантике языков программирования, признан целесообразным денотационный подход, который проиллюстрирован примером языка C# - ограниченного подмножества C#.
Важнейший вывод, к которому мы неизбежно приходим к концу лекции, заключается в том, что семантики рассмотренных нами языков программирования SMalL и C# (которые являются подмножествами реальных языков SML и C#) имеют весьма много общего.
Более того, сходство семантики рассмотренных нами конструкций ( команд и выражений ) языков программирования SMalL и C# весьма прозрачно и очевидно. Для иллюстрации справедливости этого утверждения достаточно сопоставить результаты исследования семантики рассматриваемых языков программирования.
По результатам такого сопоставления можно прийти к закономерному выводу о том, что существует явное, непосредственное отображение конструкций рассмотренных языковых подмножеств друг в друга, причем это отображение носит взаимно однозначный характер.
Попутно мы можем сделать еще один важный вывод. Формализация денотационной семантики на основе доменов с помощью теории вычислений Д. Скотта является адекватной моделью семантики выражений и команд рассмотренных языков программирования (а также функционального и объектно-ориентированного подходов в целом). Таким образом, семантика языков функционального и объектно-ориентированного программирования достаточно близка к семантике формальных теорий, на которых они основаны (в частности, это справедливо для ламбда-исчисления и языков SML и C#). Кроме того, теория вычислений является актуальной и адекватной формализацией семантики, а денотационный подход - целесообразным для моделирования семантики различных языков программирования.
В завершение лекции хотелось бы указать на аналогию теории вычислений Д. Скотта и ламбда-исчисления (как метатеорий ) со средой Microsoft .NET (как метасредой ), которые принципиально обеспечивают возможность "погружения" в себя различных языков и подходов к программированию.
Для более подробного самостоятельного ознакомления с тематикой лекции рекомендуется следующий список источников: [ 24, 35, 39, 42, 45, 53, 69, 73].