Opened 9 years ago

Closed 9 years ago

Last modified 9 years ago

#665 closed defect (invalid)

Setting a reader macro for a constituent breaks objc method syntax

Reported by: rongarret Owned by:
Priority: normal Milestone:
Component: Objective-C Bridge Version: trunk
Keywords: Cc:

Description

SLSIA. Here's an example:

Welcome to Clozure Common Lisp Version 1.5-dev-r13442M-trunk  (DarwinX8664)!
? (#/title (car (gui::windows)))
#<NS-MUTABLE-STRING "Listener" (#x1D03B0)>
? (set-macro-character #\e (lambda (stream char) char) t)
;Compiler warnings :
;   In an anonymous lambda form at position 25: Unused lexical variable STREAM
T
? (#/title (car (gui::windows)))
> Error: Undefined function NEXTSTEP-FUNCTIONS:|titl| called with arguments (#\e #<HEMLOCK-LISTENER-FRAME <HemlockListenerFrame: 0x1cd640> (#x1CD640)>) .

Here's the fix:

(set-dispatch-macro-character #\# #\/
  (let ((rt (copy-readtable nil)))
    (lambda (stream subchar numarg)
      (declare (ignorable subchar numarg))
      (let* ((token (make-array 16 :element-type 'character :fill-pointer 0 :adjustable t))
             (attrtab (rdtab.ttab rt)))
        (when (peek-char t stream nil nil)
          (loop
            (multiple-value-bind (char attr)
                                 (%next-char-and-attr stream attrtab)
              (unless (eql attr $cht_cnst)
                (when char (unread-char char stream))
                (return))
              (vector-push-extend char token))))
        (unless *read-suppress*
          (unless (> (length token) 0)
            (signal-reader-error stream "Invalid token after #/."))
          (check-objc-message-name token)
          (intern token "NSFUN"))))))

NOTE: This issue is related to the issue of reader macros affecting the syntax of uninterned symbols, which generate some controversy on the mailing list. In this case, the syntax of objective-C function names is not governed by the ANSI standard, so the controversy is moot.

Change History (5)

comment:1 Changed 9 years ago by gb

  • Resolution set to invalid
  • Status changed from new to closed

Changing the syntax of lisp definitely ... changes the syntax of lisp.

If you want to do this, you already know how to make #/ work in a modified readtable. HINT: IT DOESN"T INVOLVE CHANGING THE STANDARD READTABLE.

comment:2 Changed 9 years ago by gb

Er, the initial readtable. (I mean, THE INITIAL READTABLE.)

comment:3 Changed 9 years ago by rongarret

Please note that in my example the reader macro for #\e is non-terminating. So regardless of one's position about what the correct behavior for #/ ought to be (which is debatable since it is not governed by any standard), this still seems to me to be a legitimate bug. Other kinds of tokens are not affected:

? (set-macro-character #\e (lambda (stream char) char) t)
;Compiler warnings :
;   In an anonymous lambda form at position 25: Unused lexical variable STREAM
T
? (defun title () t)
TITLE
? #'title
#<Compiled-function TITLE #x302001B64F3F>
? (title)
T
? ':title
:TITLE
? '#:title
#:TITLE

I think you'd be hard pressed to make a case for why all those should work by #/title should not.

comment:4 Changed 9 years ago by rongarret

s/by/but/

comment:5 Changed 9 years ago by gb

(set-dispatch-macro-character #\# #\/
  (lambda (stream char subchar)
    (let* ((*readtable* (copy-readtable)) ; or cache the copy somewhere
           (f (get-dispatch-macro-character #\# #\/)))
      (if f
        (funcall f stream char subchar)
        (error "#/ reader macro not yet defined in initial readtable"))))
   *my-readtable*)

If you want to change the current readtable so that it no longer implements standard syntax but want predefined reader macros that're sensitive to character attributes to behave as they normally do, I think that it's your responsibility to ensure that behavior. (I also think that it's trivial to do that.)

I've already spent many hours of my time explaining why I believe this; I don't know if you genuinely disagree or if the point just isn't clear to you, but I don't believe that I can say any of this any more clearly than I already have, and I don't have the interest or energy or time to keep saying the same things over and over again.

Note: See TracTickets for help on using tickets.