common-lispreader-macro

Readtable conflicts with cl-annot (cl-syntax, jonathan) and pythonic-string-reader


I like pythonic-string-reader to enable python-esque triple quotes:

(defun hello ()
  """docstring"""
  :hello)

Use it:

(ql:quickload "pythonic-string-reader")
(pythonic-string-reader:enable-pythonic-string-syntax)

it also works with

(named-readtables:in-readtable pythonic-string-reader:pythonic-string-syntax)

But then I want to load the Jonathan library and I get a conflict:

(ql:quickload "jonathan")
=>
Reader macro conflict while trying to merge the macro character
#\" from #<NAMED-READTABLE CL-ANNOT::SYNTAX {1001CC18C3}> into
#<NAMED-READTABLE :CURRENT {1009474833}>.
   [Condition of type EDITOR-HINTS.NAMED-READTABLES:READER-MACRO-CONFLICT]


Backtrace:
  0: (EDITOR-HINTS.NAMED-READTABLES:MERGE-READTABLES-INTO #<NAMED-READTABLE :CURRENT {1009474833}> #<NAMED-READTABLE CL-ANNOT::SYNTAX {1001CC18C3}>)
      Locals:
        CHAR = #\"
        DISP? = NIL
        FROM = #<NAMED-READTABLE CL-ANNOT::SYNTAX {1001CC18C3}>
        NAMED-READTABLES = (#<NAMED-READTABLE CL-ANNOT::SYNTAX {1001CC18C3}>)
        READER-FN = #<FUNCTION SB-IMPL::READ-STRING>
        RESULT-READTABLE = #<NAMED-READTABLE :CURRENT {1009474833}>
        RESULT-TABLE = #<NAMED-READTABLE :CURRENT {1009474833}>
        TABLE = NIL
  1: (CL-SYNTAX::%USE-SYNTAX (:CL-ANNOT))
      Locals:
        NAMES = (:CL-ANNOT)

It isn't right, because I am not asking to use another readtable. Jonathan only uses cl-annot internally.

Who's bug is it (cl-syntax?) and how to solve it?


It works to load Jonathan first and then to enable the pythonic string syntax. However it isn't an acceptable work-around (I want to define a user package with the syntax enabled where the user could load any other library).


Looking at the cl-syntax line error it wants to merge readtables (merge-readtables-into *readtable* syntax) ), at the same time it seems to correctly use copy-readtable:

(defun %use-syntax (names)
  (declare (type (or syntax-designator
                     (proper-list syntax-designator))
                 names))
  (unless (listp names)
    (setq names (list names)))
  (setq *readtable* (copy-readtable))
  (loop for name in names
        for syntax = (find-syntax name)
        for options = (get-options name)
        if (assoc :fuze (if (consp (car options)) options (cdr options))) do
          (handler-bind ((named-readtables:reader-macro-conflict
                            (lambda (_) (declare (ignore _))
                              (invoke-restart 'continue))))
             (merge-readtables-into *readtable* syntax) )
        else do
          (merge-readtables-into *readtable* syntax) )
  (when (find-package :swank)
    (named-readtables::%frob-swank-readtable-alist *package* *readtable*)))

Any ideas? Thanks.


Solution

  • Evaluating

    (cl-syntax::get-options :CL-ANNOT)
    

    Gives

    ((:MERGE :STANDARD)
     (:MACRO-CHAR #\@ #'CL-ANNOT.SYNTAX:ANNOTATION-SYNTAX-READER))
    

    It looks like the syntax is supposed to merge the :standard readtable, not the curent one. I suspect (copy-readtable nil) would be the better choice here in the function you described.