ecl/contrib/bytecmp/bytecmp.lsp
Daniel Kochmański d75552027a compiler: bind lexically *readtable* when file is compiled
Both byte and C compilers didn't bind lexically *readtable*, what lead
to pollution of other compiled packages. Fixes #95 and #59.

Signed-off-by: Daniel Kochmański <daniel@turtleware.eu>
2015-07-28 14:25:29 +02:00

141 lines
5.2 KiB
Common Lisp
Executable file

;;;; -*- Mode: Lisp; Syntax: Common-Lisp; Package: C -*-
;;;;
;;;; Copyright (c) 1984, Taiichi Yuasa and Masami Hagiya.
;;;; Copyright (c) 1990, Giuseppe Attardi.
;;;; Copyright (c) 2001, Juan Jose Garcia Ripoll
;;;;
;;;; This program is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Library General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 2 of the License, or (at your option) any later version.
;;;;
;;;; See file '../Copyright' for full details.
;;;; BYTECMP Fake compiler which is used as a replacement when we do not
;;;; want or can have the real native compiler.
(in-package "EXT")
(defpackage "C"
(:use "CL")
(:export
"*SUPPRESS-COMPILER-WARNINGS*"
"*SUPPRESS-COMPILER-NOTES*"))
(defun bc-disassemble (thing)
(when (si::valid-function-name-p thing)
(setq thing (fdefinition thing)))
(cond ((null thing))
((functionp thing)
(si::bc-disassemble thing))
((and (consp thing)
(member (car thing) '(LAMBDA 'EXT:LAMBDA-BLOCK)))
(disassemble (compile nil thing)))
(t
(error 'simple-type-error
:datum thing
:expected-type '(OR FUNCTION (SATISFIES SI:VALID-FUNCTION-NAME-P))
:format-control "DISASSEMBLE cannot accept ~A"
:format-arguments (list thing))))
nil)
(defun bc-compile (name &optional (def nil supplied-p) &aux form)
(cond ((and supplied-p def)
(when (functionp def)
(unless (function-lambda-expression def)
(return-from bc-compile (values def nil nil)))
(setf def (function-lambda-expression def)))
(setq form (if name
`(progn (setf (symbol-function ',name) #',def) ',name)
`(setq GAZONK #',def))))
((not (fboundp name))
(error "Symbol ~s is unbound." name))
((typep (setf def (symbol-function name)) 'standard-generic-function)
(warn "COMPILE can not compile generic functions yet")
(return-from bc-compile (values def t nil)))
((null (setq form (function-lambda-expression def)))
(warn "We have lost the original function definition for ~s. Compilation failed"
name)
(return-from bc-compile (values def t nil)))
(t
(setq form `(progn (setf (symbol-function ',name) #',form) ',name))))
(values (eval form) nil nil))
(defun bc-compile-file-pathname (name &key (output-file name) (type :fasl)
verbose print c-file h-file data-file
shared-data-file system-p load external-format)
(declare (ignore load c-file h-file data-file shared-data-file system-p verbose print))
(let ((extension "fasc"))
(case type
((:fasl :fas) (setf extension "fasc"))
(t (error "In COMPILE-FILE-PATHNAME, the type ~A is unsupported." type)))
(make-pathname :type extension :defaults output-file)))
(defun bc-compile-file (input
&key
((:verbose *compile-verbose*) *compile-verbose*)
((:print *compile-print*) *compile-print*)
(load nil)
(external-format :default)
(output-file nil output-file-p)
&allow-other-keys &aux foo)
(setf output-file (if output-file-p
(pathname output-file)
(bc-compile-file-pathname input)))
(when *compile-verbose*
(format t "~&;;; Compiling ~A" input))
(cond ((not (streamp input))
(let* ((ext:*source-location* (cons (truename input) 0))
(*compile-file-pathname* (pathname (merge-pathnames input)))
(*compile-file-truename* (truename input)))
(with-open-file (sin input :direction :input)
(bc-compile-file sin :output-file output-file))))
((not output-file-p)
(error "COMPILE-FILE invoked with a stream input and no :OUTPUT-FILE"))
(t
(with-open-file (sout output-file :direction :output :if-exists :supersede
:if-does-not-exist :create
:external-format external-format)
(let ((binary (loop
with *package* = *package*
with *readtable* = *readtable*
with ext:*bytecodes-compiler* = t
for position = (file-position input)
for form = (read input nil :EOF)
until (eq form :EOF)
do (when ext::*source-location*
(rplacd ext:*source-location* position))
collect (si:eval-with-env form nil nil nil nil))))
(sys:with-ecl-io-syntax
(write binary :stream sout :circle t :escape t :readably t :pretty nil))
(terpri sout)))))
(when load
(load output-file :verbose *compile-verbose*))
(values output-file nil nil))
(defun install-bytecodes-compiler ()
(ext::package-lock (find-package :cl) nil)
(pushnew :ecl-bytecmp *features*)
(setf (fdefinition 'disassemble) #'bc-disassemble
(fdefinition 'compile) #'bc-compile
(fdefinition 'compile-file) #'bc-compile-file
(fdefinition 'compile-file-pathname) #'bc-compile-file-pathname)
(ext::package-lock (find-package :cl) t))
(defun install-c-compiler ()
(require :cmp)
(locally (declare (notinline install-c-compiler))
(funcall 'install-c-compiler)))
#-ecl-min
(progn
#+(and dlopen (not windows))
(sys::autoload "SYS:cmp" 'compile-file 'compile 'compile-file-pathname 'disassemble)
#-(and dlopen (not windows))
(install-bytecodes-compiler)
)
(provide 'BYTECMP)
#-ecl-min
(package-lock "COMMON-LISP" t)