comparison lisp/bytecomp.el @ 5391:f9dc75bdbdc4

Implement #'load-time-value less hackishly, by modifying the byte compiler. 2011-04-02 Aidan Kehoe <kehoea@parhasard.net> * bytecomp.el (byte-compile-output-preface): New. * bytecomp.el (byte-compile-output-file-form): * bytecomp.el (byte-compile-output-docform): * bytecomp.el (byte-compile-file-form): * bytecomp.el (byte-compile-file-form-defmumble): * bytecomp.el (symbol-value): * bytecomp.el (byte-compile-symbol-value): New. * cl-macs.el (load-time-value): No longer implement load-time-value by very hackishly redefining #'byte-compile-file-form-defmumble, instead make the appropriate changes in #'byte-compile-file-form-defmumble and #'byte-compile-file-form instead. We also add a specific byte-compile method for #'symbol-value, using the add-properties-to-a-gensym approach that worked for #'block and #'return-from.
author Aidan Kehoe <kehoea@parhasard.net>
date Sat, 02 Apr 2011 16:13:20 +0100
parents eac2e6bd5b2c
children 248176c74e6b
comparison
equal deleted inserted replaced
5390:593d9f73a7e8 5391:f9dc75bdbdc4
453 "list of all variables encountered during compilation of this form") 453 "list of all variables encountered during compilation of this form")
454 (defvar byte-compile-bound-variables nil 454 (defvar byte-compile-bound-variables nil
455 "Alist of variables bound in the context of the current form, 455 "Alist of variables bound in the context of the current form,
456 that is, the current lexical environment. This list lives partly 456 that is, the current lexical environment. This list lives partly
457 on the specbind stack. The cdr of each cell is an integer bitmask.") 457 on the specbind stack. The cdr of each cell is an integer bitmask.")
458 (defvar byte-compile-output-preface nil
459 "Form to output before current by `byte-compile-output-file-form'
460 This is used for implementing `load-time-value'.")
458 461
459 (defvar byte-compile-force-escape-quoted nil 462 (defvar byte-compile-force-escape-quoted nil
460 "If t, `byte-compile-maybe-reset-coding' always chooses `escape-quoted' 463 "If t, `byte-compile-maybe-reset-coding' always chooses `escape-quoted'
461 464
462 This is for situations where the byte compiler output file needs to be 465 This is for situations where the byte compiler output file needs to be
1975 (print-readably t) ; print #[] for bytecode, 'x for (quote x) 1978 (print-readably t) ; print #[] for bytecode, 'x for (quote x)
1976 (print-gensym (if (and byte-compile-print-gensym 1979 (print-gensym (if (and byte-compile-print-gensym
1977 (not byte-compile-emacs19-compatibility)) 1980 (not byte-compile-emacs19-compatibility))
1978 '(t) nil)) 1981 '(t) nil))
1979 print-gensym-alist) 1982 print-gensym-alist)
1983 (when byte-compile-output-preface
1984 (princ "\n(progn " byte-compile-outbuffer)
1985 (prin1 byte-compile-output-preface byte-compile-outbuffer))
1980 (princ "\n" byte-compile-outbuffer) 1986 (princ "\n" byte-compile-outbuffer)
1981 (prin1 form byte-compile-outbuffer) 1987 (prin1 form byte-compile-outbuffer)
1988 (when byte-compile-output-preface (princ ")" byte-compile-outbuffer))
1982 nil))) 1989 nil)))
1983 1990
1984 (defun byte-compile-output-docform (preface name info form specindex quoted) 1991 (defun byte-compile-output-docform (preface name info form specindex quoted)
1985 "Print a form with a doc string. INFO is (prefix doc-index postfix). 1992 "Print a form with a doc string. INFO is (prefix doc-index postfix).
1986 If PREFACE and NAME are non-nil, print them too, 1993 If PREFACE and NAME are non-nil, print them too,
2014 ;; negate POSITION. 2021 ;; negate POSITION.
2015 (if (and (stringp (nth (nth 1 info) form)) 2022 (if (and (stringp (nth (nth 1 info) form))
2016 (> (length (nth (nth 1 info) form)) 0) 2023 (> (length (nth (nth 1 info) form)) 0)
2017 (char= (aref (nth (nth 1 info) form) 0) ?*)) 2024 (char= (aref (nth (nth 1 info) form) 0) ?*))
2018 (setq position (- position))))) 2025 (setq position (- position)))))
2019
2020 (if preface
2021 (progn
2022 (insert preface)
2023 (prin1 name byte-compile-outbuffer)))
2024 (insert (car info))
2025 (let ((print-escape-newlines t) 2026 (let ((print-escape-newlines t)
2026 (print-readably t) ; print #[] for bytecode, 'x for (quote x) 2027 (print-readably t) ; print #[] for bytecode, 'x for (quote x)
2027 ;; Use a cons cell to say that we want 2028 ;; Use a cons cell to say that we want
2028 ;; print-gensym-alist not to be cleared between calls 2029 ;; print-gensym-alist not to be cleared between calls
2029 ;; to print functions. 2030 ;; to print functions.
2030 (print-gensym (if (and byte-compile-print-gensym 2031 (print-gensym (if (and byte-compile-print-gensym
2031 (not byte-compile-emacs19-compatibility)) 2032 (not byte-compile-emacs19-compatibility))
2032 '(t) nil)) 2033 '(t) nil))
2033 print-gensym-alist 2034 print-gensym-alist
2034 (index 0)) 2035 (index 0))
2036 (when byte-compile-output-preface
2037 (princ "\n(progn " byte-compile-outbuffer)
2038 (prin1 byte-compile-output-preface byte-compile-outbuffer))
2039 (byte-compile-flush-pending)
2040 (if preface
2041 (progn
2042 (insert preface)
2043 (prin1 name byte-compile-outbuffer)))
2044 (insert (car info))
2035 (prin1 (car form) byte-compile-outbuffer) 2045 (prin1 (car form) byte-compile-outbuffer)
2036 (while (setq form (cdr form)) 2046 (while (setq form (cdr form))
2037 (setq index (1+ index)) 2047 (setq index (1+ index))
2038 (insert " ") 2048 (insert " ")
2039 (cond ((and (numberp specindex) (= index specindex)) 2049 (cond ((and (numberp specindex) (= index specindex))
2056 byte-compile-outbuffer))) 2066 byte-compile-outbuffer)))
2057 (insert "\\\n") 2067 (insert "\\\n")
2058 (goto-char (point-max))))) 2068 (goto-char (point-max)))))
2059 (t 2069 (t
2060 (prin1 (car form) byte-compile-outbuffer))))) 2070 (prin1 (car form) byte-compile-outbuffer)))))
2061 (insert (nth 2 info)))))) 2071 (insert (nth 2 info))
2072 (when byte-compile-output-preface
2073 (princ ")" byte-compile-outbuffer))))))
2062 nil) 2074 nil)
2063 2075
2064 (defvar for-effect) ; ## Kludge! This should be an arg, not a special. 2076 (defvar for-effect) ; ## Kludge! This should be an arg, not a special.
2065 2077
2066 (defun byte-compile-keep-pending (form &optional handler) 2078 (defun byte-compile-keep-pending (form &optional handler)
2092 byte-compile-maxdepth 0 2104 byte-compile-maxdepth 0
2093 byte-compile-output nil)))) 2105 byte-compile-output nil))))
2094 2106
2095 (defun byte-compile-file-form (form) 2107 (defun byte-compile-file-form (form)
2096 (let ((byte-compile-current-form nil) ; close over this for warnings. 2108 (let ((byte-compile-current-form nil) ; close over this for warnings.
2109 (byte-compile-output-preface nil)
2097 handler) 2110 handler)
2098 (cond 2111 (cond
2099 ((not (consp form)) 2112 ((not (consp form))
2100 (byte-compile-keep-pending form)) 2113 (byte-compile-keep-pending form))
2101 ((and (symbolp (car form)) 2114 ((and (symbolp (car form))
2327 (nth 1 form)))) 2340 (nth 1 form))))
2328 (let* ((new-one (byte-compile-lambda (cons 'lambda (nthcdr 2 form)))) 2341 (let* ((new-one (byte-compile-lambda (cons 'lambda (nthcdr 2 form))))
2329 (code (byte-compile-byte-code-maker new-one)) 2342 (code (byte-compile-byte-code-maker new-one))
2330 (docform-info 2343 (docform-info
2331 (cond ((atom code) ; compiled-function-p 2344 (cond ((atom code) ; compiled-function-p
2332 (if macrop '(" '(macro . #[" 4 "])") '(" #[" 4 "]"))) 2345 (if macrop '(" '(macro . #[" 4 "]))") '(" #[" 4 "])")))
2333 ((eq (car code) 'quote) 2346 ((eq (car code) 'quote)
2334 (setq code new-one) 2347 (setq code new-one)
2335 (if macrop '(" '(macro " 2 ")") '(" '(" 2 ")"))) 2348 (if macrop '(" '(macro " 2 "))") '(" '(" 2 "))")))
2336 ((if macrop '(" (cons 'macro (" 5 "))") '(" (" 5 ")")))))) 2349 ((if macrop '(" (cons 'macro (" 5 ")))") '(" (" 5 "))"))))))
2337 (if this-one 2350 (if this-one
2338 (setcdr this-one new-one) 2351 (setcdr this-one new-one)
2339 (set this-kind 2352 (set this-kind
2340 (cons (cons name new-one) (symbol-value this-kind)))) 2353 (cons (cons name new-one) (symbol-value this-kind))))
2341 (if (and (stringp (nth 3 form)) 2354 (if (and (stringp (nth 3 form))
2358 ;; compiled-function object, or a list of some kind. If it's not a 2371 ;; compiled-function object, or a list of some kind. If it's not a
2359 ;; cons, we must coerce it into a list of the elements to be 2372 ;; cons, we must coerce it into a list of the elements to be
2360 ;; printed to the file. 2373 ;; printed to the file.
2361 (if (consp code) 2374 (if (consp code)
2362 code 2375 code
2363 (nconc (list 2376 (list* (compiled-function-arglist code)
2364 (compiled-function-arglist code) 2377 (compiled-function-instructions code)
2365 (compiled-function-instructions code) 2378 (compiled-function-constants code)
2366 (compiled-function-constants code) 2379 (compiled-function-stack-depth code)
2367 (compiled-function-stack-depth code) 2380 (compiled-function-doc-string code)
2368 (compiled-function-doc-string code))
2369 (if (commandp code) 2381 (if (commandp code)
2370 (list (nth 1 (compiled-function-interactive code)))))) 2382 (list (nth 1 (compiled-function-interactive code))))))
2371 (and (atom code) byte-compile-dynamic 2383 (and (atom code) byte-compile-dynamic
2372 1) 2384 1)
2373 nil)) 2385 nil))
2374 (princ ")" byte-compile-outbuffer)
2375 nil))) 2386 nil)))
2376 2387
2377 ;; Print Lisp object EXP in the output file, inside a comment, 2388 ;; Print Lisp object EXP in the output file, inside a comment,
2378 ;; and return the file position it will have. 2389 ;; and return the file position it will have.
2379 ;; If QUOTED is non-nil, print with quoting; otherwise, print without quoting. 2390 ;; If QUOTED is non-nil, print with quoting; otherwise, print without quoting.
3141 (byte-defop-compiler not 1) 3152 (byte-defop-compiler not 1)
3142 (byte-defop-compiler (null byte-not) 1) 3153 (byte-defop-compiler (null byte-not) 1)
3143 (byte-defop-compiler car 1) 3154 (byte-defop-compiler car 1)
3144 (byte-defop-compiler cdr 1) 3155 (byte-defop-compiler cdr 1)
3145 (byte-defop-compiler length 1) 3156 (byte-defop-compiler length 1)
3146 (byte-defop-compiler symbol-value 1) 3157 (byte-defop-compiler symbol-value)
3147 (byte-defop-compiler symbol-function 1) 3158 (byte-defop-compiler symbol-function 1)
3148 (byte-defop-compiler (1+ byte-add1) 1) 3159 (byte-defop-compiler (1+ byte-add1) 1)
3149 (byte-defop-compiler (1- byte-sub1) 1) 3160 (byte-defop-compiler (1- byte-sub1) 1)
3150 (byte-defop-compiler goto-char 1+1) 3161 (byte-defop-compiler goto-char 1+1)
3151 (byte-defop-compiler char-after 0-1+1) 3162 (byte-defop-compiler char-after 0-1+1)
4312 (byte-compile-form (car (cdr form))) 4323 (byte-compile-form (car (cdr form)))
4313 (byte-compile-out 'byte-temp-output-buffer-setup 0) 4324 (byte-compile-out 'byte-temp-output-buffer-setup 0)
4314 (byte-compile-body (cdr (cdr form))) 4325 (byte-compile-body (cdr (cdr form)))
4315 (byte-compile-out 'byte-temp-output-buffer-show 0)) 4326 (byte-compile-out 'byte-temp-output-buffer-show 0))
4316 4327
4328 (defun byte-compile-symbol-value (form)
4329 (symbol-macrolet ((not-present '#:not-present))
4330 (let ((cl-load-time-value-form not-present)
4331 (byte-compile-bound-variables byte-compile-bound-variables) gensym)
4332 (and (consp (cadr form))
4333 (eq 'quote (caadr form))
4334 (setq gensym (cadadr form))
4335 (symbolp gensym)
4336 (setq cl-load-time-value-form
4337 (get gensym 'cl-load-time-value-form not-present)))
4338 (unless (eq cl-load-time-value-form not-present)
4339 (setq byte-compile-bound-variables
4340 (acons gensym byte-compile-global-bit
4341 byte-compile-bound-variables)
4342 byte-compile-output-preface
4343 (byte-compile-top-level
4344 (if byte-compile-output-preface
4345 `(progn (setq ,gensym ,cl-load-time-value-form)
4346 ,byte-compile-output-preface)
4347 `(setq ,gensym ,cl-load-time-value-form))
4348 t 'file)))
4349 (byte-compile-one-arg form))))
4350
4317 (defun byte-compile-multiple-value-call (form) 4351 (defun byte-compile-multiple-value-call (form)
4318 (if (< (length form) 2) 4352 (if (< (length form) 2)
4319 (progn 4353 (progn
4320 (byte-compile-warn-wrong-args form 1) 4354 (byte-compile-warn-wrong-args form 1)
4321 (byte-compile-normal-call 4355 (byte-compile-normal-call