1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-22 19:44:10 +02:00
guile/module/language/tree-il/inline.scm
Andy Wingo 8a4ca0ea3b tree-il support for case-lambda
* module/language/tree-il.scm (<lambda>, <lambda-case>): Split lambda
  into the lambda itself, denoting the procedure, and lambda-case,
  denoting a particular arity case. Lambda-case is fairly featureful,
  and has not yet been fully tested.
  (<let-values>): Use a <lambda-case> as the binding expression. Seems
  to suit the purpose well.
  Adapt parsers, unparsers, traversal operators, etc. Sometimes in this
  first version we assume there are no optional args, rest args, or a
  predicate.

* module/language/tree-il/analyze.scm (analyze-lexicals): Adapt for the
  new case-lambda regime. Fairly well commented. It actually simplifies
  things.
  (report-unused-variables): Update for new tree-il.

* module/language/tree-il/compile-glil.scm: Adapt for the new tree-il.
  There are some first stabs here at proper case-lambda compilation, but
  they are untested as of yet.

* module/language/tree-il/inline.scm (inline!): Rework so we can
  recurse on a single node; though these transformations are strictly
  reductive, so they should complete in bounded time. Simplify
  accordingly, and adapt to case-lambda. Oh, and we handle lambda->let
  in not just the nullary case.

* module/ice-9/psyntax.scm (build-simple-lambda, build-case-lambda)
  (build-lambda-case): New constructors. The idea is that after syntax
  expansion, we shouldn't have to deal with improper lists any more.
  Build-simple-lambda is a shortcut for the common case. The others are
  not fully exercised yet. Adapt callers.
  (syntax): Add some debugging in the lambda case. I don't fully
  understand this, but in practice we don't seem to see rest args here.
  (lambda): Inline chi-lambda-clause, and adapt for build-simple-lambda.
* module/ice-9/psyntax-pp.scm: Regenerated.

* test-suite/tests/tree-il.test: Update tests for new tree-il lambda
  format, and to expect post-prelude labels for all glil programs.
2009-10-23 15:10:25 +02:00

88 lines
3.3 KiB
Scheme

;;; a simple inliner
;; Copyright (C) 2009 Free Software Foundation, Inc.
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;;
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; 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!))
;; Possible optimizations:
;; * constant folding, propagation
;; * procedure inlining
;; * always when single call site
;; * always for "trivial" procs
;; * otherwise who knows
;; * dead code elimination
;; * degenerate case optimizations
;; * "fixing letrec"
;; This is a completely brain-dead optimization pass whose sole claim to
;; fame is ((lambda () x)) => x.
(define (inline! x)
(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 vars predicate 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.
((<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-predicate (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))
((<letrec> vars body)
(if (null? vars) body x))
((<fix> vars body)
(if (null? vars) body x))
(else #f)))
(post-order! inline1 x))