git.fiddlerwoaroof.com
Raw Blame History
(in-package :objc-runtime)

#+ccl
(defgeneric send-message (object message &rest args)
  (:method ((object ccl:macptr) (message (eql 'alloc)) &rest args)
    (apply #'objc-msg-send object (ensure-selector "alloc") args)))

(defun read-until (test symbol-prefix &optional stop-before-chars)
  "Read from a string until"
  (lambda (s c b)
    (declare (ignore c b))
    (let ((class-name (coerce (loop for next-char = (peek-char nil s nil nil t)
                                 while next-char
                                 until (funcall test next-char)
                                 collect (read-char s t nil t)
                                 finally (when (and (not (member next-char
                                                                 stop-before-chars))
                                                    (funcall test next-char))
                                           (read-char s t nil t)))

                              'string)))
      `(,symbol-prefix ,class-name))))

(named-readtables:defreadtable :objc-readtable
  (:merge :standard)
  (:syntax-from :standard #\) #\])
  (:macro-char #\[ (lambda (s char)
                     char
                     (let ((info (read-delimited-list #\] s t))
                           (msg-send (case (peek-char nil s nil #\p t)
                                       (#\# (read-char s t nil t) 'objc-msg-send-int)
                                       (#\s (read-char s t nil t) 'objc-msg-send-string)
                                       (#\@ (read-char s t nil t) 'objc-msg-send-nsstring)
                                       (#\& (read-char s t nil t) 'objc-msg-send)
                                       (t 'objc-msg-send))))
                       (when info
                         (destructuring-bind (obj message . args) info
                           `(,msg-send ,obj ,message ,@args)))))
               nil)
  (:dispatch-macro-char #\# #\@
                        (lambda (s c b)
                          c b
                          (let ((class-name (coerce (loop for c = (peek-char nil s nil nil t)
                                                       until (or (null c)
                                                                 (serapeum:whitespacep c)
                                                                 (member c
                                                                         '(#\) #\(  #\[ #\])))
                                                       collect (read-char s t nil t))
                                                    'string)))
                            `(objc-look-up-class ,class-name))))
  (:macro-char #\@ :dispatch t)
  (:dispatch-macro-char #\@ #\( (read-until (serapeum:op (char= _ #\)))
                                            'ensure-selector))
  (:dispatch-macro-char #\@ #\" (read-until (serapeum:op (char= _ #\"))
                                            'make-nsstring)))