;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
(define-module (language tree-il inline)
+ #:use-module (system base pmatch)
#:use-module (system base syntax)
#:use-module (language tree-il)
#:export (inline!))
;; This is a completely brain-dead optimization pass whose sole claim to
;; fame is ((lambda () x)) => x.
(define (inline! x)
- (post-order!
- (lambda (x)
- (record-case x
- ((<application> src proc args)
- (cond
-
- ;; ((lambda () x)) => x
- ((and (lambda? proc) (null? (lambda-vars proc))
- (null? args))
- (lambda-body proc))
+ (define (inline1 x)
+ (record-case x
+ ((<application> src proc args)
+ (record-case proc
+ ;; ((lambda (y ...) x) z ...) => (let ((y z) ...) x)
+ ((<lambda> body)
+ (let lp ((lcase body))
+ (and lcase
+ (record-case lcase
+ ((<lambda-case> req opt rest kw inits vars body else)
+ (if (and (= (length vars) (length req) (length args)))
+ (let ((x (make-let src req vars args body)))
+ (or (inline1 x) x))
+ (lp else)))))))
;; (call-with-values (lambda () foo) (lambda (a b . c) bar))
;; => (let-values (((a b . c) foo)) bar)
;; Note that this is a singly-binding form of let-values. Also
;; note that Scheme's let-values expands into call-with-values,
;; then here we reduce it to tree-il's let-values.
- ((and (primitive-ref? proc)
- (eq? (primitive-ref-name proc) '@call-with-values)
- (= (length args) 2)
- (lambda? (cadr args)))
- (let ((producer (car args))
- (consumer (cadr args)))
- (make-let-values src
- (lambda-names consumer)
- (lambda-vars consumer)
- (if (and (lambda? producer)
- (null? (lambda-names producer)))
- (lambda-body producer)
- (make-application src producer '()))
- (lambda-body consumer))))
+ ((<primitive-ref> name)
+ (and (eq? name '@call-with-values)
+ (pmatch args
+ ((,producer ,consumer)
+ (guard (lambda? consumer)
+ (lambda-case? (lambda-body consumer))
+ (not (lambda-case-opt (lambda-body consumer)))
+ (not (lambda-case-kw (lambda-body consumer)))
+ (not (lambda-case-else (lambda-body consumer))))
+ (make-let-values
+ src
+ (let ((x (make-application src producer '())))
+ (or (inline1 x) x))
+ (lambda-body consumer)))
+ (else #f))))
(else #f)))
- ((<let> vars body)
- (if (null? vars) body x))
+ ((<let> vars body)
+ (if (null? vars) body x))
- ((<letrec> vars body)
- (if (null? vars) body x))
+ ((<letrec> vars body)
+ (if (null? vars) body x))
- ((<fix> vars body)
- (if (null? vars) body x))
+ ((<fix> vars body)
+ (if (null? vars) body x))
- (else #f)))
- x))
+ (else #f)))
+ (post-order! inline1 x))