1 ;;;; the representation of a lexical environment
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
14 ;;; support for the idiom (in MACROEXPAND and elsewhere) that NIL is
15 ;;; to be taken as a null lexical environment.
16 ;;; Of course this is a mostly pointless "idiom" because NIL *is*
17 ;;; an environment, as far as most environment inquiry functions care.
18 (defun coerce-to-lexenv (x)
20 (null (make-null-lexenv))
22 #!+(and sb-fasteval
(host-feature sb-xc
))
23 (sb!interpreter
:basic-env
(sb!interpreter
:lexenv-from-env x
))))
25 ;;; Take the lexenv surrounding an inlined function and extract things
26 ;;; needed for the inline expansion suitable for dumping into fasls.
27 ;;; Right now it's MACROLET, SYMBOL-MACROLET, SPECIAL and
28 ;;; INLINE/NOTINLINE declarations. Upon encountering something else return NIL.
29 ;;; This is later used by PROCESS-INLINE-LEXENV to reproduce the lexenv.
31 ;;; Previously it just used the functions and vars of the innermost
32 ;;; lexenv, but the body of macrolet can refer to other macrolets
33 ;;; defined earlier, so it needs to process all the parent lexenvs to
34 ;;; recover the proper order.
35 (defun reconstruct-lexenv (lexenv)
39 (loop for env
= lexenv then parent
40 for parent
= (lexenv-parent env
)
41 for vars
= (lexenv-vars env
)
42 for funs
= (lexenv-funs env
)
43 for declarations
= nil
44 for symbol-macros
= nil
47 (loop for binding in vars
48 for
(name . what
) = binding
50 (find binding
(lexenv-vars parent
)))
53 (aver (eq (car what
) 'macro
))
54 (push name shadowed-vars
)
55 (push (list name
(cdr what
)) symbol-macros
))
57 (aver (eq (global-var-kind what
) :special
))
58 (push `(special ,name
) declarations
))
60 (unless (memq name shadowed-vars
)
61 (return-from reconstruct-lexenv
)))))
62 (loop for binding in funs
63 for
(name . what
) = binding
65 (find binding
(lexenv-funs parent
)))
69 (push name shadowed-funs
)
70 (push (cons name
(function-lambda-expression (cdr what
))) macros
))
71 ;; FIXME: Is there a good reason for this not to be
72 ;; DEFINED-FUN (which :INCLUDEs GLOBAL-VAR, in case
73 ;; you're wondering how this ever worked :-)? Maybe
74 ;; in conjunction with an AVERrance that it's not an
75 ;; (AND GLOBAL-VAR (NOT GLOBAL-FUN))? -- CSR,
78 (unless (defined-fun-p what
)
79 (return-from reconstruct-lexenv
))
80 (push `(,(car (rassoc (defined-fun-inlinep what
)
81 *inlinep-translations
*))
85 (unless (memq name shadowed-funs
)
86 (return-from reconstruct-lexenv
)))))
88 (setf result
(list* :declare declarations
(and result
(list result
)))))
90 (setf result
(list* :symbol-macro symbol-macros
(and result
(list result
)))))
92 (setf result
(list* :macro macros
(and result
(list result
)))))
94 (not (null-lexenv-p parent
))))
97 ;;; Return a sexpr for LAMBDA in LEXENV such that loading it from fasl
98 ;;; preserves the original lexical environment for inlining.
99 ;;; Return NIL if the lexical environment is too complicated.
100 (defun maybe-inline-syntactic-closure (lambda lexenv
)
101 (declare (type list lambda
) (type lexenv-designator lexenv
))
102 (aver (eql (first lambda
) 'lambda
))
103 ;; We used to have a trivial implementation, verifying that lexenv
104 ;; was effectively null. However, this fails to take account of the
107 ;; (declaim (inline foo))
108 ;; (macrolet ((def (x) `(defun ,x () ...)))
111 ;; which, while too complicated for the cross-compiler to handle in
112 ;; unfriendly foreign lisp environments, would be good to support in
113 ;; the target compiler. -- CSR, 2002-05-13 and 2002-11-02
116 (let ((vars (lexenv-vars lexenv
))
117 (funs (lexenv-funs lexenv
)))
118 (acond ((or (lexenv-blocks lexenv
) (lexenv-tags lexenv
)) nil
)
119 ((and (null vars
) (null funs
)) lambda
)
120 ;; If the lexenv is too hairy for cross-compilation,
121 ;; you'll find out later, when trying to perform inlining.
122 ;; This is fine, because if the inline expansion is only
123 ;; for the target, it's totally OK to cross-compile this
124 ;; defining form. The syntactic env is correctly captured.
125 ((reconstruct-lexenv lexenv
)
126 `(lambda-with-lexenv ,it
,@(cdr lambda
))))))
127 #!+(and sb-fasteval
(host-feature sb-xc
))
128 (sb!interpreter
:basic-env
129 (awhen (sb!interpreter
::reconstruct-syntactic-closure-env lexenv
)
130 `(lambda-with-lexenv ,it
,@(cdr lambda
))))
132 (null lambda
))) ; trivial case. Never occurs in the compiler.