52700.fb2
⇒ e; case • of {. . . } : s; H
v;
case • of {. . . } : s;
H
⇒ case v of {. . . }; s; H
Рис. 10.5: Синтаксис STG
Вычисления начинаются с третьего правила, в котором нам встречается case-выражения с произвольным
e. В этом правиле мы сохраняем в стеке альтернативы и адрес возвращаемого значения и продолжаем вы-
числение выражения e. После вычисления мы перейдём к четвёртому правилу, тогда мы снимем со стека
160 | Глава 10: Реализация Haskell в GHC
информацию необходимую для продолжения вычисления case-выражения. Это приведёт нас к одному из
первых двух правил. В первом правиле значение аргумента содержит конструктор, подходящий по одной из
альтернатив, а во втором мы выбираем альтернативу по умолчанию.
Теперь посмотрим как вычисляются THUNK-объекты.
x;
s;
H[ x → T HU N K e]
⇒ e; Upd x • : s; H[ x → BLACKHOLE]
y;
U pd x • : s;
H
⇒ y; s; H[ x → H[ y]]
если H[ y] является значением
Рис. 10.6: Синтаксис STG
Если переменная указывает на отложенное вычисление e, мы сохраняем в стеке адрес по которому
необходимо обновить значение и вычисляем значение e. В это время мы записываем в по адресу x объ-
ект BLACKHOLE. У нас нет такого правила, которое реагирует на левую часть, если в ней содержится
объект BLACKHOLE. Поэтому во время вычисления T HUNK ни одно из правил сработать не может.
Этот трюк необходим для избежания утечек памяти. Как только выражнение будет вычислено мы извлечём
из стека адрес x и обновим значение.
Правила применения функций, если арность совпадает с числом аргументов в тексте выражения:
f n a 1 . . . an;
s;
H[ y → F U N ( x 1 . . . xn → e)]
⇒ e[ a 1/ x 1 . . . an/ xn]; s; H
⊕ a 1 . . . an; s; H
⇒ a; s; H
a – результат вычисления ( ⊕ a 1 . . . an)
Рис. 10.7: Синтаксис STG
Мы просто заменяем все вхождения аргументов на значения. Второе правило выполняет применение
примитивной функции к значениям.
Правила для стратегии вставка-вход
f k a 1 . . . am;
s;
H
⇒ f; Arg a 1 : … : Arg am : s; H
f ;
Arg a 1 : … : Arg an : s;
H[ f → F U N ( x 1 . . . xn → e)]