Compiled COMPILE forms at load time Bug
CMUCL's file compiler does not correctly compile "top level" COMPILE forms in the source. Quick sketch: $ echo '(compile nil (lambda (x) x))' > foo.lisp $ lisp -noinit * (compile-file "foo.lisp") * (load *) At FASL Load Time this results in an error, with a `back' stack that looks like: Type-error in KERNEL::OBJECT-NOT-TYPE-ERROR-HANDLER: NIL is not of type C::DEBUG-SOURCE 0: (FUNCTION-LAMBDA-EXPRESSION #<Function "COMPILE NIL" {5863BFB1}>) 1: (C::GET-LAMBDA-TO-COMPILE #<Function "COMPILE NIL" {5863BFB1}>) 2: ((FLET #:G0 COMPILE)) 3: (COMPILE NIL #<Function "COMPILE NIL" {5863BFB1}>) 4: (COMPILE 2 NIL #<Function "COMPILE NIL" {5863BFB1}>)[:EXTERNAL] 5: (C::DO-CALL #<Code Object "Top-Level Form" {5863C087}> 4 5 4 ...) 6: (LISP::FOP-FUNCALL-FOR-EFFECT) 7: (LISP::LOAD-GROUP #<Stream for file "/home/madhu/foo.x86f">) 8: (LISP::FASLOAD #<Stream for file "/home/madhu/foo.x86f">) 9: (LISP::INTERNAL-LOAD #P"/home/madhu/foo.x86f" #P"/home/madhu/foo.x86f" :ERROR :BINARY ...) [I think this behaviour has been around for a long time (?), and it is a bug because it prevents you from ensuring compiled functions are stored in DEFVAR forms.] -- Madhu
On 2/14/10 12:50 PM, Madhu wrote:
CMUCL's file compiler does not correctly compile "top level" COMPILE forms in the source. Quick sketch:
$ echo '(compile nil (lambda (x) x))' > foo.lisp $ lisp -noinit * (compile-file "foo.lisp") * (load *)
At FASL Load Time this results in an error, with a `back' stack that looks like:
Type-error in KERNEL::OBJECT-NOT-TYPE-ERROR-HANDLER: NIL is not of type C::DEBUG-SOURCE
0: (FUNCTION-LAMBDA-EXPRESSION #<Function "COMPILE NIL" {5863BFB1}>)
This immediate issue can be fixed by modifying function-lambda-expression in eval.lisp. In the first clause of the cond expression, change it to (and source (eq (c::debug-source-from source) :lisp) ...). That takes care of that problem. But now cmucl will complain that the function is the function #<Function "COMPILE NIL"> was defined in a non-null lexical environment. I don't know if that's right or not. Ray
* Raymond Toy [2010-02-14 21:04+0100] writes:
This immediate issue can be fixed by modifying function-lambda-expression in eval.lisp. In the first clause of the cond expression, change it to (and source (eq (c::debug-source-from source) :lisp) ...).
That takes care of that problem. But now cmucl will complain that the function is the function #<Function "COMPILE NIL"> was defined in a non-null lexical environment. I don't know if that's right or not.
Seems like a cryptic way to say that the lambda-expression isn't available. But we don't need the lambda-expression. To quote the CLHS entry for compile: If the definition is already a compiled function, compile either produces that function itself (i.e., is an identity operation) or an equivalent function. We could probably fix the problem by binding form in compile in main.lisp with something like this: (form (etypecase definition ((or cons eval:interpreted-function) `#',(get-lambda-to-compile definition)) (function `',definition))) Helmut
On 2/14/10 4:15 PM, Helmut Eller wrote:
* Raymond Toy [2010-02-14 21:04+0100] writes:
This immediate issue can be fixed by modifying function-lambda-expression in eval.lisp. In the first clause of the cond expression, change it to (and source (eq (c::debug-source-from source) :lisp) ...).
That takes care of that problem. But now cmucl will complain that the function is the function #<Function "COMPILE NIL"> was defined in a non-null lexical environment. I don't know if that's right or not.
Seems like a cryptic way to say that the lambda-expression isn't available.
But we don't need the lambda-expression. To quote the CLHS entry for compile:
If the definition is already a compiled function, compile either produces that function itself (i.e., is an identity operation) or an equivalent function.
We could probably fix the problem by binding form in compile in main.lisp with something like this:
(form (etypecase definition ((or cons eval:interpreted-function) `#',(get-lambda-to-compile definition)) (function `',definition)))
That certainly fixes the problem. I'll want to run a few other tests on this and if all goes well, I'll check it in. Thanks! Ray
On 2/14/10 4:15 PM, Helmut Eller wrote:
We could probably fix the problem by binding form in compile in main.lisp with something like this:
(form (etypecase definition ((or cons eval:interpreted-function) `#',(get-lambda-to-compile definition)) (function `',definition)))
Oops. I checked in this change and it's in the March snapshot. But it also breaks something that used to work: (defun foo (x y) (+ x y)) (compile 'foo) (compile 'foo) This used to work. Now the second compile generates an error about FOO being undefined. Ray
On 3/10/10 9:24 AM, Raymond Toy wrote:
On 2/14/10 4:15 PM, Helmut Eller wrote:
We could probably fix the problem by binding form in compile in main.lisp with something like this:
(form (etypecase definition ((or cons eval:interpreted-function) `#',(get-lambda-to-compile definition)) (function `',definition)))
Oops. I checked in this change and it's in the March snapshot. But it also breaks something that used to work:
(defun foo (x y) (+ x y)) (compile 'foo) (compile 'foo)
This used to work. Now the second compile generates an error about FOO being undefined.
Perhaps the following change would work. It makes the old behavior work again, and still fixes the compile form issue: (form (etypecase definition ((or cons eval:interpreted-function) `#',(get-lambda-to-compile definition)) (function (multiple-value-bind (exp lexenv) (function-lambda-expression definition) (if (and exp (not lexenv)) `#',exp `',definition))))) (Perhaps this can be written in a better way. The second etypecase clause is like get-lambda-to-compile, except we don't signal an error.) I think we still need the additional fix in function-lambda-expression in case the compiled-debug-info-source is NIL. Ray
* Raymond Toy [2010-03-10 17:26+0100] writes:
On 3/10/10 9:24 AM, Raymond Toy wrote:
On 2/14/10 4:15 PM, Helmut Eller wrote:
We could probably fix the problem by binding form in compile in main.lisp with something like this:
(form (etypecase definition ((or cons eval:interpreted-function) `#',(get-lambda-to-compile definition)) (function `',definition)))
Oops. I checked in this change and it's in the March snapshot. But it also breaks something that used to work:
(defun foo (x y) (+ x y)) (compile 'foo) (compile 'foo)
This used to work. Now the second compile generates an error about FOO being undefined.
Who would have thought that writing an identity function could be so hard :-)
Perhaps the following change would work. It makes the old behavior work again, and still fixes the compile form issue:
(form (etypecase definition ((or cons eval:interpreted-function) `#',(get-lambda-to-compile definition)) (function (multiple-value-bind (exp lexenv) (function-lambda-expression definition) (if (and exp (not lexenv)) `#',exp `',definition)))))
(Perhaps this can be written in a better way. The second etypecase clause is like get-lambda-to-compile, except we don't signal an error.)
We could add this (when (typep definition '(and function (not eval:interpreted-function))) (when name (setf (fdefinition name) definition)) (return-from compile (values definition nil nil))) right before the with-compilation-unit form. We can't return-from inside the with-compilation-unit without producing some error message so we have to put it before it. We'd lose some restarts, but that should only be noticeable if (setf (fdefinition ..)) hits a definition lock and it's not required by the spec anyway. Then form would be bound as it used to be (form `#',(get-lambda-to-compile definition).
I think we still need the additional fix in function-lambda-expression in case the compiled-debug-info-source is NIL.
I think we always have the lambda expression for interpreted functions. Helmut
One more thing: (defmacro bar () 1) (compile 'bar '(lambda () 2)) should remove the macro binding for bar. COMPILE has my vote for most stupid interface of this year. Helmut
On 3/10/10 1:47 PM, Helmut Eller wrote:
One more thing:
(defmacro bar () 1) (compile 'bar '(lambda () 2))
should remove the macro binding for bar.
I agree. I think I've figured out how to remove the macro binding and will be checking it in shortly. Ray
On 3/11/10 9:58 PM, Raymond Toy wrote:
On 3/10/10 1:47 PM, Helmut Eller wrote:
One more thing:
(defmacro bar () 1) (compile 'bar '(lambda () 2))
should remove the macro binding for bar.
I agree. I think I've figured out how to remove the macro binding and will be checking it in shortly.
Another issue. This is ok: * (defstruct rrr a) RRR * (defun rrr-a () 42) Warning: Undefining structure type: RRR so that this slot accessor can be redefined: RRR-A RRR-A But: * (defstruct zzz a) ZZZ * (compile 'zzz-a '(lambda () 42)) ; Compiling LAMBDA NIL: ; Compiling Top-Level Form: ZZZ-A NIL NIL * (zzz-a) 42 * (make-zzz) Invalid number of arguments: 1 So COMPILE has silently zapped the structure. We should probably print he warning for this too. Note that in both cases any existing structures will be in a bad state. They still exist, but there's not much you can do with them. Ray
* Raymond Toy [2010-03-12 12:35+0100] writes:
So COMPILE has silently zapped the structure. We should probably print he warning for this too.
Yes, definitely. Also for this: (defstruct xyz a) (setf (fdefinition 'xyz-a) (lambda () 42))
Note that in both cases any existing structures will be in a bad state. They still exist, but there's not much you can do with them.
Compiled could would continue to work since accessors are inlined. Also (type-of (make-xyz)) still works. The printer is effed up, though. Helmut
On 3/12/10 11:45 AM, Helmut Eller wrote:
* Raymond Toy [2010-03-12 12:35+0100] writes:
So COMPILE has silently zapped the structure. We should probably print he warning for this too.
Yes, definitely. Also for this:
(defstruct xyz a) (setf (fdefinition 'xyz-a) (lambda () 42))
I added a hook to *setf-fdefinition-hook* to check for this case. Works ok, but now I can't compile clx/depdefs.lisp. CMUCL complains about redefining reply-size and buffer-lock which are slot accessor functions. But I haven't figured out from the code where the redefinition is coming from. Also, consider this: (defstruct abc a b c) (defun abc-a () 42) CMUCL undefines the structure, but (defstruct abc a) produces an error about incompatibly redefining the structure.
Note that in both cases any existing structures will be in a bad state. They still exist, but there's not much you can do with them.
Compiled could would continue to work since accessors are inlined. Also (type-of (make-xyz)) still works. The printer is effed up, though.
If we undefined the structure, I would expect make-xyz (or make-abc) not to work. What to do? Ray
* Raymond Toy [2010-03-15 15:01+0100] writes:
On 3/12/10 11:45 AM, Helmut Eller wrote:
* Raymond Toy [2010-03-12 12:35+0100] writes:
So COMPILE has silently zapped the structure. We should probably print he warning for this too.
Yes, definitely. Also for this:
(defstruct xyz a) (setf (fdefinition 'xyz-a) (lambda () 42))
I added a hook to *setf-fdefinition-hook* to check for this case. Works ok, but now I can't compile clx/depdefs.lisp. CMUCL complains about redefining reply-size and buffer-lock which are slot accessor functions. But I haven't figured out from the code where the redefinition is coming from.
Also, consider this:
(defstruct abc a b c) (defun abc-a () 42)
CMUCL undefines the structure, but
CMUCL undefines the structure? That seems a bit aggressive. I think it should only delete the (c:info function info 'abc-a) entry if that's not done yet. The compiler uses that to recognize "known" functions. I don't know if (setf abc-a) still works if the info entry for abc-a is cleared.
(defstruct abc a)
produces an error about incompatibly redefining the structure.
That seems totally OK to me.
Note that in both cases any existing structures will be in a bad state. They still exist, but there's not much you can do with them.
Compiled could would continue to work since accessors are inlined. Also (type-of (make-xyz)) still works. The printer is effed up, though.
If we undefined the structure, I would expect make-xyz (or make-abc) not to work.
What to do?
I wouldn't undefine the entire structure; only redefine the named accessor function. For the printer we could come up with something like SLOT-VALUE but it should work without PCL. Helmut
On 3/15/10 10:45 AM, Helmut Eller wrote:
* Raymond Toy [2010-03-15 15:01+0100] writes:
On 3/12/10 11:45 AM, Helmut Eller wrote:
* Raymond Toy [2010-03-12 12:35+0100] writes:
So COMPILE has silently zapped the structure. We should probably print he warning for this too.
Yes, definitely. Also for this:
(defstruct xyz a) (setf (fdefinition 'xyz-a) (lambda () 42))
I added a hook to *setf-fdefinition-hook* to check for this case. Works ok, but now I can't compile clx/depdefs.lisp. CMUCL complains about redefining reply-size and buffer-lock which are slot accessor functions. But I haven't figured out from the code where the redefinition is coming from.
Also, consider this:
(defstruct abc a b c) (defun abc-a () 42)
CMUCL undefines the structure, but
CMUCL undefines the structure? That seems a bit aggressive. I think it should only delete the (c:info function info 'abc-a) entry if that's not done yet. The compiler uses that to recognize "known" functions.
The code that does this is define-function-name in proclaim.lisp. If the name is an accessor-for, then undefine-structure is called. The comment for undefine-structure says it's supposed to blow away all compiler info and undefining all associated functions.
I don't know if (setf abc-a) still works if the info entry for abc-a is cleared.
(defstruct abc a)
produces an error about incompatibly redefining the structure.
That seems totally OK to me.
Well, I was expecting that if we undefined the structure, then there would be no information about the structure, and hence didn't exist. But perhaps that can't be completely true if there are already structure objects of that type.
If we undefined the structure, I would expect make-xyz (or make-abc) not to work.
What to do?
I wouldn't undefine the entire structure; only redefine the named
That's the historical behavior, but I don't think I've ever run into this before, even when playing around. I only noticed this when looking at compile and define-function-name to see how things worked.
accessor function. For the printer we could come up with something like SLOT-VALUE but it should work without PCL.
There's probably some way to do this without PCL. Ray
* Raymond Toy [2010-03-15 16:18+0100] writes:
On 3/15/10 10:45 AM, Helmut Eller wrote:
* Raymond Toy [2010-03-15 15:01+0100] writes:
On 3/12/10 11:45 AM, Helmut Eller wrote:
* Raymond Toy [2010-03-12 12:35+0100] writes:
So COMPILE has silently zapped the structure. We should probably print he warning for this too.
Yes, definitely. Also for this:
(defstruct xyz a) (setf (fdefinition 'xyz-a) (lambda () 42))
I added a hook to *setf-fdefinition-hook* to check for this case. Works ok, but now I can't compile clx/depdefs.lisp. CMUCL complains about redefining reply-size and buffer-lock which are slot accessor functions. But I haven't figured out from the code where the redefinition is coming from.
Also, consider this:
(defstruct abc a b c) (defun abc-a () 42)
CMUCL undefines the structure, but
CMUCL undefines the structure? That seems a bit aggressive. I think it should only delete the (c:info function info 'abc-a) entry if that's not done yet. The compiler uses that to recognize "known" functions.
The code that does this is define-function-name in proclaim.lisp. If the name is an accessor-for, then undefine-structure is called. The comment for undefine-structure says it's supposed to blow away all compiler info and undefining all associated functions.
Now I see. It looks like undefine-function-name would be more adequate or just fmakunbound. It's a bit troubling that c:%%defun does so much more than a simple (setf (fdefinition ..)). If a user calls (setf (fdefinition ..)) directly the various bits in the info db are not cleaned out.
I don't know if (setf abc-a) still works if the info entry for abc-a is cleared.
(defstruct abc a)
produces an error about incompatibly redefining the structure.
That seems totally OK to me.
Well, I was expecting that if we undefined the structure, then there would be no information about the structure, and hence didn't exist. But perhaps that can't be completely true if there are already structure objects of that type.
Hmm... looks like undefine-structure doesn't delete the (info type class ..) bit which still points to the defstruct description. Helmut
On 3/15/10 1:58 PM, Helmut Eller wrote:
* Raymond Toy [2010-03-15 16:18+0100] writes:
On 3/15/10 10:45 AM, Helmut Eller wrote:
* Raymond Toy [2010-03-15 15:01+0100] writes:
On 3/12/10 11:45 AM, Helmut Eller wrote:
* Raymond Toy [2010-03-12 12:35+0100] writes:
So COMPILE has silently zapped the structure. We should probably print he warning for this too.
Yes, definitely. Also for this:
(defstruct xyz a) (setf (fdefinition 'xyz-a) (lambda () 42))
I added a hook to *setf-fdefinition-hook* to check for this case. Works ok, but now I can't compile clx/depdefs.lisp. CMUCL complains about redefining reply-size and buffer-lock which are slot accessor functions. But I haven't figured out from the code where the redefinition is coming from.
Also, consider this:
(defstruct abc a b c) (defun abc-a () 42)
CMUCL undefines the structure, but
CMUCL undefines the structure? That seems a bit aggressive. I think it should only delete the (c:info function info 'abc-a) entry if that's not done yet. The compiler uses that to recognize "known" functions.
The code that does this is define-function-name in proclaim.lisp. If the name is an accessor-for, then undefine-structure is called. The comment for undefine-structure says it's supposed to blow away all compiler info and undefining all associated functions.
Now I see. It looks like undefine-function-name would be more adequate or just fmakunbound.
Yeah, that would work too. I guess we need to decide what we really want to happen if you try to redefine a structure accessor. Undefining the structure seems a bit heavy-handed, especially since we just warn afterwards instead of signaling at least a continuable error. We could just allow the redefinition and assume (or perhaps check) that the new function at least takes the same arguments.
It's a bit troubling that c:%%defun does so much more than a simple (setf (fdefinition ..)). If a user calls (setf (fdefinition ..))
%%defun doesn't seem like so much to me; it looks like it's just setting up the compiler info db with the appropriate info.
directly the various bits in the info db are not cleaned out.
That's probably an oversight; we can add another *setf-fdefinition-hook* to clear out the info db or update the info db based on what ever information we have about the new fdefinition function. Ray
* Raymond Toy [2010-03-15 22:49+0100] writes:
The code that does this is define-function-name in proclaim.lisp. If the name is an accessor-for, then undefine-structure is called. The comment for undefine-structure says it's supposed to blow away all compiler info and undefining all associated functions.
Now I see. It looks like undefine-function-name would be more adequate or just fmakunbound.
Yeah, that would work too. I guess we need to decide what we really want to happen if you try to redefine a structure accessor. Undefining the structure seems a bit heavy-handed, especially since we just warn afterwards instead of signaling at least a continuable error. We could just allow the redefinition and assume (or perhaps check) that the new function at least takes the same arguments.
For (defun some-existing-accessor ..) I'd like to see a warning at compile time--if it can be done easily. At load time, a cerror if the whole structure gets removed; no warning if only the accessor gets overwritten. We have already definition locks which can be used for more delicate accessor names.
It's a bit troubling that c:%%defun does so much more than a simple (setf (fdefinition ..)). If a user calls (setf (fdefinition ..))
%%defun doesn't seem like so much to me; it looks like it's just setting up the compiler info db with the appropriate info.
directly the various bits in the info db are not cleaned out.
That's probably an oversight; we can add another *setf-fdefinition-hook* to clear out the info db or update the info db based on what ever information we have about the new fdefinition function.
On one side (setf (fdefinition ..)) should delete/overwrite the stuff that a previous %%defun left in the info db. On the other hand, if the user wants to update the info db he can and should use defun. Hmm.. actually I prefer the latter, i.e. what CMUCL does currently. Helmut
On 3/16/10 7:16 AM, Helmut Eller wrote:
For (defun some-existing-accessor ..) I'd like to see a warning at compile time--if it can be done easily. This already happens. A simple test shows that we get the warning when compiling, and another warning when loading the fasl.
At load time, a cerror if the whole structure gets removed; no warning if only the accessor gets overwritten. We have already definition locks which can be used for more delicate accessor names.
I didn't quite follow you here. We already get a cerror if we redefine a structure. So if an accessor is redefined, we just silently allow it?
On one side (setf (fdefinition ..)) should delete/overwrite the stuff that a previous %%defun left in the info db. On the other hand, if the user wants to update the info db he can and should use defun. Hmm.. actually I prefer the latter, i.e. what CMUCL does currently.
Sounds good to me. Ray
* Raymond Toy [2010-03-16 14:18+0100] writes:
At load time, a cerror if the whole structure gets removed; no warning if only the accessor gets overwritten. We have already definition locks which can be used for more delicate accessor names.
I didn't quite follow you here. We already get a cerror if we redefine a structure. So if an accessor is redefined, we just silently allow it?
I would not expect that defun can undefine a structure and therefore I would like to see a warning. That defun can redefine a accessor function seems normal to me; at least no different than redefining an inlineable function. Also those load time warnings tend be confusing because it's hard to give a source location. If a warning was already given at compile time, there's little need to repeat it at load time. Helmut
On 3/15/10 1:58 PM, Helmut Eller wrote:
* Raymond Toy [2010-03-15 16:18+0100] writes:
On 3/15/10 10:45 AM, Helmut Eller wrote:
* Raymond Toy [2010-03-15 15:01+0100] writes:
On 3/12/10 11:45 AM, Helmut Eller wrote:
* Raymond Toy [2010-03-12 12:35+0100] writes:
So COMPILE has silently zapped the structure. We should probably print he warning for this too.
Yes, definitely. Also for this:
(defstruct xyz a) (setf (fdefinition 'xyz-a) (lambda () 42))
I added a hook to *setf-fdefinition-hook* to check for this case. Works ok, but now I can't compile clx/depdefs.lisp. CMUCL complains about redefining reply-size and buffer-lock which are slot accessor functions. But I haven't figured out from the code where the redefinition is coming from.
Also, consider this:
(defstruct abc a b c) (defun abc-a () 42)
CMUCL undefines the structure, but
CMUCL undefines the structure? That seems a bit aggressive. I think it should only delete the (c:info function info 'abc-a) entry if that's not done yet. The compiler uses that to recognize "known" functions.
The code that does this is define-function-name in proclaim.lisp. If the name is an accessor-for, then undefine-structure is called. The comment for undefine-structure says it's supposed to blow away all compiler info and undefining all associated functions.
Now I see. It looks like undefine-function-name would be more adequate or just fmakunbound.
I tried undefine-function-name instead of undefine-structure. It works, but having a redefined structure accessor that doesn't really work is a problem. For example, (defstruct abc a) (defun abc-a (x) 42) (make-abc :a 'a) -> #S(abc :a 42) This seems not good either. Maybe disallowing redefining structure-accessors this way is the best; don't kill the structure, don't allow redefinition of the accessor either. Ray
* Raymond Toy [2010-03-16 04:41+0100] writes:
I tried undefine-function-name instead of undefine-structure. It works, but having a redefined structure accessor that doesn't really work is a problem. For example,
(defstruct abc a) (defun abc-a (x) 42) (make-abc :a 'a) -> #S(abc :a 42)
This seems not good either.
default-structure-print calls (fdefinition (dsd-accessor slot)). We could change that to %instance-ref. That would also help in this case: (defstruct abc a) (fmakunbound 'abc-a) (make-abc :a 'a) -> error during printing Unfortunately, there are other places that call dsd-accessor by name. Like inspect.
Maybe disallowing redefining structure-accessors this way is the best; don't kill the structure, don't allow redefinition of the accessor either.
Sounds like a candidate for cerror. Helmut
On 3/16/10 7:17 AM, Helmut Eller wrote:
* Raymond Toy [2010-03-16 04:41+0100] writes:
I tried undefine-function-name instead of undefine-structure. It works, but having a redefined structure accessor that doesn't really work is a problem. For example,
(defstruct abc a) (defun abc-a (x) 42) (make-abc :a 'a) -> #S(abc :a 42)
This seems not good either.
default-structure-print calls (fdefinition (dsd-accessor slot)). We could change that to %instance-ref. That would also help in this case:
(defstruct abc a) (fmakunbound 'abc-a) (make-abc :a 'a) -> error during printing
Unfortunately, there are other places that call dsd-accessor by name. Like inspect.
Is there any reason why we couldn't replace at least these two places by %instance-ref?
Maybe disallowing redefining structure-accessors this way is the best; don't kill the structure, don't allow redefinition of the accessor either.
Sounds like a candidate for cerror.
I did that already last night, just to see if did what I wanted. Seems to work. Ray
* Raymond Toy [2010-03-16 04:41+0100] writes:
I tried undefine-function-name instead of undefine-structure. It works, but having a redefined structure accessor that doesn't really work is a problem. For example,
(defstruct abc a) (defun abc-a (x) 42) (make-abc :a 'a) -> #S(abc :a 42)
Another funny case is this one: (defstruct abc a) (setf (fdefinition 'abc-a) (lambda (x) 42)) (abc-a nil) => 42 (defstruct abc b) (abc-a nil) -> abc-a not defined Helmut
* Helmut Eller [2010-03-16 12:43+0100] writes:
* Raymond Toy [2010-03-16 04:41+0100] writes:
I tried undefine-function-name instead of undefine-structure. It works, but having a redefined structure accessor that doesn't really work is a problem. For example,
(defstruct abc a) (defun abc-a (x) 42) (make-abc :a 'a) -> #S(abc :a 42)
Another funny case is this one:
(defstruct abc a) (setf (fdefinition 'abc-a) (lambda (x) 42)) (abc-a nil) => 42 (defstruct abc b) (abc-a nil) -> abc-a not defined
Another silly example: (defstruct foo -a) (defstruct foo- a) (make-foo) -> error during print Helmut
On 3/16/10 7:43 AM, Helmut Eller wrote:
* Raymond Toy [2010-03-16 04:41+0100] writes:
I tried undefine-function-name instead of undefine-structure. It works, but having a redefined structure accessor that doesn't really work is a problem. For example,
(defstruct abc a) (defun abc-a (x) 42) (make-abc :a 'a) -> #S(abc :a 42)
Another funny case is this one:
(defstruct abc a) (setf (fdefinition 'abc-a) (lambda (x) 42)) (abc-a nil) => 42 (defstruct abc b) (abc-a nil) -> abc-a not defined
I think this is ok. Redefining a struct is undefined, IIRC, so we have some leeway. I think we should just leave it this way. Ray
On 3/10/10 1:47 PM, Helmut Eller wrote:
One more thing:
(defmacro bar () 1) (compile 'bar '(lambda () 2))
should remove the macro binding for bar.
Hmm. The CLHS entry for COMPILE says: if name is a symbol that names a macro, its macro function is updated What is that supposed to mean? The macro binding should be removed? That we're defining a new macro expansion for that symbol? Ray
On 12 March 2010 14:01, Raymond Toy <toy.raymond@gmail.com> wrote:
On 3/10/10 1:47 PM, Helmut Eller wrote:
One more thing:
(defmacro bar () 1) (compile 'bar '(lambda () 2))
should remove the macro binding for bar.
Hmm. The CLHS entry for COMPILE says:
if name is a symbol that names a macro, its macro function is updated
What is that supposed to mean? The macro binding should be removed? That we're defining a new macro expansion for that symbol?
I believe it means this (which is the SBCL take on the subject): CL-USER> (defmacro foo () "old FOO") FOO CL-USER> (foo) "old FOO" CL-USER> (compile 'foo `(lambda (form env) (declare (ignore form env)) "new FOO")) FOO NIL NIL CL-USER> (foo) "new FOO" Cheers, -- Nikodemus
On 3/12/10 7:41 AM, Nikodemus Siivola wrote:
On 12 March 2010 14:01, Raymond Toy <toy.raymond@gmail.com> wrote:
On 3/10/10 1:47 PM, Helmut Eller wrote:
One more thing:
(defmacro bar () 1) (compile 'bar '(lambda () 2))
should remove the macro binding for bar.
Hmm. The CLHS entry for COMPILE says:
if name is a symbol that names a macro, its macro function is updated
What is that supposed to mean? The macro binding should be removed? That we're defining a new macro expansion for that symbol?
I believe it means this (which is the SBCL take on the subject):
CL-USER> (defmacro foo () "old FOO") FOO CL-USER> (foo) "old FOO" CL-USER> (compile 'foo `(lambda (form env) (declare (ignore form env)) "new FOO")) FOO NIL NIL CL-USER> (foo) "new FOO"
Ok, so SBCL defines a new macro. I notice that ACL, Clisp and CCL define new functions. ACL and Clisp do it silently; CCL produces a cerror about redefining a macro as a function. Ray
* Raymond Toy [2010-03-12 14:32+0100] writes:
Ok, so SBCL defines a new macro. I notice that ACL, Clisp and CCL define new functions. ACL and Clisp do it silently; CCL produces a cerror about redefining a macro as a function.
LispWorks, like SBCL, updates the macro-function. It seems that the wording in the spec intends that. I guess it could be useful to compile the expander function with (compile 'my-macro) if my-macro is very complicated. Helmut
On 3/10/10 1:27 PM, Helmut Eller wrote:
We could add this
(when (typep definition '(and function (not eval:interpreted-function))) (when name (setf (fdefinition name) definition)) (return-from compile (values definition nil nil)))
If I understand this correctly, this will just return the original definition. If so, then I wasn't quite clear about the (compile 'foo) example. The second compile would actually recompile foo from the original sources, not return the already previously compiled function. This is handy if you've changed something like a macro or inline function and want to compile foo again to see the effect.
right before the with-compilation-unit form. We can't return-from inside the with-compilation-unit without producing some error message so we have to put it before it. We'd lose some restarts, but that should only be noticeable if (setf (fdefinition ..)) hits a definition lock and it's not required by the spec anyway.
Then form would be bound as it used to be (form `#',(get-lambda-to-compile definition).
I think we still need the additional fix in function-lambda-expression in case the compiled-debug-info-source is NIL.
I think we always have the lambda expression for interpreted functions.
Yes, this is true. But for some reason, in Madhu's example, the compiled-debug-info-source is NIL, hence the traceback that he shows. Ray
* Raymond Toy [2010-03-11 15:18+0100] writes:
On 3/10/10 1:27 PM, Helmut Eller wrote:
We could add this
(when (typep definition '(and function (not eval:interpreted-function))) (when name (setf (fdefinition name) definition)) (return-from compile (values definition nil nil)))
If I understand this correctly, this will just return the original definition.
Right. And this should also work if the function has no debug-info at all e.g. because it was compiled with (debug 0).
If so, then I wasn't quite clear about the (compile 'foo) example. The second compile would actually recompile foo from the original sources, not return the already previously compiled function. This is handy if you've changed something like a macro or inline function and want to compile foo again to see the effect.
Hmm.. good point.
right before the with-compilation-unit form. We can't return-from inside the with-compilation-unit without producing some error message so we have to put it before it. We'd lose some restarts, but that should only be noticeable if (setf (fdefinition ..)) hits a definition lock and it's not required by the spec anyway.
Then form would be bound as it used to be (form `#',(get-lambda-to-compile definition).
I think we still need the additional fix in function-lambda-expression in case the compiled-debug-info-source is NIL.
I think we always have the lambda expression for interpreted functions.
Yes, this is true. But for some reason, in Madhu's example, the compiled-debug-info-source is NIL, hence the traceback that he shows.
The problem with Madhu's example is that the debug-info is back-patched sometime later after the top-level code is executed. This is not easy to fix without changing the way things are dumped to the fasl file. Helmut
participants (4)
-
Helmut Eller -
Madhu -
Nikodemus Siivola -
Raymond Toy