[slime-devel] ABCL patches for SLIME HEAD

Attach please find a patch that allows SLIME HEAD to work with ABCL. This patch o does not attempt to automatically compile the files in the SLIME 'contrib' directory, as ABCL never returns when asked to compile 'contrib/swank-arglists.lisp' o allows the use of slime-compile-and-load-file (C-c C-k) by patching the definition of COMPILER-CONDITION with explicit NILs, and does a load time creation of a COMPILER-CONDITION to get the MOP discriminating functions initialized correctly Both these patches should really be addressed within the ABCL itself, but I haven't had the time to figure out these problems to the depth needed for understanding how to fix them. Patching SLIME to get around these problems at the present moment would at least stop people from complaining "SLIME is broken for ABCL", but I leave that decision up to the ruling SLIME-heads. . . -- <Mark.Evenson@gmx.at> "[T]his is not a disentanglement from, but a progressive knotting into." Index: swank-abcl.lisp =================================================================== RCS file: /project/slime/cvsroot/slime/swank-abcl.lisp,v retrieving revision 1.42 diff -u -r1.42 swank-abcl.lisp --- swank-abcl.lisp 23 Aug 2007 19:03:37 -0000 1.42 +++ swank-abcl.lisp 3 Sep 2007 09:11:52 -0000 @@ -532,6 +532,7 @@ (defimplementation quit-lisp () (ext:exit)) - - - +(let ((c (make-condition 'compiler-condition)) + (slots `(severity message short-message references location))) + (dolist (slot slots) + (funcall slot c))) Index: swank-backend.lisp =================================================================== RCS file: /project/slime/cvsroot/slime/swank-backend.lisp,v retrieving revision 1.122 diff -u -r1.122 swank-backend.lisp --- swank-backend.lisp 23 Aug 2007 19:32:56 -0000 1.122 +++ swank-backend.lisp 3 Sep 2007 09:11:52 -0000 @@ -390,14 +390,17 @@ ;; The original condition thrown by the compiler if appropriate. ;; May be NIL if a compiler does not report using conditions. :type (or null condition) + :initform nil :initarg :original-condition :accessor original-condition) (severity :type severity :initarg :severity + :initform nil :accessor severity) (message :initarg :message + :initform nil :accessor message) (short-message :initarg :short-message @@ -409,6 +412,7 @@ :accessor references) (location :initarg :location + :initform nil :accessor location))) (definterface find-external-format (coding-system) Index: swank-loader.lisp =================================================================== RCS file: /project/slime/cvsroot/slime/swank-loader.lisp,v retrieving revision 1.70 diff -u -r1.70 swank-loader.lisp --- swank-loader.lisp 31 Aug 2007 11:48:23 -0000 1.70 +++ swank-loader.lisp 3 Sep 2007 09:11:52 -0000 @@ -218,8 +218,10 @@ (append-dir fasl-directory "contrib"))) (compile-files-if-needed-serially (swank-source-files source-directory) fasl-directory t) + ;; ABCL chokes on compiling 'contrib/swank-arglists.lisp' + #-:abcl (compile-files-if-needed-serially (contrib-source-files source-directory) - contrib-fasl-directory nil) + contrib-fasl-directory nil) (set (read-from-string "swank::*swank-wire-protocol-version*") (slime-version-string)) (funcall (intern (string :warn-unimplemented-interfaces) :swank-backend))

Mark Evenson <mark.evenson@gmx.at> writes:
o does not attempt to automatically compile the files in the SLIME contrib' directory, as ABCL never returns when asked to compile contrib/swank-arglists.lisp'
Just a guess, but what I could imagine that `parse-first-valid-form-spec' in swank-arglist.lisp could possibly be the culprit, as it uses the "mapping on several lists, one being circular" trick: (mapcar #'+ '(1 2 3 4) '#1=(10 . #1#)) I'd expect this one to return (11 12 13 14), but closely rereading the CLHS entry for the mapping functions, reveals that those are actually only defined for /proper lists/. Is this something one could (and should?) reasonably expect to be de facto portable behaviour? IOW, am I to blame, or is ABCL? I figure that at least LOOP's for-as-in-list clause could be meaningfully used in the above manner. So rewriting the code in question is no problem. Still, it's something I'd like to find out what's the commonly shared opinion about this. -T.

Tobias C. Rittweiler wrote:
Just a guess, but what I could imagine that `parse-first-valid-form-spec' in swank-arglist.lisp could possibly be the culprit, as it uses the "mapping on several lists, one being circular" trick:
(mapcar #'+ '(1 2 3 4) '#1=(10 . #1#))
I'd expect this one to return (11 12 13 14), but closely rereading the CLHS entry for the mapping functions, reveals that those are actually only defined for /proper lists/.
Actually, ABCL seems to handle this form ok, returning the expected (11 12 13 14). And ABCL can compile PARSE-FIRST-VALID-FORM-SPEC from swank-arglist.lisp. The problem ABCL seems to be once again [1] in its MOP when it attempts to compile the DEFMETHODs for EXTRA-KEYWORDS with the first argument specialized on (EQL 'MAKE-INSTANCE). The following blows ABCL up with an unprintable (by SLIME) backtrace: ;;; From SLIME 'contrib/extra-keywords.lisp' r1.5 (defgeneric extra-keywords (operator &rest args) (:documentation "Return a list of extra keywords of OPERATOR (a symbol) when applied to the (unevaluated) ARGS. As a secondary value, return whether other keys are allowed. As a tertiary value, return the initial sublist of ARGS that was needed to determine the extra keywords.")) (defmethod extra-keywords ((operator (eql 'make-instance)) &rest args) (multiple-value-or (apply #'extra-keywords/make-instance operator args) (call-next-method)))
Is this something one could (and should?) reasonably expect to be de facto portable behaviour? IOW, am I to blame, or is ABCL?
I don't really feel qualified to answer about portability: all I can offer is that ABCL seems to understand the idiom correctly, but I haven't looked at the relevant code in the reader. [1]: See the discussion around http://thread.gmane.org/gmane.editors.j.devel/1397 for context. -- Mark Evenson <evenson@panix.com> "A screaming comes across the sky. It has happened before, but there is nothing to compare to it now."

"Tobias C. Rittweiler" <tcr@freebits.de> writes:
(mapcar #'+ '(1 2 3 4) '#1=(10 . #1#))
I figure that at least LOOP's for-as-in-list clause could be meaningfully used in the above manner. So rewriting the code in question is no problem. Still, it's something I'd like to find out what's the commonly shared opinion about this.
I do not like it, because it uses a tricky construct to achieve something simple. I would use something like (mapcar (curry #'+ 10) list) instead, where (defun curry (func &rest args) "Supplies @arg{args} to @arg{func} from the left." #'(lambda (&rest after-args) (apply func (append args after-args)))) is a utility function. Nicolas

Nicolas Neuss <neuss@math.uni-karlsruhe.de> writes:
I do not like it, because it uses a tricky construct to achieve something simple. I would use something like
(mapcar (curry #'+ 10) list)
(Notice that this is not currying, but partial application; hence the util is probably better named `papply' or similiarly.)

"Tobias C. Rittweiler" <tcr@freebits.de> writes:
Nicolas Neuss <neuss@math.uni-karlsruhe.de> writes:
I do not like it, because it uses a tricky construct to achieve something simple. I would use something like
(mapcar (curry #'+ 10) list)
(Notice that this is not currying, but partial application; hence the util is probably better named `papply' or similiarly.)
Hm, I think that I am at least in agreement with Graham's AnsiCL book where he calls such functions 'curry' (supplying arguments from the left) and 'rcurry' (supplying arguments from the right). Nicolas

* Tobias C. Rittweiler [2007-09-03 19:32+0200] writes:
Just a guess, but what I could imagine that `parse-first-valid-form-spec' in swank-arglist.lisp could possibly be the culprit, as it uses the "mapping on several lists, one being circular" trick: [...]
Without parse-first-valid-form-spec, ABCL can compile the file.
(mapcar #'+ '(1 2 3 4) '#1=(10 . #1#))
I'd expect this one to return (11 12 13 14), but closely rereading the CLHS entry for the mapping functions, reveals that those are actually only defined for /proper lists/.
Never heard of this trick.
Is this something one could (and should?) reasonably expect to be de facto portable behaviour? IOW, am I to blame, or is ABCL?
Don't know, but parse-first-valid-form-spec gets my vote for most obfuscated function of the month. Helmut.

On Sep 4, 2007, at 5:17 AM, Helmut Eller wrote:
* Tobias C. Rittweiler [2007-09-03 19:32+0200] writes:
Just a guess, but what I could imagine that `parse-first-valid-form-spec' in swank-arglist.lisp could possibly be the culprit, as it uses the "mapping on several lists, one being circular" trick:
(mapcar #'+ '(1 2 3 4) '#1=(10 . #1#))
I'd expect this one to return (11 12 13 14), but closely rereading the CLHS entry for the mapping functions, reveals that those are actually only defined for /proper lists/.
Never heard of this trick.
I think it's fair to consider it archaic, but it was once well known in Maclisp and early Lisp Machine Lisp. IIRC, the latter even had a builtin function `circular-list' to simplify the construction of such lists. -- Scott

* Mark Evenson [2007-09-03 11:21+0200] writes:
o allows the use of slime-compile-and-load-file (C-c C-k) by patching the definition of COMPILER-CONDITION with explicit NILs, and does a load time creation of a COMPILER-CONDITION to get the MOP discriminating functions initialized correctly
I didn't see any difference for C-c C-k with and without the patch. Can you explain what it is? I'd like to keep the definition of COMPILER-CONDITION as it is. Would it be enough to supply explicit nils in the load time form? Like so: (let ((c (make-condition 'compiler-condition :original-condition nil :severity ':note :message "" :location nil)) (slots `(severity message short-message references location))) (dolist (slot slots) (funcall slot c))) Helmut.

Helmut Eller wrote:
* Mark Evenson [2007-09-03 11:21+0200] writes:
o allows the use of slime-compile-and-load-file (C-c C-k) by patching the definition of COMPILER-CONDITION with explicit NILs, and does a load time creation of a COMPILER-CONDITION to get the MOP discriminating functions initialized correctly
I didn't see any difference for C-c C-k with and without the patch. Can you explain what it is?
On any version subsequent to (and inclusive of) ABCL-0.0.10 that I have compiled without this patch to SLIME, slime-compile-and-load-file doesn't work, producing a backtrace akin to something like [1]. I received exactly one (1) report of another user for whom this patch solved a similar problem, so I had some confidence that it would help some of the users of SLIME/ABCL. But I suspect that the the SLIME + ABCL community is fairly small, and it may be that for some unknown reason the bug only manifests itself for some versions of the JavaVM that hosts ABCL. The patch was derived from a trial and error approach from the SLIME side of things, as opposed to ABCL internals (which I am only starting to understand). Essentially, without this patch the first time SLIME tries to create a SWANK-BACKEND::COMPILER-CONDITION with sufficiently complicated arguments (/me waves hands), I would get the backtrace. But if I: 1) gave the definition of COMPILER-CONDITION explicit nil :INITFORMs 2) created an empty COMPILER-CONDITION at load-time that calls each of the readers then the bug doesn't occur. Out of curiosity, which version of ABCL on which JVM on which OS where you testing on?
I'd like to keep the definition of COMPILER-CONDITION as it is. Would it be enough to supply explicit nils in the load time form? Like so:
(let ((c (make-condition 'compiler-condition :original-condition nil :severity ':note :message "" :location nil)) (slots `(severity message short-message references location))) (dolist (slot slots) (funcall slot c)))
Using this supplied form in 'swank-abcl.lisp' doesn't help. It seems that one needs the explicit :INITFORM nil for all the COMPILER-CONDITION slots. Thanks for looking at the patch. Even if you decide not to accept it, at least this thread can give future SLIME/ABCL hackers (including me when I have the time) a place to start looking at this issue. [1]: http://article.gmane.org/gmane.editors.j.devel/1397 -- <Mark.Evenson@gmx.at> "[T]his is not a disentanglement from, but a progressive knotting into."

* Mark Evenson [2007-09-04 14:52+0200] writes:
Out of curiosity, which version of ABCL on which JVM on which OS where you testing on?
ABCL 0.0.10 (the version from the web page) Sun's JVM 1.6.0/Linux-2.6/x86
(let ((c (make-condition 'compiler-condition :original-condition nil :severity ':note :message "" :location nil)) (slots `(severity message short-message references location))) (dolist (slot slots) (funcall slot c)))
Using this supplied form in 'swank-abcl.lisp' doesn't help. It seems that one needs the explicit :INITFORM nil for all the COMPILER-CONDITION slots.
It seems to help here, at least a bit. I used this file for testing: (defun fib (number) (let ((x 1)) (if (= number 0) 1 (+ number (fib (1- number)))))) (defun foo () (bar)) #-abcl (defun baz () (if)) The warning in fib is reported as it should; the warning about the undefined function bar is only printed in the console; and I had to disable baz, because otherwise ABCL jumps to the debugger.
Thanks for looking at the patch. Even if you decide not to accept it, at least this thread can give future SLIME/ABCL hackers (including me when I have the time) a place to start looking at this issue.
I only committed my version. Helmut.
participants (6)
-
Helmut Eller
-
Mark Evenson
-
Mark Evenson
-
Nicolas Neuss
-
Scott L. Burson
-
Tobias C. Rittweiler