Desugaring combines adjacent top-level defines into one letrec

This commit is contained in:
2026-01-27 10:58:02 -06:00
parent bb23fe5c58
commit 67d7cd8e3e

View File

@@ -31,7 +31,7 @@
(boolean? x))) (boolean? x)))
(define primitives (define primitives
'(#t #f () cons car cdr = + - / *)) '(#t #f () cons car cdr = + - / * < >))
(define (primitive? x) (define (primitive? x)
(memq x primitives)) (memq x primitives))
@@ -41,6 +41,9 @@
(boolean? x) (boolean? x)
(and (pair? x) (eq? 'quote (car x))))) (and (pair? x) (eq? 'quote (car x)))))
(define (define? x)
(and (pair? x) (eq? 'define (car x))))
;; Environment Records ;; Environment Records
;; The idea of an hierarchy of environments comes across often in lexical variable definition ;; The idea of an hierarchy of environments comes across often in lexical variable definition
(define-record-type <environment> (define-record-type <environment>
@@ -78,28 +81,36 @@
;; Transforms to simplify the language ;; Transforms to simplify the language
;; - lambdas, lets and letrecs can only have 1 expression in body position ;; - lambdas, lets and letrecs can only have 1 expression in body position
;; - defines are decomposed to letrecs that bind their values and wrap their continuations ;; - defines are decomposed to letrecs that bind their values and wrap their continuations
;; - adjacent top-level defines are combined into a single top-level letrec
;; <prgm> ::= <exp> ... ;; <prgm> ::= <exp> ...
;; <exp> ::= (lambda (<var> ...) <exp>) ;; <exp> ::= (lambda (<var> ...) <exp>)
;; | (if <exp> <exp> <exp>) ;; | (if <exp> <exp> <exp>)
;; | (<exp> <exp> ...) ;; | (<exp> <exp> ...)
;; | (let ((<var> <exp>) ...) <exp>) ;; | (let ((<var> <exp>) ...) <exp>)
;; | (letrec ((<var> <exp>)) <exp> ...) ;; | (letrec ((<var> <exp>) ...) <exp>)
;; | (begin <exp> ...) ;; | (begin <exp> ...)
;; | <num> | <sym> | <var> | #t | #f ;; | <num> | <sym> | <var> | #t | #f
(define (desugar-top prgm) (define (collect-bindings prgm)
(match prgm ;; Collect the bindings of adjacent defines
[() '()] (match (car prgm)
[(('define . _) cont ...) (desugar-define (car prgm) cont)]
[_ (cons (desugar-exp (car prgm))
(desugar-top (cdr prgm)))]))
(define (desugar-define def cont)
(match def
[`(define ,(name params ...) . ,e*) [`(define ,(name params ...) . ,e*)
`(letrec ([,name ,(desugar-exp `(lambda ,params ,@e*))]) (begin ,@(desugar-top cont)))] (let-values ([(bindings cont) (collect-bindings (cdr prgm))])
(values (cons `(,name ,(desugar-exp `(lambda ,params ,@e*))) bindings)
cont))]
[`(define ,name ,exp) [`(define ,name ,exp)
`(letrec ([,name ,(desugar-exp exp)]) (begin ,@(desugar-top cont)))])) (let-values ([(bindings cont) (collect-bindings (cdr prgm))])
(values (cons `(,name ,(desugar-exp exp)) bindings)
cont))]
[_ (values '() prgm)]))
(define (desugar-top prgm)
(cond
[(null? prgm) '()]
[(define? (car prgm))
(let-values ([(bindings cont) (collect-bindings prgm)])
`(letrec ,bindings ,(desugar-body cont)))]
[else (cons (desugar-exp (car prgm)) (desugar-top (cdr exp)))]))
(define (desugar-exp exp) (define (desugar-exp exp)
(match exp (match exp
@@ -180,10 +191,10 @@
[ ('quote e) `(,c ,expr)] [ ('quote e) `(,c ,expr)]
[`(lambda . ,_) `(,c ,(M expr r))] [`(lambda . ,_) `(,c ,(M expr r))]
[ (? atomic?) `(,c ,(M expr r))] [ (? atomic?) `(,c ,(M expr r))]
[ ('letrec ([v e]) body) [ ('letrec ([v* e*] ...) body)
(let-values ([(r0 v0) (uniq-name r v)]) (let-values ([(r0 v*0) (uniq-names r v*)])
(T-k e (lambda ($e) (T*-k e* (lambda ($e*)
(T-k body (lambda ($body) `(letrec ([,v0 ,$e]) (,c ,$body))) r0)) (T-k body (lambda ($body) `(letrec ,(zip v*0 $e*) (,c ,$body))) r0))
r0))] r0))]
[ ('begin e) (T-c e c r)] [ ('begin e) (T-c e c r)]
[ ('begin e e* ...) [ ('begin e e* ...)
@@ -217,12 +228,12 @@
[ ('quote e) (k expr)] [ ('quote e) (k expr)]
[`(lambda . ,_) (k (M expr r))] [`(lambda . ,_) (k (M expr r))]
[(? atomic?) (k (M expr r))] [(? atomic?) (k (M expr r))]
[('letrec ([v e]) body) [('letrec ([v* e*] ...) body)
(let-values ([(r0 v0) (uniq-name r v)]) (let-values ([(r0 v*0) (uniq-names r v*)])
(T-k e (T*-k e*
(lambda ($e) (lambda ($e*)
(T-k body (T-k body
(lambda ($body) `(letrec ([,v ,$e]) ,(k $body))) (lambda ($body) `(letrec ,(zip v*0 $e*) ,(k $body)))
r0)) r0))
r0))] r0))]
[('begin e) (T-k e k r)] [('begin e) (T-k e k r)]