[Openmcl-devel] Why is remhash being called here?

Ron Garret ron at flownet.com
Sun Jun 30 18:20:35 PDT 2013


On Jun 30, 2013, at 2:08 PM, Gary Byers wrote:

> My guess is that REMHASH is being called to remove something from a hash table.

Yes.  That much I was actually able to figure out on my own.

> If your next question is going to be something like "what hash table, and why
> is a hash table apparently being maintained when forms are being read bv the
> REPL (in this case) ?", a short answer is that this is involved in making
> M-. (the editor command) work in more cases for more people and in allowing
> DISASSEMBLE to annotate its output with the corresponding source code.

That would make sense except for two things:

1.  This happens in the command-line version too where there is no meta-.

2.  REMHASH is (apparently) only called when I evaluate a form that invokes a reader macro.

I know the toplevel does some things besides simply calling (print (eval (read))) but AFAIK none of those things should care (of even know) that a reader macro had been invoked.  Hence my puzzlement.

> If your next question is going to be "aren't there significant costs involved
> here, and do the benefits justify those costs ?", my answer would be a resounding ...
> oh wait, you haven't really asked that question.  Never mind.

Indeed, I have not asked that question.  I'm really just trying to understand why the toplevel is doing something different when a reader macro is invoked.

In hopes of being deemed worthy of a non-snarky answer, I did some more digging on my own.  The function that is calling remhash turns out to be ccl::read-recording-source:

? (trace ccl::read-recording-source)
NIL
? '$x
0> Calling (CCL::READ-RECORDING-SOURCE #<GUI::COCOA-LISTENER-INPUT-STREAM #x30200221A4BD> :EOFVAL (NIL) :FILE-NAME NIL :START-OFFSET NIL :MAP #<HASH-TABLE :TEST EQ size 0/60 #x30200221F89D> :SAVE-SOURCE-TEXT T) 
 1> Calling (REMHASH $X #<HASH-TABLE :TEST EQ size 2/60 #x30200221F89D>) 
 <1 REMHASH returned T
<0 CCL::READ-RECORDING-SOURCE returned 2 values :
<0      '$X
<0      #<SOURCE-NOTE Interactive "'$x ">

So the code that is calling remhash is (apparently):

(defun read-recording-source (stream &key eofval file-name start-offset map save-source-text)
  "Read a top-level form, perhaps recording source locations.
If MAP is NIL, just reads a form as if by READ.
If MAP is non-NIL, returns a second value of a source-note object describing the form.
In addition, if MAP is a hash table, it gets filled with source-note's for all
non-atomic nested subforms."
...
(loop for form being the hash-key using (hash-value note) of map
                   do (cond ((eq note source-note) nil)
                            ;; Remove entries with multiple source notes, which can happen
                            ;; for atoms.  If we can't tell which instance we mean, then we
                            ;; don't have useful source info.
                            ((listp note) (remhash form map))
                            ((loop for p = note then (source-note-source p) while (source-note-p p)
                                   thereis (eq p source-note))
                             ;; Flatten the backpointers so each subnote points directly
                             ;; to the toplevel note.
                             (setf (source-note.source note) source-note))))

But '$x doesn't have multiple source notes.  It shouldn't have any source notes at all.  And this code is beyond the limits of my ability to reverse-engineer it.  So any additional light you (or anyone else) could shed on this would be much appreciated.

rg




More information about the Openmcl-devel mailing list