добавление элемента в обычный список: elem
: s.Рассмотрим правило для let
-выражений:let x
= obj in e;s
;H
⇒ e
[ x / x]; s; H[ x → obj] , x – новое имяРис. 10.4: Синтаксис STG
В этом правиле мы добавляем в кучу новый объект obj
под именем (или по адресу) x . Запись e[ x / x]означает замену x
на x в выражении e.Теперь разберёмся с правилами для case
-выражений.case v
of {. . . ; C x 1 . . . xn → e; . . . };⇒ e
[ a 1/ x 1 . . . an/ xn]; s; Hs
;H
[ v → CON ( C a 1 . . . an)]case v
of {. . . ; x → e};s
;H
⇒ e
[ v/ x]; s; HЕсли v
– литерал или H[ v] – значение,которое не подходит ни по одной из альтернатив
case e
of {. . . };s
;H
⇒ e
; case • of {. . . } : s; Hv
;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; Ha
– результат вычисления ( ⊕ a 1 . . . an)Рис. 10.7: Синтаксис STG
Мы просто заменяем все вхождения аргументов на значения. Второе правило выполняет применение
примитивной функции к значениям.
Правила для стратегии вставка-вход
f k a
1 . . . am;s
;H
⇒ f
; Arg a 1 : … : Arg am : s; Hf
;Arg a
1 : … : Arg an : s;H
[ f → F U N ( x 1 . . . xn → e)]⇒ e
[ a 1/ x 1 . . . an/ xn]; s; Hf
;Arg a
1 : … : Arg am : s;H
[ f → F U N ( x 1 . . . xn → e)]⇒ p
; s; H[ p → P AP ( f a 1 . . . am)]при m ≥
1; m < n; верхний элемент sне является Arg
; p – новый адресf
;Arg an
+1 : s;H
[ f → P AP ( g a 1 . . . an)]⇒ g
; Arg a 1 : … : Arg an : Arg an+1 : s; HРис. 10.8: Синтаксис STG
Первое правило выполняет этап “вставка”. Если мы видим применение функции, мы первым делом со-
храняем все аргументы в стеке. Во втором правиле мы вычислили значение f, оно оказалось функцией с
арностью n
. Тогда мы добираем из стека n аргументов и подставляем их в правую часть функции e. Еслив стеке оказалось слишком мало аргументов, то мы переходим к третьему правилу и составляем частичное
применение. Последнее правило говорит о том как расшифровывается частичное применение. Мы вставляем
в стек все аргументы и начинаем вычисление функции g
из тела P AP .Вычисление STG | 161
f • a
1 . . . an;s
;H
[ f → F U N ( x 1 . . . xn → e)]⇒ e
[ a 1/ x 1 . . . an/ xn]; s; Hf k a
1 . . . am;s
;H
[ f → F U N ( x 1 . . . xn → e)]⇒ e
[ a 1/ x 1 . . . an/ xn]; ( • an+1 . . . am) : s; Hпри m ≥ n
⇒ p
; s; H[ p → P AP ( f a 1 . . . am)]при m < n, p
– новый адресf • a
1 . . . am;s
;H
[ f → T HU N K e]⇒ f
; ( • a 1 . . . am) : s; Hf k an
+1 . . . am;s
;H
[ f → P AP ( g a 1 . . . an)]⇒ g• a
1 . . . an an+1 . . . am; s; Hf
;( • a
1 . . . an) : s;H
⇒ f• a
1 . . . an; s; HH
[ f ] является F U N или P APРис. 10.9: Синтаксис STG
Правила для стратегии вычисление-применение
Разберёмся с первыми двумя правилами. В первом правиле статическая арность f
неизвестна, но зна-чение f
уже вычислено, и мы можем узнать арность по объекту F UN, далее возможны три случая. Числоаргументов переданных в функцию совпадает с арностью F UN
, тогда мы применяем аргументы к правой