Thread: [CEDET-devel] no-next-method in SemanticDB
Brought to you by:
zappo
From: drkm <dar...@ya...> - 2005-07-02 11:52:03
|
Hi I just installed the 1.0pre3. When I 'C-x C-c', and SemanticDB have to save some DB in '~/.semanticdb', with 'kill-emacs-hook', I get the following error: (no-next-method "#<semanticdb-project-database-file .semanticdb/>" nil) Unfortunately, I don't have time to investigate furthemore. Sorry. Following is what the debugger sais (after removing the content of 'byte-code', containing some control chars): Debugger entered--Lisp error: (error "(no-next-method \"#<semanticdb-project-database-file .semanticdb/>\" nil)") signal(error ("(no-next-method \"#<semanticdb-project-database-file .semanticdb/>\" nil)")) error("%S" (no-next-method "#<semanticdb-project-database-file .semanticdb/>" nil)) byte-code("<...snipped...>" [foo string-match "write-protected" message error "%S"] 3) semanticdb-project-database-file(#1=[object semanticdb-project-database-file ".semanticdb/" "c:/Documents and Settings/drkm/My Documents/" semanticdb-table ([object semanticdb-table ".emacs" #1# emacs-lisp-mode ... ".emacs" 3867 unbound]) "c:/Documents and Settings/drkm/My Documents/.semanticdb/!drive_c!Documents and Settings!drkm!My Documents!.semantic.cache" #2="2.0pre3" #2#]) apply(semanticdb-project-database-file #1=[object semanticdb-project-database-file ".semanticdb/" "c:/Documents and Settings/drkm/My Documents/" semanticdb-table ([object semanticdb-table ".emacs" #1# emacs-lisp-mode ... ".emacs" 3867 unbound]) "c:/Documents and Settings/drkm/My Documents/.semanticdb/!drive_c!Documents and Settings!drkm!My Documents!.semantic.cache" #2="2.0pre3" #2#]) (setq rval (apply (car ...) newargs)) (let ((scoped-class ...) (eieio-generic-call-key ...)) (setq found t) (setq rval (apply ... newargs))) (if (car lambdas) (let (... ...) (setq found t) (setq rval ...))) (while lambdas (if (car lambdas) (let ... ... ...)) (setq lambdas (cdr lambdas) keys (cdr keys))) (let ((rval nil) (found nil)) (while lambdas (if ... ...) (setq lambdas ... keys ...)) (if (not found) (if ... ... ...)) rval) (let ((newargs nil) (mclass nil) (lambdas nil) (tlambdas nil) (keys nil) (static nil) (eieio-generic-call-methodname method) (eieio-generic-call-arglst args) (firstarg nil)) (setq newargs args firstarg (car newargs)) (if (and ... ... ... ...) (load ...)) (cond (... ...) (... ...)) (when (object-p firstarg) (setq tlambdas ...) (setq lambdas ... keys ...) (setq tlambdas ...) (setq lambdas ... keys ...) (setq tlambdas ...) (setq lambdas ... keys ...)) (unless (find-if ... lambdas) (setq tlambdas ...) (setq lambdas ... keys ...)) (let (... ...) (while lambdas ... ...) (if ... ...) rval)) eieio-generic-call(semanticdb-save-db (#1=[object semanticdb-project-database-file ".semanticdb/" "c:/Documents and Settings/drkm/My Documents/" semanticdb-table ([object semanticdb-table ".emacs" #1# emacs-lisp-mode ... ".emacs" 3867 unbound]) "c:/Documents and Settings/drkm/My Documents/.semanticdb/!drive_c!Documents and Settings!drkm!My Documents!.semantic.cache" #2="2.0pre3" #2#])) semanticdb-save-db(#1=[object semanticdb-project-database-file ".semanticdb/" "c:/Documents and Settings/drkm/My Documents/" semanticdb-table ([object semanticdb-table ".emacs" #1# emacs-lisp-mode ... ".emacs" 3867 unbound]) "c:/Documents and Settings/drkm/My Documents/.semanticdb/!drive_c!Documents and Settings!drkm!My Documents!.semantic.cache" #2="2.0pre3" #2#]) mapcar(semanticdb-save-db ([object semanticdb-project-database-emacs-lisp "Emacs" unbound semanticdb-table-emacs-lisp unbound] #1=[object semanticdb-project-database-file ".semanticdb/" "c:/Documents and Settings/drkm/My Documents/" semanticdb-table ([object semanticdb-table ".emacs" #1# emacs-lisp-mode ... ".emacs" 3867 unbound]) "c:/Documents and Settings/drkm/My Documents/.semanticdb/!drive_c!Documents and Settings!drkm!My Documents!.semantic.cache" #2="2.0pre3" #2#])) semanticdb-save-all-db() semanticdb-kill-emacs-hook() run-hooks(kill-emacs-hook) kill-emacs() save-buffers-kill-emacs() (let ((i 0)) (while (re-search-forward "^Auto-saving...done$" ... t) (setq i ...)) (message "Googbye drkm. You typed more than %d characters today." (* i auto-save-interval)) (when (get-buffer "*scratch*") (switch-to-buffer "*scratch*")) (sit-for 120) (save-buffers-kill-emacs)) (save-excursion (set-buffer "*Messages*") (goto-char (point-min)) (let (...) (while ... ...) (message "Googbye drkm. You typed more than %d characters today." ...) (when ... ...) (sit-for 120) (save-buffers-kill-emacs))) drkm-fun-save-buffers-kill-emacs() call-interactively(drkm-fun-save-buffers-kill-emacs) I'm sorry that I can't help more on this issue, --drkm ___________________________________________________________________________ Appel audio GRATUIT partout dans le monde avec le nouveau Yahoo! Messenger Téléchargez cette version sur http://fr.messenger.yahoo.com |
From: Eric M. L. <er...@si...> - 2005-07-02 13:33:04
|
Hello, Based on your stack, the error is thrown from semanticdb-file.el, line 187. The only method called there is eieio-persistent-save which in turn calls `object-write'. Semanticdb-project-database-file has an `object-write' that uses `call-next-method' which might be the error source. The next method in this case would be eieio-default-superclass. I have seen the default superclass get lost in some cases of recompiling eieio.el in a running emacs. Since the eieio code in your stack is not compiled, it might be related. Thus, the solution is to exit emacs, rebuild cedet, and try again. Eric >>> drkm <dar...@ya...> seems to think that: > Hi > > I just installed the 1.0pre3. When I 'C-x C-c', and SemanticDB have >to save some DB in '~/.semanticdb', with 'kill-emacs-hook', I get the >following error: > > (no-next-method "#<semanticdb-project-database-file .semanticdb/>" >nil) > > Unfortunately, I don't have time to investigate furthemore. Sorry. >Following is what the debugger sais (after removing the content of >'byte-code', containing some control chars): > >Debugger entered--Lisp error: (error "(no-next-method >\"#<semanticdb-project-database-file .semanticdb/>\" nil)") > signal(error ("(no-next-method \"#<semanticdb-project-database-file >.semanticdb/>\" nil)")) > error("%S" (no-next-method "#<semanticdb-project-database-file >.semanticdb/>" nil)) > byte-code("<...snipped...>" [foo string-match "write-protected" >message error "%S"] 3) > semanticdb-project-database-file(#1=[object >semanticdb-project-database-file ".semanticdb/" "c:/Documents and >Settings/drkm/My Documents/" semanticdb-table ([object semanticdb-table >".emacs" #1# emacs-lisp-mode ... ".emacs" 3867 unbound]) "c:/Documents >and Settings/drkm/My Documents/.semanticdb/!drive_c!Documents and >Settings!drkm!My Documents!.semantic.cache" #2="2.0pre3" #2#]) > apply(semanticdb-project-database-file #1=[object >semanticdb-project-database-file ".semanticdb/" "c:/Documents and >Settings/drkm/My Documents/" semanticdb-table ([object semanticdb-table >".emacs" #1# emacs-lisp-mode ... ".emacs" 3867 unbound]) "c:/Documents >and Settings/drkm/My Documents/.semanticdb/!drive_c!Documents and >Settings!drkm!My Documents!.semantic.cache" #2="2.0pre3" #2#]) > (setq rval (apply (car ...) newargs)) > (let ((scoped-class ...) (eieio-generic-call-key ...)) (setq found t) >(setq rval (apply ... newargs))) > (if (car lambdas) (let (... ...) (setq found t) (setq rval ...))) > (while lambdas (if (car lambdas) (let ... ... ...)) (setq lambdas >(cdr lambdas) keys (cdr keys))) > (let ((rval nil) (found nil)) (while lambdas (if ... ...) (setq >lambdas ... keys ...)) (if (not found) (if ... ... ...)) rval) > (let ((newargs nil) (mclass nil) (lambdas nil) (tlambdas nil) (keys >nil) (static nil) (eieio-generic-call-methodname method) >(eieio-generic-call-arglst args) (firstarg nil)) (setq newargs args >firstarg (car newargs)) (if (and ... ... ... ...) (load ...)) (cond >(... ...) (... ...)) (when (object-p firstarg) (setq tlambdas ...) >(setq lambdas ... keys ...) (setq tlambdas ...) (setq lambdas ... keys >...) (setq tlambdas ...) (setq lambdas ... keys ...)) (unless (find-if >... lambdas) (setq tlambdas ...) (setq lambdas ... keys ...)) (let (... >...) (while lambdas ... ...) (if ... ...) rval)) > eieio-generic-call(semanticdb-save-db (#1=[object >semanticdb-project-database-file ".semanticdb/" "c:/Documents and >Settings/drkm/My Documents/" semanticdb-table ([object semanticdb-table >".emacs" #1# emacs-lisp-mode ... ".emacs" 3867 unbound]) "c:/Documents >and Settings/drkm/My Documents/.semanticdb/!drive_c!Documents and >Settings!drkm!My Documents!.semantic.cache" #2="2.0pre3" #2#])) > semanticdb-save-db(#1=[object semanticdb-project-database-file >".semanticdb/" "c:/Documents and Settings/drkm/My Documents/" >semanticdb-table ([object semanticdb-table ".emacs" #1# emacs-lisp-mode >... ".emacs" 3867 unbound]) "c:/Documents and Settings/drkm/My >Documents/.semanticdb/!drive_c!Documents and Settings!drkm!My >Documents!.semantic.cache" #2="2.0pre3" #2#]) > mapcar(semanticdb-save-db ([object >semanticdb-project-database-emacs-lisp "Emacs" unbound >semanticdb-table-emacs-lisp unbound] #1=[object >semanticdb-project-database-file ".semanticdb/" "c:/Documents and >Settings/drkm/My Documents/" semanticdb-table ([object semanticdb-table >".emacs" #1# emacs-lisp-mode ... ".emacs" 3867 unbound]) "c:/Documents >and Settings/drkm/My Documents/.semanticdb/!drive_c!Documents and >Settings!drkm!My Documents!.semantic.cache" #2="2.0pre3" #2#])) > semanticdb-save-all-db() > semanticdb-kill-emacs-hook() > run-hooks(kill-emacs-hook) > kill-emacs() > save-buffers-kill-emacs() > (let ((i 0)) (while (re-search-forward "^Auto-saving...done$" ... t) >(setq i ...)) (message "Googbye drkm. You typed more than %d >characters today." (* i auto-save-interval)) (when (get-buffer >"*scratch*") (switch-to-buffer "*scratch*")) (sit-for 120) >(save-buffers-kill-emacs)) > (save-excursion (set-buffer "*Messages*") (goto-char (point-min)) >(let (...) (while ... ...) (message "Googbye drkm. You typed more than >%d characters today." ...) (when ... ...) (sit-for 120) >(save-buffers-kill-emacs))) > drkm-fun-save-buffers-kill-emacs() > call-interactively(drkm-fun-save-buffers-kill-emacs) > > I'm sorry that I can't help more on this issue, > >--drkm [ ... ] -- Eric Ludlam: za...@gn..., er...@si... Home: http://www.ludlam.net Siege: www.siege-engine.com Emacs: http://cedet.sourceforge.net GNU: www.gnu.org |
From: drkm <dar...@ya...> - 2005-07-02 16:47:31
|
"Eric M. Ludlam" <er...@si...> writes: > The next method in this case would be > eieio-default-superclass. I have seen the default superclass get lost > in some cases of recompiling eieio.el in a running emacs. Since the > eieio code in your stack is not compiled, it might be related. But I have 'eieio-default-superclass', and 'eieio.el' is compiled. BTW, the folowing works: (defclass C () ()) (object-write (make-instance 'C)) BTW, to be sure that it's 'object-write' the problem, I modified 'no-next-method'. What do you think of the patch at the end of the post? In the present case, I got this: (no-next-method object-write "#<semanticdb-project-database-file .semanticdb/>" ";; SEMANTICDB Tags save file") --drkm --- eieio.el-orig 2005-06-30 05:08:02.000000000 +0200 +++ eieio.el 2005-07-02 18:40:06.000000000 +0200 @@ -1656,7 +1656,8 @@ (returnval nil) ) (if (or (not next) (not (car next))) - (no-next-method (car newargs)) + (apply 'no-next-method + (car newargs) eieio-generic-call-methodname (cdr newargs)) (let* ((eieio-generic-call-next-method-list (cdr eieio-generic-call-next-method-list)) (scoped-class (cdr next)) @@ -1999,16 +2000,15 @@ (signal 'no-method-definition (list method (object-name object))) ) -(defmethod no-next-method ((object eieio-default-superclass) - &rest args) +(defmethod no-next-method ((object eieio-default-superclass) methodname + &rest args) "Called from `call-next-method' when no additional methods are available. OBJECT is othe object being called on `call-next-method'. ARGS are the arguments it is called by. This method throws `no-next-method' by default. Override this method to not throw an error, and it's return value becomes the return value of `call-next-method'." - (signal 'no-next-method (list (object-name object) args)) -) + (signal 'no-next-method `(,methodname ,(object-name object) ,@args))) (defmethod clone ((obj eieio-default-superclass) &rest params) "Make a deep copy of OBJ, and then apply PARAMS. |
From: drkm <dar...@ya...> - 2005-07-02 17:06:14
|
drkm writes: > BTW, to be sure that it's 'object-write' the problem, I > modified 'no-next-method'. What do you think of the patch > at the end of the post? Well, forget it. It's useful, IMHO, but the lambda list of the method 'no-next-method' must not change (because, if I remember well, it's a method from the CLOS standard). But with on other way of passing the method name, indeed... --drkm |
From: drkm <dar...@ya...> - 2005-07-03 14:06:47
|
drkm writes: > Well, forget it. It's useful, IMHO, but the lambda list of the > method 'no-next-method' must not change (because, if I remember > well, it's a method from the CLOS standard). Well, after checking the Common Lisp HyperSpec you can find at <URL:http://www.lispworks.com/documentation/HyperSpec/Body/f_no_nex.htm>, I found the signature is not correct: ** Standard Generic Function NO-NEXT-METHOD ** * Syntax: no-next-method generic-function method &rest args => result* * Method Signatures: no-next-method (generic-function standard-generic-function) (method standard-method) &rest args * Arguments and Values: generic-function -- generic function to which method belongs. method -- method that contained the call to call-next-method for which there is no next method. args -- arguments to call-next-method. result---an object. * Description: The generic function no-next-method is called by call-next-method when there is no next method. The generic function no-next-method is not intended to be called by programmers. Programmers may write methods for it. IMHO, this is more useful. Even for the system-supplied method on 'no-next-method', which will can report more interresting information about the error. The only negative point I see here is that in EIEIO, I think, method and generic functions are not objects. So the only way to designate them is by name (by symbol). So the generic function and the method will be the same. Maybe replacing the method by its sequence of parameter specializers can be usefull here. For example, the following code could result in the following error: (defclass C () ()) ;; Assume there is no next method. (defmethod test ((obj C) param) (call-next-method obj param)) (test (make-instance 'C) 'dummy) ==> Error: '(no-next-method test ((obj C) param) ([object C "C"] dummy)) Maybe, in the end of the following week, in a few days, I'll have more free time to look deeper in this issue. Thanks, --drkm |
From: Eric M. L. <er...@si...> - 2005-07-05 20:21:01
|
Thanks for your thoughts and patches on this topic. I had the same idea but got distracted before I could write a stitch of code. I do agree with your assessment below. I look forward to a future patch for this enhancement. Was your other problem ever resolved that caused the need for this patch? When EIEIO recompiles, it re-creates a new default superclass. Re-creation of any class is supposed to find objects that inherit from it and swap in the new value. A great idea in principle, but sometimes it goes awry in the same way you had described the original problem. An earlier question was how to distinguish which version of a method was the problem. Each method is stored on a symbol the same name as the class. Thus if method foo on object BAR is called, you would see a stack that starts with foo, and eventually calls BAR, except BAR is not in the default symbol obarray. As such, you can learn a lot from a stack... which is what was missing in this case. It should be possible to derive the active method symbol, and append the text together for the method name to make something comprehensible. Eric >>> drkm <dar...@ya...> seems to think that: >drkm writes: > >> Well, forget it. It's useful, IMHO, but the lambda list of the >> method 'no-next-method' must not change (because, if I remember >> well, it's a method from the CLOS standard). > > Well, after checking the Common Lisp HyperSpec you can find at ><URL:http://www.lispworks.com/documentation/HyperSpec/Body/f_no_nex.htm>, >I found the signature is not correct: > > ** Standard Generic Function NO-NEXT-METHOD ** > > * Syntax: > > no-next-method generic-function method &rest args => result* > > * Method Signatures: > > no-next-method (generic-function standard-generic-function) > (method standard-method) > &rest args > > * Arguments and Values: > > generic-function -- generic function to which method belongs. > > method -- method that contained the call to call-next-method > for which there is no next method. > > args -- arguments to call-next-method. > > result---an object. > > * Description: > > The generic function no-next-method is called by > call-next-method when there is no next method. > > The generic function no-next-method is not intended to be > called by programmers. Programmers may write methods for it. > > IMHO, this is more useful. Even for the system-supplied method >on 'no-next-method', which will can report more interresting >information about the error. > > The only negative point I see here is that in EIEIO, I think, >method and generic functions are not objects. So the only way to >designate them is by name (by symbol). So the generic function >and the method will be the same. Maybe replacing the method by >its sequence of parameter specializers can be usefull here. > > For example, the following code could result in the following >error: > > (defclass C () ()) > > ;; Assume there is no next method. > (defmethod test ((obj C) param) > (call-next-method obj param)) > > (test (make-instance 'C) 'dummy) > > ==> Error: '(no-next-method test > ((obj C) param) > ([object C "C"] dummy)) > > Maybe, in the end of the following week, in a few days, I'll >have more free time to look deeper in this issue. > > Thanks, [ ... ] -- Eric Ludlam: za...@gn..., er...@si... Home: http://www.ludlam.net Siege: www.siege-engine.com Emacs: http://cedet.sourceforge.net GNU: www.gnu.org |
From: drkm <dar...@ya...> - 2005-07-06 02:30:19
|
"Eric M. Ludlam" writes: > Was your other problem ever resolved that caused the need for this > patch? When EIEIO recompiles, it re-creates a new default superclass. > Re-creation of any class is supposed to find objects that inherit from it > and swap in the new value. A great idea in principle, but sometimes > it goes awry in the same way you had described the original problem. Not already. I didn't already have time to try. Maybe on Thursday. But the strange thing is that I already had the same problem. I'm on Cygwin here, and I had the same problem on a Linux (at SF.net or lxplus.cern.ch, I don't remember), with the pre2, I think. Here with a CVS GNU Emacs, and there with a 21.3, I think. After installed CEDET the way the INSTALL file told me. I'll let you know if I find something interesting. > An earlier question was how to distinguish which version of a method > was the problem. Each method is stored on a symbol the same name as > the class. Thus if method foo on object BAR is called, you would see > a stack that starts with foo, and eventually calls BAR, except BAR is > not in the default symbol obarray. As such, you can learn a lot from > a stack... which is what was missing in this case. Yes. Such a stack would be easily implementable. 'call-next-method' may easily maintains it, isn't it? One particularity of EIEIO (in regard of CLOS) is that the dispatching is done only on the first argument. So a stack of classes symbols may be enough (the entire arguments lists, as I first said, is too much). But having real objects representing methods could be of interest, too. They can be stored in the plist of the same-name-of-the-class-symbols in the obarrays in the 'eieio-method-obarray' property of the generic function symbol, for example. > It should be possible to derive the active method symbol, and append > the text together for the method name to make something > comprehensible. What do you mean by "to derive the active method symbol"? Thanks, --drkm |
From: Eric M. L. <er...@si...> - 2005-07-06 13:08:53
|
>>> drkm <dar...@ya...> seems to think that: >"Eric M. Ludlam" writes: [ ... ] >> An earlier question was how to distinguish which version of a method >> was the problem. Each method is stored on a symbol the same name as >> the class. Thus if method foo on object BAR is called, you would see >> a stack that starts with foo, and eventually calls BAR, except BAR is >> not in the default symbol obarray. As such, you can learn a lot from >> a stack... which is what was missing in this case. > > Yes. Such a stack would be easily implementable. >'call-next-method' may easily maintains it, isn't it? > > One particularity of EIEIO (in regard of CLOS) is that the >dispatching is done only on the first argument. So a stack of >classes symbols may be enough (the entire arguments lists, as I >first said, is too much). Yes, that is an EIEIO limitation resulting from my inexperience as an OO programmer back in the day. > But having real objects representing methods could be of >interest, too. They can be stored in the plist of the >same-name-of-the-class-symbols in the obarrays in the >'eieio-method-obarray' property of the generic function symbol, >for example. Back when I was implementing EIEIO, much of the spec baffled me in terms of implementation, or the spec seemed to suggest an implementation that I thought would be very inefficient, and as such I simplified it as best I could. In the case of method dispatching, I created a system that optimized itself over time to try and boost performance. A side effect is that it is not very flexible, and has goofy restrictions. That said, your suggestion of grafting a method object onto the side of the existing system has some merit and may actually be possible without a full re-write. Doing so may provide additional flexibility in the future. >> It should be possible to derive the active method symbol, and append >> the text together for the method name to make something >> comprehensible. > > What do you mean by "to derive the active method symbol"? [ ... ] I mean something like this: (concat (symbol-name method-symbol) ":" eieio-generic-call-methodname) would produce "foo-class:some-method" which would be as specific as you need. Here 'method-symbol' is the symbol that holds the method implementation for a specific class. Eric -- Eric Ludlam: za...@gn..., er...@si... Home: http://www.ludlam.net Siege: www.siege-engine.com Emacs: http://cedet.sourceforge.net GNU: www.gnu.org |
From: drkm <dar...@ya...> - 2005-07-09 02:22:54
|
"Eric M. Ludlam" writes: >>>> drkm seems to think that: >> But having real objects representing methods could be of >>interest, too. They can be stored in the plist of the >>same-name-of-the-class-symbols in the obarrays in the >>'eieio-method-obarray' property of the generic function symbol, >>for example. > [...] > That said, your suggestion of grafting a method object onto the side > of the existing system has some merit and may actually be possible > without a full re-write. Doing so may provide additional flexibility > in the future. I wrote a piece of code to see what it can look like. It's based (from far) on MOP <URL:http://www.lisp.org/mop/index.html>. So I included all the ancestor classes of the two I used, 'eieio-standard-generic-function' and 'eieio-standard-method'. I don't really know MOP, so my (mis)understanding can be buggy. The code is not verry robust (not tested), but I don't have a lot of time to work on. So I post it here, to see your comments. I still have a problem related to bootstrap issue. But, again, I don't have a lot of time, and it's just a prototype. So, at this time, in EIEIO, methods and generic functions are represented like the following (let me know if I misunderstood something). The generic function name (a symbol in the default obarray) have the properties 'eieio-method-tree' and 'eieio-method-obarray'. I don't really understand what the 'eieio-method-tree' is used for. The 'eieio-method-obarray' is used as a container of the method implementations. Because EIEIO dispatches only on the first parameter, a single symbol can specify the implementation for a given call: the symbol of the class of the first parameter. So a symbol is created in the obarray for each implementation, whose the name is the same as the class symbol. This newly interned symbol is 'fset'ed to the implementation. It's a little bit more complex, because the qualifiers (:BEFORE, :PRIMARY, etc.). So there is an obarray for each existing qualifier (all the obarrays are in a vector, the real value of the 'eieio-method-obarray' property). What I done is just putting a property on these symbols (those in the obarrays). The property name is ':eieio-method', and the value is the method object. I put also a property on the generic function symbols, whose name is ':eieio-generic-function', and the value is the generic function object. I also changed 'no-next-method' to something more closely related to the ANSI CL, IMHO. Maybe the infos it passes to 'signal' may be improved. I think this kind of code can be usefull. But it need improvments. Unfortunately, I can't spend a lot of time on this during July and August. Maybe after (so after the CEDET 1.0 release :-p). Thanks, --drkm --- eieio.el-old 2005-06-30 05:08:02.000000000 +0200 +++ eieio.el 2005-07-09 02:54:20.000000000 +0200 @@ -869,7 +869,7 @@ calls defgeneric for you. With this implementation the arguments are currently ignored. You can use `defgeneric' to apply specialized top level documentation to a method." - `(eieio-defgeneric (quote ,method) ,doc-string)) + `(eieio-defgeneric (quote ,method) ,doc-string (quote ,args))) (defun eieio-defgeneric-form (method doc-string) "The lambda form that would be used as the function defined on METHOD. @@ -879,7 +879,7 @@ ,doc-string (eieio-generic-call (quote ,method) local-args))) -(defun eieio-defgeneric (method doc-string) +(defun eieio-defgeneric (method doc-string &optional args) "Engine part to `defgeneric' macro defining METHOD with DOC-STRING." (if (and (fboundp method) (not (generic-p method)) (or (byte-code-function-p (symbol-function method)) @@ -896,8 +896,13 @@ (fset method (eieio-defgeneric-form method doc-string)) ;; Make sure the method tables are installed. (eieiomt-install method) + (put method :eieio-generic-function + (make-instance 'eieio-standard-generic-function + :name method + :lambda-list args + :documentation doc-string)) ;; Return the method - 'method)) + method)) (defun eieio-unbind-method-implementations (method) "Make the generic method METHOD have no implementations.. @@ -1656,7 +1661,7 @@ (returnval nil) ) (if (or (not next) (not (car next))) - (no-next-method (car newargs)) + (no-next-method-trempoline newargs) (let* ((eieio-generic-call-next-method-list (cdr eieio-generic-call-next-method-list)) (scoped-class (cdr next)) @@ -1727,8 +1732,25 @@ ;; said symbol in the correct obarray, otherwise use the ;; other array to keep this stuff (if (< key method-num-lists) - (let ((nsym (intern (symbol-name class) (aref emto key)))) - (fset nsym method))) + (let ((nsym (intern (symbol-name class) (aref emto key))) + (generic (get method-name :eieio-generic-function)) + (qual (cond ((eq key method-before) :BEFORE) + ((eq key method-after) :AFTER) + ((eq key method-primary) :PRIMARY) + ((eq key method-static) :STATIC) + (t (error "eieiomt-add: Unknown qualifier %s" key))))) + (put nsym :eieio-method + (make-instance + 'eieio-standard-method + :function method + :generic-function generic + ;; FIXME: Bootstrap problem. + :lambda-list (when (fboundp 'generic-function-lambda-list) + (generic-function-lambda-list generic)) + :lambda-list `(,class) + :specializers `(,class) ;; EIEIO is special + :qualifiers `(,qual))) + (fset nsym method))) ;; Now optimize the entire obarray (if (< key method-num-lists) (let ((eieiomt-optimizing-obarray (aref emto key))) @@ -1917,6 +1939,59 @@ (defalias 'standard-class 'eieio-default-superclass) +;; Classes from MOP (see http://www.lisp.org/mop/index.html) +;; +(defclass eieio-standard-object () + () + "TODO: not implemented.") + +(defclass eieio-funcallable-standard-object (eieio-standard-object) + () + "TODO: not implemented.") + +(defclass eieio-generic-function (eieio-funcallable-standard-object) + () + "TODO: not implemented.") + +(defclass eieio-standard-generic-function (eieio-generic-function) + ((name :initarg :name) + (methods :initform nil) + ;; TODO: The default class for this generic function's method + ;; metaobjects is available as a class metaobject. + (lambda-list :initarg :lambda-list) + ;; TODO: The method combination is available as a method + ;; combination metaobject. + (documentation :initarg :documentation) + ;; TODO: The argument precedence order is available as a + ;; permutation of those symbols from the lambda list which name the + ;; required arguments of the generic function. + ;; TODO: The declarations are available as a list of declarations. + ) + "TODO: write docstring.") + +(defclass eieio-metaobject (eieio-standard-object) + () + "TODO: not implemented.") + +(defclass eieio-method (eieio-metaobject) + () + "TODO: not implemented.") + +(defclass eieio-standard-method (eieio-method) + ((function :initarg :function) + (generic-function :initarg :generic-function) + (lambda-list :initarg :lambda-list) + (specializers :initarg :specializers) + (qualifiers :initarg :qualifiers)) + "TODO: write docstring.") + +(defclass eieio-standard-accessor-method (eieio-standard-method) + ((slot-definition :initarg :slot-definition)) + "TODO: write docstring.") + +(flet ((make-instance (class &rest initargs) + (message "DEBUG: `make-instance' deactivated..."))) + (defmethod constructor :STATIC ((class eieio-default-superclass) newname &rest fields) "Default constructor for CLASS `eieio-defualt-superclass'. @@ -1971,6 +2046,8 @@ ;; Shared initialize will parse our fields for us. (shared-initialize this fields)) +) ;; flet + (defmethod slot-missing ((object eieio-default-superclass) slot-name operation &optional new-value) "Slot missing is invoked when an attempt to access a slot in OBJECT fails. @@ -1999,16 +2076,43 @@ (signal 'no-method-definition (list method (object-name object))) ) -(defmethod no-next-method ((object eieio-default-superclass) - &rest args) +(defun eieio-get-generic-function-object (generic-sym) + "..." + (get generic-sym :eieio-generic-function)) + +;; TODO: What to do if the first argument to defmethod is not typed? +;; +(defun eieio-get-method-object (generic-sym class key) + "..." + (get (intern (symbol-name (if (object-p class) (object-class class) class)) + (aref (get generic-sym 'eieio-method-obarray) key)) + :eieio-method)) + +(defun no-next-method-trempoline (newargs) + "..." + (apply 'no-next-method + (eieio-get-generic-function-object eieio-generic-call-methodname) + (eieio-get-method-object eieio-generic-call-methodname + (car newargs) + eieio-generic-call-key) + newargs)) + +(defmethod no-next-method ((generic eieio-generic-function) + (method eieio-method) + &rest args) "Called from `call-next-method' when no additional methods are available. OBJECT is othe object being called on `call-next-method'. ARGS are the arguments it is called by. This method throws `no-next-method' by default. Override this method to not throw an error, and it's return value becomes the return value of `call-next-method'." - (signal 'no-next-method (list (object-name object) args)) -) + (signal 'no-next-method + `(,(object-class (car args)) + ,(eieio-generic-function-name generic) + ,(eieio-method-qualifiers method) + ,(eieio-method-lambda-list method) + ,(object-name (car args)) + ,@(cdr args)))) (defmethod clone ((obj eieio-default-superclass) &rest params) "Make a deep copy of OBJ, and then apply PARAMS. @@ -2123,6 +2227,158 @@ (princ (make-string (* eieio-print-depth 2) ? )) (princ ")"))) +(defgeneric eieio-generic-function-argument-precedence-order + (generic-function) + "Returns the argument precedence order of the generic +function. This value is a list of symbols, a permutation of the +required parameters in the lambda list of the generic +function. This is the defaulted value of +the :argument-precedence-order initialization argument that was +associated with the generic function metaobject during +initialization or reinitialization.") + +(defgeneric eieio-generic-function-declarations (generic-function) + "Returns a possibly empty list of the declarations of the +generic function. The elements of this list are +declarations. This list is the defaulted value of +the :declarations initialization argument that was associated +with the generic function metaobject during initialization or +reinitialization.") + +(defgeneric eieio-generic-function-lambda-list (generic-function) + "Returns the lambda list of the generic function. This is the +defaulted value of the :lambda-list initialization argument that +was associated with the generic function metaobject during +initialization or reinitialization. An error is signaled if the +lambda list has yet to be supplied.") + +(defgeneric eieio-generic-function-method-class (generic-function) + "Returns the default method class of the generic function. This +class must be a subclass of the class method. This is the +defaulted value of the :method-class initialization argument that +was associated with the generic function metaobject during +initialization or reinitialization.") + +(defgeneric eieio-generic-function-method-combination (generic-function) + "Returns the method combination of the generic function. This +is a method combination metaobject. This is the defaulted value +of the :method-combination initialization argument that was +associated with the generic function metaobject during +initialization or reinitialization.") + +(defgeneric eieio-generic-function-methods (generic-function) + "Returns the set of methods currently connected to the generic +function. This is a set of method metaobjects. This value is +maintained by the generic functions ADD-METHOD and +REMOVE-METHOD.") + +;; TODO: The SETF form... +;; +(defgeneric eieio-generic-function-name (generic-function) + "Returns the name of the generic function, or nil if the +generic function has no name. This is the defaulted value of +the :name initialization argument that was associated with the +generic function metaobject during initialization or +reinitialization. (Also see (setf generic-function-name) [EIEIO: +not implemented yet].)") + +(defmethod eieio-generic-function-argument-precedence-order + ((gf eieio-standard-generic-function)) + "TODO: write docstring." + (error "`eieio-generic-function-argument-precedence-order': not implemented yet!")) + +(defmethod eieio-generic-function-declarations + ((gf eieio-standard-generic-function)) + "TODO: write docstring." + (error "`eieio-generic-function-declarations': not implemented yet!")) + +(defmethod eieio-generic-function-lambda-list + ((gf eieio-standard-generic-function)) + "TODO: write docstring." + (oref gf lambda-list)) + +(defmethod eieio-generic-function-method-class + ((gf eieio-standard-generic-function)) + "TODO: write docstring." + (error "`eieio-generic-function-method-class': not implemented yet!")) + +(defmethod eieio-generic-function-method-combination + ((gf eieio-standard-generic-function)) + "TODO: write docstring." + (error "`eieio-generic-function-method-combination': not implemented yet!")) + +(defmethod eieio-generic-function-methods + ((gf eieio-standard-generic-function)) + "TODO: write docstring." + (oref gf methods)) + +(defmethod eieio-generic-function-name + ((gf eieio-standard-generic-function)) + "TODO: write docstring." + (oref gf name)) + +(defgeneric eieio-method-function (method) + "Returns the method function of method. This is the defaulted +value of the :function initialization argument that was +associated with the method during initialization.") + +(defgeneric eieio-method-generic-function (method) + "Returns the generic function that method is currently +connected to, or nil if it is not currently connected to any +generic function. This value is either a generic function +metaobject or nil. When a method is first created it is not +connected to any generic function. This connection is maintained +by the generic functions ADD-METHOD and REMOVE-METHOD.") + +(defgeneric eieio-method-lambda-list (method) + "Returns the (unspecialized) lambda list of method. This value +is a Common Lisp lambda list. This is the defaulted value of +the :lambda-list initialization argument that was associated with +the method during initialization.") + +(defgeneric eieio-method-specializers (method) + "Returns a list of the specializers of method. This value is a +list of specializer metaobjects. This is the defaulted value of +the :specializers initialization argument that was associated +with the method during initialization.") + +(defgeneric eieio-method-qualifiers (method) + "Returns a (possibly empty) list of the qualifiers of +method. This value is a list of non-nil atoms. This is the +defaulted value of the :qualifiers initialization argument that +was associated with the method during initialization.") + +(defgeneric eieio-accessor-method-slot-definition (method) + "This accessor can only be called on accessor methods. It +returns the direct slot definition metaobject that defined this +method. This is the value of the :slot-definition initialization +argument associated with the method during initialization.") + +(defmethod eieio-method-function ((m eieio-standard-method)) + "TODO: write docstring." + (oref m function)) + +(defmethod eieio-method-lambda-list ((m eieio-standard-method)) + "TODO: write docstring." + (oref m lambda-list)) + +(defmethod eieio-method-specializers ((m eieio-standard-method)) + "TODO: write docstring." + (oref m specializers)) + +(defmethod eieio-method-qualifiers ((m eieio-standard-method)) + "TODO: write docstring." + (oref m qualifiers)) + +(defmethod eieio-method-generic-function ((m eieio-standard-method)) + "TODO: write docstring." + (oref m generic-function)) + +(defmethod eieio-accessor-method-slot-definition + ((m eieio-standard-accessor-method)) + "TODO: write docstring." + (error "`eieio-accessor-method-slot-definition': not implemented yet!")) + ;;; Unimplemented functions from CLOS ;; |
From: drkm <dar...@ya...> - 2005-07-09 05:06:16
|
drkm writes: > I wrote a piece of code to see what it can look like. I don't know if it's related, but while I tested it, I found the following: (defclass C () ()) (defclass D (C) ()) (defmethod f ((c C)) (message "f(C): %s" c)) (defmethod f ((d D)) (message "f(D): %s" d) (call-next-method)) (f (make-instance 'D)) ==> No next method: D, f, (:PRIMARY), (D), "#<D D>" Here is the backtrace. But now, really, I can't investigate anymore. Debugger entered--Lisp error: (no-next-method D f (:PRIMARY) (D) "#<D D>") signal(no-next-method (D f (:PRIMARY) (D) "#<D D>")) eieio-generic-function([object eieio-standard-generic-function "eieio-standard-generic-function" f nil nil "Generically created method `f'"] [object eieio-standard-method "eieio-standard-method" (lambda (d) (message "f(D): %s" d) (call-next-method)) [object eieio-standard-generic-function "eieio-standard-generic-function" f nil nil "Generically created method `f'"] (D) (D) (:PRIMARY)] [object D "D"]) apply(eieio-generic-function (#1=[object eieio-standard-generic-function "eieio-standard-generic-function" f nil nil "Generically created method `f'"] [object eieio-standard-method "eieio-standard-method" (lambda ... ... ...) #1# (D) (D) (:PRIMARY)] [object D "D"])) (setq rval (apply (car ...) newargs)) (let ((scoped-class ...) (eieio-generic-call-key ...)) (setq found t) (setq rval (apply ... newargs))) (if (car lambdas) (let (... ...) (setq found t) (setq rval ...))) (while lambdas (if (car lambdas) (let ... ... ...)) (setq lambdas (cdr lambdas) keys (cdr keys))) (let ((rval nil) (found nil)) (while lambdas (if ... ...) (setq lambdas ... keys ...)) (if (not found) (if ... ... ...)) rval) (let ((newargs nil) (mclass nil) (lambdas nil) (tlambdas nil) (keys nil) (static nil) (eieio-generic-call-methodname method) (eieio-generic-call-arglst args) (firstarg nil)) (setq newargs args firstarg (car newargs)) (if (and ... ... ... ...) (load ...)) (cond (... ...) (... ...)) (when (object-p firstarg) (setq tlambdas ...) (setq lambdas ... keys ...) (setq tlambdas ...) (setq lambdas ... keys ...) (setq tlambdas ...) (setq lambdas ... keys ...)) (unless (find-if ... lambdas) (setq tlambdas ...) (setq lambdas ... keys ...)) (let (... ...) (while lambdas ... ...) (if ... ...) rval)) eieio-generic-call(no-next-method (#1=[object eieio-standard-generic-function "eieio-standard-generic-function" f nil nil "Generically created method `f'"] [object eieio-standard-method "eieio-standard-method" (lambda ... ... ...) #1# (D) (D) (:PRIMARY)] [object D "D"])) no-next-method([object eieio-standard-generic-function "eieio-standard-generic-function" f nil nil "Generically created method `f'"] [object eieio-standard-method "eieio-standard-method" (lambda (d) (message "f(D): %s" d) (call-next-method)) [object eieio-standard-generic-function "eieio-standard-generic-function" f nil nil "Generically created method `f'"] (D) (D) (:PRIMARY)] [object D "D"]) apply(no-next-method [object eieio-standard-generic-function "eieio-standard-generic-function" f nil nil "Generically created method `f'"] [object eieio-standard-method "eieio-standard-method" (lambda (d) (message "f(D): %s" d) (call-next-method)) [object eieio-standard-generic-function "eieio-standard-generic-function" f nil nil "Generically created method `f'"] (D) (D) (:PRIMARY)] [object D "D"]) no-next-method-trempoline(([object D "D"])) call-next-method() D([object D "D"]) apply(D [object D "D"]) (setq rval (apply (car ...) newargs)) (let ((scoped-class ...) (eieio-generic-call-key ...)) (setq found t) (setq rval (apply ... newargs))) (if (car lambdas) (let (... ...) (setq found t) (setq rval ...))) (while lambdas (if (car lambdas) (let ... ... ...)) (setq lambdas (cdr lambdas) keys (cdr keys))) (let ((rval nil) (found nil)) (while lambdas (if ... ...) (setq lambdas ... keys ...)) (if (not found) (if ... ... ...)) rval) (let ((newargs nil) (mclass nil) (lambdas nil) (tlambdas nil) (keys nil) (static nil) (eieio-generic-call-methodname method) (eieio-generic-call-arglst args) (firstarg nil)) (setq newargs args firstarg (car newargs)) (if (and ... ... ... ...) (load ...)) (cond (... ...) (... ...)) (when (object-p firstarg) (setq tlambdas ...) (setq lambdas ... keys ...) (setq tlambdas ...) (setq lambdas ... keys ...) (setq tlambdas ...) (setq lambdas ... keys ...)) (unless (find-if ... lambdas) (setq tlambdas ...) (setq lambdas ... keys ...)) (let (... ...) (while lambdas ... ...) (if ... ...) rval)) eieio-generic-call(f ([object D "D"])) f([object D "D"]) eval((f (make-instance (quote D)))) eval-last-sexp-1(nil) eval-last-sexp(nil) call-interactively(eval-last-sexp) Thanks, --drkm |
From: Eric M. L. <er...@si...> - 2005-07-13 02:08:29
|
Hi, I was away for a few days. Sorry for the late reply. >>> drkm <dar...@ya...> seems to think that: >"Eric M. Ludlam" writes: > >>>>> drkm seems to think that: > >>> But having real objects representing methods could be of >>>interest, too. They can be stored in the plist of the >>>same-name-of-the-class-symbols in the obarrays in the >>>'eieio-method-obarray' property of the generic function symbol, >>>for example. > >> [...] > >> That said, your suggestion of grafting a method object onto the side >> of the existing system has some merit and may actually be possible >> without a full re-write. Doing so may provide additional flexibility >> in the future. > > I wrote a piece of code to see what it can look like. It's >based (from far) on MOP <URL:http://www.lisp.org/mop/index.html>. >So I included all the ancestor classes of the two I used, >'eieio-standard-generic-function' and 'eieio-standard-method'. Thanks for the patch. I will investigate it at length as soon as I can. [ ... ] > So, at this time, in EIEIO, methods and generic functions are >represented like the following (let me know if I misunderstood >something). The generic function name (a symbol in the default >obarray) have the properties 'eieio-method-tree' and >'eieio-method-obarray'. > > I don't really understand what the 'eieio-method-tree' is used >for. I looked through eieio.el myself and I must profess, I don't remember, nor can I divine it's purpose anymore. My suspicion is that its purpose has been overtaken by the obarray which was an optimization technique that came later. Your other questions and self-answers in previous emails were all accurate. > The 'eieio-method-obarray' is used as a container of the method >implementations. Because EIEIO dispatches only on the first >parameter, a single symbol can specify the implementation for a >given call: the symbol of the class of the first parameter. So a >symbol is created in the obarray for each implementation, whose >the name is the same as the class symbol. This newly interned >symbol is 'fset'ed to the implementation. > > It's a little bit more complex, because the qualifiers >(:BEFORE, :PRIMARY, etc.). So there is an obarray for each >existing qualifier (all the obarrays are in a vector, the real >value of the 'eieio-method-obarray' property). > > What I done is just putting a property on these symbols (those >in the obarrays). The property name is ':eieio-method', and the >value is the method object. > > I put also a property on the generic function symbols, whose >name is ':eieio-generic-function', and the value is the generic >function object. > > I also changed 'no-next-method' to something more closely >related to the ANSI CL, IMHO. Maybe the infos it passes to >'signal' may be improved. > > I think this kind of code can be usefull. But it need >improvments. Unfortunately, I can't spend a lot of time on this >during July and August. Maybe after (so after the CEDET 1.0 >release :-p). [ ... ] Your strategy sounds good. I have similar issues related to time I can spend on CEDET. As I have just finished getting some paperwork done for the FSF, I need to ice CEDET development and make a 1.0 release so that the dates line up, thus allowing GNU Emacs to incorporate aspects of CEDET. I'll come back to this when I am done with that. Eric -- Eric Ludlam: za...@gn..., er...@si... Home: http://www.ludlam.net Siege: www.siege-engine.com Emacs: http://cedet.sourceforge.net GNU: www.gnu.org |
From: Eric M. L. <er...@si...> - 2005-07-13 02:11:06
|
>>> drkm <dar...@ya...> seems to think that: >drkm writes: > >> I wrote a piece of code to see what it can look like. > > I don't know if it's related, but while I tested it, I found >the following: > > (defclass C () ()) > (defclass D (C) ()) > > (defmethod f ((c C)) > (message "f(C): %s" c)) > > (defmethod f ((d D)) > (message "f(D): %s" d) > (call-next-method)) > > (f (make-instance 'D)) > > ==> No next method: D, f, (:PRIMARY), (D), "#<D D>" > > Here is the backtrace. But now, really, I can't investigate >anymore. [ ... ] Hi, I tried out this code, and it worked fine for me. Perhaps this is somehow related to your recent EIEIO hacking? Eric -- Eric Ludlam: za...@gn..., er...@si... Home: http://www.ludlam.net Siege: www.siege-engine.com Emacs: http://cedet.sourceforge.net GNU: www.gnu.org |
From: drkm <dar...@ya...> - 2005-07-13 15:02:09
|
"Eric M. Ludlam" <er...@si...> writes: >drkm writes: >> (defclass C () ()) >> (defclass D (C) ()) >> (defmethod f ((c C)) >> (message "f(C): %s" c)) >> (defmethod f ((d D)) >> (message "f(D): %s" d) >> (call-next-method)) >> (f (make-instance 'D)) >> ==> No next method: D, f, (:PRIMARY), (D), "#<D D>" > I tried out this code, and it worked fine for me. Perhaps this is > somehow related to your recent EIEIO hacking? I tried with the original EIEIO, off course (while the error was which I got with the patch, to be more verbose). I can't investigate deeper now, but I will try to do as soon as I can. --drkm |
From: drkm <dar...@ya...> - 2005-07-14 18:57:41
|
drkm writes: > "Eric M. Ludlam" <er...@si...> writes: >>drkm writes: >>> (defclass C () ()) >>> (defclass D (C) ()) >>> (defmethod f ((c C)) >>> (message "f(C): %s" c)) >>> (defmethod f ((d D)) >>> (message "f(D): %s" d) >>> (call-next-method)) >>> (f (make-instance 'D)) >>> ==> No next method: D, f, (:PRIMARY), (D), "#<D D>" >> I tried out this code, and it worked fine for me. Perhaps this is >> somehow related to your recent EIEIO hacking? > I tried with the original EIEIO, off course (while the error > was which I got with the patch, to be more verbose). I can't > investigate deeper now, but I will try to do as soon as I can. I just try with a completely fresh CEDET pre3, properly installed, and I get again the same error: Debugger entered--Lisp error: (no-next-method "#<D D>" nil) Does somebody else have the same problem while evaluating the code above? --drkm |
From: drkm <dar...@ya...> - 2005-07-14 19:21:05
|
drkm writes: > I just try with a completely fresh CEDET pre3, properly > installed, and I get again the same error: > Debugger entered--Lisp error: (no-next-method "#<D D>" nil) > Does somebody else have the same problem while evaluating the > code above? More infos: (symbol-value (intern-soft "D" (aref (get 'f 'eieio-method-obarray) 2))) ==> C (symbol-function (symbol-value (intern-soft "D" (aref (get 'f 'eieio-method-obarray) 2)))) ==> (lambda (c) (message "f(C): %s" c)) --drkm |
From: drkm <dar...@ya...> - 2005-07-14 19:38:08
|
drkm writes: > More infos: > (symbol-value > (intern-soft "D" (aref (get 'f 'eieio-method-obarray) 2))) > ==> C > (symbol-function > (symbol-value > (intern-soft "D" (aref (get 'f 'eieio-method-obarray) 2)))) > ==> (lambda (c) (message "f(C): %s" c)) And even more: (defadvice call-next-method (before drkm:call-next-method activate) (flet ((display (sym) (message (concat (symbol-name sym) ": %s") (symbol-value (intern-soft (concat "eieio-generic-call-" (symbol-name sym))))))) (display 'methodname) (display 'arglst) (display 'key) (display 'next-method-list))) ... (f (make-instance 'D)) ==> methodname: f arglst: ([object D D]) key: 2 next-method-list: nil So it seems that the 'eieio-generic-call-next-method-list' is not well computed. --drkm |
From: drkm <dar...@ya...> - 2005-07-14 22:01:07
|
drkm writes: > So it seems that the 'eieio-generic-call-next-method-list' is > not well computed. It's a false alert, again. The cause was an old patch I made to allow passing an object to :STATIC generic functions. The problem is corrected in CEDET, but the patch was still installed (I installed it in a wrong way). Shame on me! (but now, I understand better the internals of EIEIO :-p) I guess the initial problem had the same origin. BTW, I still have such an old patch that make accessors to class allocated slots to be :STATIC methods. Before I remove it, the problem is solved, isn't it? I apologize for all this noise, --drkm |
From: drkm <dar...@ya...> - 2005-07-15 23:52:42
|
drkm writes: The following code, from my previous patch: > +;; TODO: What to do if the first argument to defmethod is not typed? > +;; > +(defun eieio-get-method-object (generic-sym class key) > + "..." > + (get (intern (symbol-name (if (object-p class) (object-class class) class)) > + (aref (get generic-sym 'eieio-method-obarray) key)) > + :eieio-method)) > +(defun no-next-method-trempoline (newargs) > + "..." > + (apply 'no-next-method > + (eieio-get-generic-function-object eieio-generic-call-methodname) > + (eieio-get-method-object eieio-generic-call-methodname > + (car newargs) > + eieio-generic-call-key) > + newargs)) have to be change with: ;; TODO: What to do if the first argument to defmethod is not typed? ;; (defun eieio-get-method-object (generic-sym class-or-obj key) "..." (let* ((class (symbol-name (if (object-p class-or-obj) (object-class class-or-obj) class-or-obj))) (array (get generic-sym 'eieio-method-obarray))) (get (or (intern class (aref array method-primary)) (intern class (aref array method-static))) :eieio-method))) ;; TODO: What to do if the first argument to defmethod is not typed? ;; (defun eieio-get-last-method-object (generic-sym class-or-obj key) "..." (let* ((class (symbol-name (if (object-p class-or-obj) (object-class class-or-obj) class-or-obj))) (array (get generic-sym 'eieio-method-obarray)) (sym (or (intern class (aref array method-primary)) (intern class (aref array method-static))))) (while (and (boundp sym) (symbol-value sym)) (setq sym (symbol-value sym))) (get sym :eieio-method))) (defun no-next-method-trempoline (newargs) "..." (apply 'no-next-method (eieio-get-generic-function-object eieio-generic-call-methodname) (eieio-get-last-method-object eieio-generic-call-methodname (car newargs) eieio-generic-call-key) newargs)) If not, the 'no-next-method' error always reports the method object for the initial method found. I guess I can easily change 'eieio-generic-call-next-method-list' to record method objects as well (I hope without too much runtime cost), so this'll can be simplified. --drkm |
From: drkm <dar...@ya...> - 2005-07-16 00:25:49
|
drkm writes: > I guess I can easily change > 'eieio-generic-call-next-method-list' to record method objects as > well (I hope without too much runtime cost), so this'll can be > simplified. Sorry, I misunderstood this variable, as it already stores the needed information. I just have to record its initial value. So the patch is now as at the end of this post (it begins to be useable, IMHO). Regards, --drkm --- eieio.el-old 2005-06-30 05:08:02.000000000 +0200 +++ eieio.el 2005-07-16 02:17:32.000000000 +0200 @@ -869,7 +869,7 @@ calls defgeneric for you. With this implementation the arguments are currently ignored. You can use `defgeneric' to apply specialized top level documentation to a method." - `(eieio-defgeneric (quote ,method) ,doc-string)) + `(eieio-defgeneric (quote ,method) ,doc-string (quote ,args))) (defun eieio-defgeneric-form (method doc-string) "The lambda form that would be used as the function defined on METHOD. @@ -879,7 +879,7 @@ ,doc-string (eieio-generic-call (quote ,method) local-args))) -(defun eieio-defgeneric (method doc-string) +(defun eieio-defgeneric (method doc-string &optional args) "Engine part to `defgeneric' macro defining METHOD with DOC-STRING." (if (and (fboundp method) (not (generic-p method)) (or (byte-code-function-p (symbol-function method)) @@ -896,8 +896,13 @@ (fset method (eieio-defgeneric-form method doc-string)) ;; Make sure the method tables are installed. (eieiomt-install method) + (put method :eieio-generic-function + (make-instance 'eieio-standard-generic-function + :name method + :lambda-list args + :documentation doc-string)) ;; Return the method - 'method)) + method)) (defun eieio-unbind-method-implementations (method) "Make the generic method METHOD have no implementations.. @@ -1491,6 +1496,7 @@ "When executing a PRIMARY or STATIC method, track the 'next-method'. During executions, the list is first generated, then as each next method is called, the next method is popped off the stack.") +(defvar eieio-generic-call-next-method-list-orig nil) (defun eieio-generic-call (method args) "Call METHOD with ARGS. @@ -1588,7 +1594,10 @@ ;; Use the cdr, as the first element is the fcn ;; we are calling right now. (when has-return-val (cdr primarymethodlist))) - ) + ) + (when has-return-val + (setq eieio-generic-call-next-method-list-orig + primarymethodlist)) (setq found t) ;;(setq rval (apply (car (car lambdas)) newargs)) (setq lastval (apply (car (car lambdas)) newargs)) @@ -1636,7 +1645,7 @@ (nreverse lambdas)))) (defun next-method-p () - "Return a list of lambdas which qualify as the `next-method'." + "Return a list of methods which qualify as the `next-method'." eieio-generic-call-next-method-list) (defun call-next-method (&rest replacement-args) @@ -1656,7 +1665,7 @@ (returnval nil) ) (if (or (not next) (not (car next))) - (no-next-method (car newargs)) + (no-next-method-trempoline newargs) (let* ((eieio-generic-call-next-method-list (cdr eieio-generic-call-next-method-list)) (scoped-class (cdr next)) @@ -1727,8 +1736,25 @@ ;; said symbol in the correct obarray, otherwise use the ;; other array to keep this stuff (if (< key method-num-lists) - (let ((nsym (intern (symbol-name class) (aref emto key)))) - (fset nsym method))) + (let ((nsym (intern (symbol-name class) (aref emto key))) + (generic (get method-name :eieio-generic-function)) + (qual (cond ((eq key method-before) :BEFORE) + ((eq key method-after) :AFTER) + ((eq key method-primary) :PRIMARY) + ((eq key method-static) :STATIC) + (t (error "eieiomt-add: Unknown qualifier %s" key))))) + (put nsym :eieio-method + (make-instance + 'eieio-standard-method + :function method + :generic-function generic + ;; FIXME: Bootstrap problem. + :lambda-list (when (fboundp 'generic-function-lambda-list) + (generic-function-lambda-list generic)) + :lambda-list `(,class) + :specializers `(,class) ;; EIEIO is special + :qualifiers `(,qual))) + (fset nsym method))) ;; Now optimize the entire obarray (if (< key method-num-lists) (let ((eieiomt-optimizing-obarray (aref emto key))) @@ -1917,6 +1943,59 @@ (defalias 'standard-class 'eieio-default-superclass) +;; Classes from MOP (see http://www.lisp.org/mop/index.html) +;; +(defclass eieio-standard-object () + () + "TODO: not implemented.") + +(defclass eieio-funcallable-standard-object (eieio-standard-object) + () + "TODO: not implemented.") + +(defclass eieio-generic-function (eieio-funcallable-standard-object) + () + "TODO: not implemented.") + +(defclass eieio-standard-generic-function (eieio-generic-function) + ((name :initarg :name) + (methods :initform nil) + ;; TODO: The default class for this generic function's method + ;; metaobjects is available as a class metaobject. + (lambda-list :initarg :lambda-list) + ;; TODO: The method combination is available as a method + ;; combination metaobject. + (documentation :initarg :documentation) + ;; TODO: The argument precedence order is available as a + ;; permutation of those symbols from the lambda list which name the + ;; required arguments of the generic function. + ;; TODO: The declarations are available as a list of declarations. + ) + "TODO: write docstring.") + +(defclass eieio-metaobject (eieio-standard-object) + () + "TODO: not implemented.") + +(defclass eieio-method (eieio-metaobject) + () + "TODO: not implemented.") + +(defclass eieio-standard-method (eieio-method) + ((function :initarg :function) + (generic-function :initarg :generic-function) + (lambda-list :initarg :lambda-list) + (specializers :initarg :specializers) + (qualifiers :initarg :qualifiers)) + "TODO: write docstring.") + +(defclass eieio-standard-accessor-method (eieio-standard-method) + ((slot-definition :initarg :slot-definition)) + "TODO: write docstring.") + +(flet ((make-instance (class &rest initargs) + (message "DEBUG: `make-instance' deactivated..."))) + (defmethod constructor :STATIC ((class eieio-default-superclass) newname &rest fields) "Default constructor for CLASS `eieio-defualt-superclass'. @@ -1971,6 +2050,8 @@ ;; Shared initialize will parse our fields for us. (shared-initialize this fields)) +) ;; flet + (defmethod slot-missing ((object eieio-default-superclass) slot-name operation &optional new-value) "Slot missing is invoked when an attempt to access a slot in OBJECT fails. @@ -1999,16 +2080,48 @@ (signal 'no-method-definition (list method (object-name object))) ) -(defmethod no-next-method ((object eieio-default-superclass) - &rest args) +(defun eieio-get-generic-function-object (generic-sym) + "..." + (get generic-sym :eieio-generic-function)) + +;; TODO: What to do if the first argument to defmethod is not typed? +;; +(defun eieio-get-method-object (generic-sym class-or-obj key) + "..." + (let* ((class (symbol-name (if (object-p class-or-obj) + (object-class class-or-obj) + class-or-obj))) + (array (get generic-sym 'eieio-method-obarray))) + (get (or (intern class (aref array method-primary)) + (intern class (aref array method-static))) + :eieio-method))) + +(defun no-next-method-trempoline (newargs) + "..." + (let ((last-method (car (last eieio-generic-call-next-method-list-orig)))) + (apply 'no-next-method + (eieio-get-generic-function-object eieio-generic-call-methodname) + (eieio-get-method-object eieio-generic-call-methodname + (cdr last-method) + eieio-generic-call-key) + newargs))) + +(defmethod no-next-method ((generic eieio-generic-function) + (method eieio-method) + &rest args) "Called from `call-next-method' when no additional methods are available. OBJECT is othe object being called on `call-next-method'. ARGS are the arguments it is called by. This method throws `no-next-method' by default. Override this method to not throw an error, and it's return value becomes the return value of `call-next-method'." - (signal 'no-next-method (list (object-name object) args)) -) + (signal 'no-next-method + `(,(object-class (car args)) + ,(eieio-generic-function-name generic) + ,(eieio-method-qualifiers method) + ,(eieio-method-lambda-list method) + ,(object-name (car args)) + ,@(cdr args)))) (defmethod clone ((obj eieio-default-superclass) &rest params) "Make a deep copy of OBJ, and then apply PARAMS. @@ -2123,6 +2236,158 @@ (princ (make-string (* eieio-print-depth 2) ? )) (princ ")"))) +(defgeneric eieio-generic-function-argument-precedence-order + (generic-function) + "Returns the argument precedence order of the generic +function. This value is a list of symbols, a permutation of the +required parameters in the lambda list of the generic +function. This is the defaulted value of +the :argument-precedence-order initialization argument that was +associated with the generic function metaobject during +initialization or reinitialization.") + +(defgeneric eieio-generic-function-declarations (generic-function) + "Returns a possibly empty list of the declarations of the +generic function. The elements of this list are +declarations. This list is the defaulted value of +the :declarations initialization argument that was associated +with the generic function metaobject during initialization or +reinitialization.") + +(defgeneric eieio-generic-function-lambda-list (generic-function) + "Returns the lambda list of the generic function. This is the +defaulted value of the :lambda-list initialization argument that +was associated with the generic function metaobject during +initialization or reinitialization. An error is signaled if the +lambda list has yet to be supplied.") + +(defgeneric eieio-generic-function-method-class (generic-function) + "Returns the default method class of the generic function. This +class must be a subclass of the class method. This is the +defaulted value of the :method-class initialization argument that +was associated with the generic function metaobject during +initialization or reinitialization.") + +(defgeneric eieio-generic-function-method-combination (generic-function) + "Returns the method combination of the generic function. This +is a method combination metaobject. This is the defaulted value +of the :method-combination initialization argument that was +associated with the generic function metaobject during +initialization or reinitialization.") + +(defgeneric eieio-generic-function-methods (generic-function) + "Returns the set of methods currently connected to the generic +function. This is a set of method metaobjects. This value is +maintained by the generic functions ADD-METHOD and +REMOVE-METHOD.") + +;; TODO: The SETF form... +;; +(defgeneric eieio-generic-function-name (generic-function) + "Returns the name of the generic function, or nil if the +generic function has no name. This is the defaulted value of +the :name initialization argument that was associated with the +generic function metaobject during initialization or +reinitialization. (Also see (setf generic-function-name) [EIEIO: +not implemented yet].)") + +(defmethod eieio-generic-function-argument-precedence-order + ((gf eieio-standard-generic-function)) + "TODO: write docstring." + (error "`eieio-generic-function-argument-precedence-order': not implemented yet!")) + +(defmethod eieio-generic-function-declarations + ((gf eieio-standard-generic-function)) + "TODO: write docstring." + (error "`eieio-generic-function-declarations': not implemented yet!")) + +(defmethod eieio-generic-function-lambda-list + ((gf eieio-standard-generic-function)) + "TODO: write docstring." + (oref gf lambda-list)) + +(defmethod eieio-generic-function-method-class + ((gf eieio-standard-generic-function)) + "TODO: write docstring." + (error "`eieio-generic-function-method-class': not implemented yet!")) + +(defmethod eieio-generic-function-method-combination + ((gf eieio-standard-generic-function)) + "TODO: write docstring." + (error "`eieio-generic-function-method-combination': not implemented yet!")) + +(defmethod eieio-generic-function-methods + ((gf eieio-standard-generic-function)) + "TODO: write docstring." + (oref gf methods)) + +(defmethod eieio-generic-function-name + ((gf eieio-standard-generic-function)) + "TODO: write docstring." + (oref gf name)) + +(defgeneric eieio-method-function (method) + "Returns the method function of method. This is the defaulted +value of the :function initialization argument that was +associated with the method during initialization.") + +(defgeneric eieio-method-generic-function (method) + "Returns the generic function that method is currently +connected to, or nil if it is not currently connected to any +generic function. This value is either a generic function +metaobject or nil. When a method is first created it is not +connected to any generic function. This connection is maintained +by the generic functions ADD-METHOD and REMOVE-METHOD.") + +(defgeneric eieio-method-lambda-list (method) + "Returns the (unspecialized) lambda list of method. This value +is a Common Lisp lambda list. This is the defaulted value of +the :lambda-list initialization argument that was associated with +the method during initialization.") + +(defgeneric eieio-method-specializers (method) + "Returns a list of the specializers of method. This value is a +list of specializer metaobjects. This is the defaulted value of +the :specializers initialization argument that was associated +with the method during initialization.") + +(defgeneric eieio-method-qualifiers (method) + "Returns a (possibly empty) list of the qualifiers of +method. This value is a list of non-nil atoms. This is the +defaulted value of the :qualifiers initialization argument that +was associated with the method during initialization.") + +(defgeneric eieio-accessor-method-slot-definition (method) + "This accessor can only be called on accessor methods. It +returns the direct slot definition metaobject that defined this +method. This is the value of the :slot-definition initialization +argument associated with the method during initialization.") + +(defmethod eieio-method-function ((m eieio-standard-method)) + "TODO: write docstring." + (oref m function)) + +(defmethod eieio-method-lambda-list ((m eieio-standard-method)) + "TODO: write docstring." + (oref m lambda-list)) + +(defmethod eieio-method-specializers ((m eieio-standard-method)) + "TODO: write docstring." + (oref m specializers)) + +(defmethod eieio-method-qualifiers ((m eieio-standard-method)) + "TODO: write docstring." + (oref m qualifiers)) + +(defmethod eieio-method-generic-function ((m eieio-standard-method)) + "TODO: write docstring." + (oref m generic-function)) + +(defmethod eieio-accessor-method-slot-definition + ((m eieio-standard-accessor-method)) + "TODO: write docstring." + (error "`eieio-accessor-method-slot-definition': not implemented yet!")) + ;;; Unimplemented functions from CLOS ;; |