224
interpreter (Select cond s1 s2) env =
interpreter iff env
where iff =
(if (evaluate cond env) == (Constant 1) then s1 else s2)
interpreter oper@(Loop cond s) env =
if (evaluate cond env) == (Constant 0)
then env
else interpreter oper (interpreter s env)
Эти уравнения необходимо объяснить. Первое уравнение, впрочем,
очевидно – оно отражает тот факт, что выполнение пустого оператора не
изменяет среду. Второе уравнение использует функцию replace, которая
заменяет в заданной среде значение одной переменной на заданное
значение. Точнее, функция должна построить новую среду, отличающуюся
от исходной значением только одной переменной. Вот как может
выглядеть определение этой функции.
replace :: String -> Expression -> Environment -> Environment
replace x v ((first@(y, _)):others)
| x == y = (y, v) : others
| otherwise = first:(replace x v others)
Третье и четвертое уравнения функции interpret задают
семантику выполнения последовательности операторов следующим
образом. Последовательность из нулевого числа операторов не меняет
среду, а если последовательность не пуста, то надо сначала выполнить
первый из операторов, а оставшиеся выполнить в среде, которая получится
после исполнения первого оператора.
Пятое уравнение предписывает для исполнения условного оператора
сначала вычислить значение условия, и в зависимости от результата
исполнять первый или второй из внутренних операторов.
Самое сложное – последнее уравнение, описывающее семантику
выполнения оператора цикла. В нем предписывается вычислить условие
цикла в исходном состоянии, а затем, в зависимости от результата либо
оставить среду неизменной (исполнение цикла завершено), либо
исполнить тело
цикла в исходной среде, а затем повторить исполнение
того же оператора в новой среде, полученной после однократного
выполнения тела цикла
Можно проверить, что наш интерпретатор действительно работает.
Если вызвать функцию interpreter с параметрами, задающими нашу
исходную программу вычисления факториала и с начальной средой
env_initial, то результатом вычисления будет новая среда
env_final = [("f", (Constant 120)), ("n", (Constant 0))]
В данном случае, правда, важно не столько то, что мы можем с
помощью функции interpreter получать результаты исполнения
программы, сколько то, что мы можем с ее помощью по любой программе
получать эквивалентную этой программе функцию. Ранее, в этой главе мы