Compiling a Lisp: Lambda lifting
Переписал Ghuloum-туториал на Python (~300 строк). Убрал читалку S-выражений и бинарный код — теперь текстовая ассемблерная печать.
Lambda-lifting требует:
- знать связанные переменные;
- собирать свободные переменные лямбд;
- накапливать создаваемые
code
-объекты.
Связывают let
и lambda
; для них обновляем окружение.
Lifter
class LambdaConverter:
def __init__(self):
self.labels = {}
def convert(self, expr, bound, free):
match expr:
case int() | Char() | bool():
return expr
case str() if expr in bound or expr in BUILTINS:
return expr
case str():
free.add(expr)
return expr
case ["if", t, c, a]:
return ["if",
self.convert(t, bound, free),
self.convert(c, bound, free),
self.convert(a, bound, free)]
lift_lambdas
запускает обход и возвращает (labels …)
.
Lambda
Лямбда:
- связывает параметры;
- выделяет код;
- захватывает внешнее окружение.
Пример:
(lambda () x) ; x свободна
превращается в
(labels ((f0 (code () (x) x)))
(closure f0 x))
Даже если x
связан снаружи, внутри лямбды он считается свободным.