Hello, Your friendly neighborhood (oop goops) has been nationalized and reclaimed by a group calling itself the "People's Compilation Front" (PCF). I found the following note scrawled on the back of a page of R6RS, and wished to communicate it to the wider Guile community. I've added some comments.
$ ./pre-inst-guile Guile Scheme interpreter 0.5 on Guile 1.9.0 Copyright (C) 2001-2008 Free Software Foundation, Inc. Enter `,help' for help. We should release 1.9.1 soon, no? Maybe that way the PCF can keep the old version and we can have the new one, like detente in the 70s. scheme@(guile-user)> (use-modules (oop goops)) I am afraid that it takes a bit longer to load than it used to; there are margin notes on the document that suggest that large speedups are possible, however. scheme@(guile-user)> (define-class <foo> ()) scheme@(guile-user)> (define-method (bar (x <foo>)) (pk 'hi-mom)) scheme@(guile-user)> (bar (make <foo>)) ;;; (hi-mom) $1 = hi-mom OK, so the PCF knows how to define classes and invoke methods. What's the big deal? scheme@(guile-user)> (slot-ref (car (generic-function-methods bar)) 'code-table) $2 = ((#<<class> <foo> 86971d0> . #<program #(2 35 #f) (x)>)) Oooh, is that a compiled method? scheme@(guile-user)> ,x (cdar $2) Disassembly of #<program #(2 35 #f) (x)>: nargs = 1 nrest = 0 nlocs = 0 nexts = 0 Bytecode: 0 (late-variable-ref 0) ;; #<program peek stuff> 2 (object-ref 1) ;; hi-mom at (unknown file):2:35 4 (goto/args 1) at (unknown file):2:31 Why yes, yes it is! scheme@(guile-user)> (define-class <baz> (<foo>)) scheme@(guile-user)> (define-method (bar (x <baz>)) (pk 'hi-dad) (next-method)) scheme@(guile-user)> (bar (make <baz>)) ;;; (hi-dad) ;;; (hi-mom) $3 = hi-mom OK... not sure where they're going.. Although, I guess since there is a (next-method) in this one, the case is slightly different... scheme@(guile-user)> (slot-ref (car (generic-function-methods bar)) 'code-table) $4 = ((#<<class> <baz> 85ce110> . #<program 853f980 (x)>)) It took me a while to figure out why this didn't include the old entry, but besides any cache invalidation effects, the PCF failed to note that (generic-function-methods bar) was added to, with the new method defined above -- must be the method on <baz>. scheme@(guile-user)> ,x (cdar $4) Disassembly of #<program 853f980 (x)>: nargs = 1 nrest = 0 nlocs = 1 nexts = 1 Bytecode: 0 (local-ref 0) ;; `x' (arg) 2 (external-set 0) ;; `x' (arg) OK, capture the `x' arg on the heap... 4 (object-ref 0) ;; #<program 853fa28 args> 6 (make-closure) 7 (local-set 1) ;; `next-method' These instructions appear to bind the `next-method' local to some program stuffed in object slot 0... 9 (late-variable-ref 1) ;; #<program peek stuff> 11 (object-ref 2) ;; hi-dad 13 (call 1) 15 (drop) 16 (local-ref 1) ;; `next-method' 18 (goto/args 0) Aha, here they invoke the next method just by referencing the precomputed local procedure! That's quite clever of them, those compilationists. Externals: 0 #<program #(2 35 #f) (x)> ---------------------------------------- Disassembly of #<program 853fa28 args>: nargs = 1 nrest = 1 nlocs = 0 nexts = 0 Bytecode: 0 (local-ref 0) ;; `args' (arg) 2 (null?) 3 (br-if-not 0 6) ;; -> 12 So here we're disassembling the next-method stub; it appears to check if the rest argument `args' is null; if it is, we continue through here: 6 (external-ref 1) ;; (closure variable) 8 (external-ref 0) ;; (closure variable) 10 (goto/args 1) Which appears to tail-call external #1 (relative to this procedure) with the argument that is in external #0. #1 is probably that procedure above that was not disassembled, and #0 would be `x'. 12 (external-ref 1) ;; (closure variable) 14 (local-ref 0) ;; `args' (arg) 16 (goto/apply 2) And this seems to be `(apply <external-1> args)', for the case in which `(next-method)' is given arguments. Well, what can I say, those compilationists might be some loony people, but their code looks correct. Should I send them a GNU copyright assignment form? GNU takes all kinds, no? Andy -- http://wingolog.org/