From: Peter v. E. <pj...@cs...> - 2009-03-22 09:43:45
|
Hi, Package locks don't seem to protect against attempting to redefine a macro as a function. Even though the package violation raises an error, the symbol is considered a function afterwards. For example, evaluating (defun defun () t) seems to render cl:defun unusable, even though one chooses to "abort" upon package lock violation. Longer transcript follows: ------------------------------ This is SBCL 1.0.22, an implementation of ANSI Common Lisp. More information about SBCL is available at <http://www.sbcl.org/>. SBCL is free software, provided as is, with absolutely no warranty. It is mostly in the public domain; some portions are provided under BSD-style licenses. See the CREDITS and COPYING files in the distribution for more information. * (defpackage :foo (:use :cl)) #<PACKAGE "FOO"> * (defmacro foo::hello () `(print "Hello")) FOO::HELLO * (foo::hello) "Hello" "Hello" * (lock-package :foo) T * (defun foo::hello () "Hello") ; in: LAMBDA NIL ; (SB-INT:NAMED-LAMBDA FOO::HELLO NIL (BLOCK FOO::HELLO "Hello")) ; ==> ; #'(SB-INT:NAMED-LAMBDA FOO::HELLO NIL (BLOCK FOO::HELLO "Hello")) ; ; caught STYLE-WARNING: ; FOO::HELLO was previously defined as a macro. ; ; compilation unit finished ; caught 1 STYLE-WARNING condition STYLE-WARNING: redefining FOO::HELLO in DEFUN debugger invoked on a SYMBOL-PACKAGE-LOCKED-ERROR in thread #<THREAD "initial thread" RUNNING {A8F78E9}>: Lock on package FOO violated when setting fdefinition of HELLO. See also: The SBCL Manual, Node "Package Locks" Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL. restarts (invokable by number or by possibly-abbreviated name): 0: [CONTINUE ] Ignore the package lock. 1: [IGNORE-ALL ] Ignore all package locks in the context of this operation. 2: [UNLOCK-PACKAGE] Unlock the package. 3: [ABORT ] Exit debugger, returning to top level. (PACKAGE-LOCK-VIOLATION #<PACKAGE "FOO">)[:EXTERNAL] 0] 3 * (foo::hello) debugger invoked on a UNDEFINED-FUNCTION in thread #<THREAD "initial thread" RUNNING {A8F78E9}>: The function FOO::HELLO is undefined. Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL. restarts (invokable by number or by possibly-abbreviated name): 0: [ABORT] Exit debugger, returning to top level. ((LAMBDA (&REST SB-C::ARGS))) 0] 0 ------------------------------ -- Peter von Etter |
From: Tobias C. R. <tc...@fr...> - 2009-03-27 21:27:20
|
Peter von Etter <pj...@cs...> writes: > Hi, > > Package locks don't seem to protect against attempting to redefine a > macro as a function. Even though the package violation raises an > error, the symbol is considered a function afterwards. > > For example, evaluating (defun defun () t) seems to render cl:defun > unusable, even though one chooses to "abort" upon package lock > violation. I glanced at this, and what I thought would be the obvious fix didn't in fact fix the problem. I then tried to come up with an extensive test case. The test case would work on the line of redefine FOO, a function, to a macro; test whether FOO is a macro? test whether FOO is a function? And do this for all kind of stuff (macro to function, function to setf expander, structure to class, etc.pp.) So I wrote a general function CLASSIFY-NAMEOID to find out all the things a name refers to. (See PS.) Basically I just grabbed the testing forms from FIND-DEFINITION-SOURCES-BY-NAME in sb-introspect.lisp. I plan to write the FIND-D-S-BY-NAME function in terms of CLASSIFY-NAMEOID. Write test cases for CLASSIFY-NAMEOID. But where should the latter function go? (As it's supposed to be used in the test suite, it cannot be placed in SB-INTROSPECT.) -T. PS (defun classify-nameoid (name) (let ((classifications '())) (flet ((push-if (conditional item) (when conditional (push item classifications))) (get-class (name) (and (symbolp name) (find-class name nil))) (real-fdefinition (name) ;; for getting the real function object, even if the ;; function is being profiled (let ((profile-info (gethash name sb-profile::*profiled-fun-name->info*))) (if profile-info (sb-profile::profile-info-encapsulated-fun profile-info) (fdefinition name))))) (push-if (and (symbolp name) (eq (sb-int:info :variable :kind name) :special)) :variable) (push-if (and (symbolp name) (eq (sb-int:info :variable :kind name) :constant)) :constant) (push-if (and (symbolp name) (macro-function name)) :macro) ... (push-if (or (sb-int:info :type :source-location name) (sb-int:info :type :expander name)) :type) (push-if (let ((n (if (and (consp name) (eq (car name) 'setf)) (cadr name) name))) (or (sb-int:info :setf :inverse n) (sb-int:info :setf :expander n))) :setf-expander) ... classifications ))) |
From: Nikodemus S. <nik...@ra...> - 2009-04-17 09:59:38
|
2009/3/27 Tobias C. Rittweiler <tc...@fr...>: > I plan to write the FIND-D-S-BY-NAME function in terms of > CLASSIFY-NAMEOID. Write test cases for CLASSIFY-NAMEOID. But where > should the latter function go? (As it's supposed to be used in the test > suite, it cannot be placed in SB-INTROSPECT.) I vote for SB-INT. Cheers, -- Nikodemus |