210
Все эти переходы совершенно понятны – значение из команды или
контекста просто переносится на стек результатов, возможно, несколько
видоизменяясь. Так, при исполнении команды LoadFunc загрузки
функции в стек помещается замыкание, образованное из команд,
реализующих работу этой функции, и текущего контекста. При
исполнении команды загрузки встроенной функции LoadOp формируется
пустой список аргументов,
и с помощью функции arity вычисляется
количество требуемых аргументов для того, чтобы функция могла
выполниться.
Команда Select тоже работает достаточно просто, однако
результат ее работы зависит от значения, находящегося на вершине стека.
Исполнение этой команды мы опишем с помощью двух переходов,
соответствующих двум возможным значениям, которые будут находиться
на вершине стека
в момент ее исполнения.
((Boolean True):s,ctx,(Select th el):c,d) ⇒ (s,ctx,th ++ c,d)
((Boolean False):s,ctx,(Select th el):c,d) ⇒ (s,ctx,el ++ c,d)
В результате к текущему списку команд регистра управления
добавляется один из двух списков команд из исполняющейся команды
Select. Теперь опишем пару команд для исполнения входа в функцию и
выхода из нее – команд Apply и Return. В случае, когда функция, в
которую происходит вход, представлена замыканием, команда Apply
просто сохраняет текущее состояние
SECD-машины в регистре хранения
состояний, формирует новый контекст и подготавливает машину к
выполнению команд вызываемой функции. Такое поведение можно
описать с помощью следующего правила перехода:
((Closure coms env):arg:s, ctx, Apply:c, d) ⇒
([], [arg]:env, coms, (s, ctx, c):d)
Работа команды Apply в ситуации, когда исполняемая функция
представлена сечением зависит от того, является ли аргумент функции
последним требуемым аргументом. Если да, то результат вычисляется с
помощью функции intrinsic, которая, как и раньше, выполняет
действия по исполнению встроенной функции. Если нет, то очередной
аргумент просто добавляется в список аргументов сечения. Таким
образом,
работа этой команды может быть описана с помощью следующих двух
правил перехода (во втором из этих правил подразумевается, что значение
n больше единицы).
((Op f 1 list):arg:s, ctx, Apply:c, d) ⇒
((intrinsic f (list ++ [arg])):s, ctx, c, d)
((Op f n list):arg:s, ctx, Apply:c, d) ⇒
((Op f (n-1) (list ++ [arg])):s, ctx, c, d)