/[advanced-readtable]/src.lisp
ViewVC logotype

Diff of /src.lisp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1 by rklochkov, Thu Sep 20 07:50:22 2012 UTC revision 12 by rklochkov, Mon Dec 31 13:39:29 2012 UTC
# Line 1  Line 1 
 (in-package #:advanced-readtable)  
   
 ;;;  
 ;;; study virgin readtable  
 ;;;  
   
 (defmacro with-case (case &body body)  
   (let ((save (gensym)))  
     `(let ((,save (readtable-case *readtable*)))  
        (setf (readtable-case *readtable*) ,case)  
        (unwind-protect  
             (progn ,@body)  
          (setf (readtable-case *readtable*) ,save)))))  
   
 (defun does-not-terminate-token-p (c)  
   (ignore-errors  
     (let ((str (format nil "a~Ab" c)))  
       (string= str (symbol-name  
                     (with-case :preserve  
                       (read-from-string (format nil "#:~A" str))))))))  
   
   
 (defun whitespace[2]-p (c)  
   (ignore-errors  
     (= 2 (length (read-from-string (format nil "(#:a~A#:b)" c))))))  
   
 (defun multiple-escape-p (c)  
   (ignore-errors  
     (string= "qQ" (symbol-name  
                    (with-case :upcase  
                      (read-from-string (format nil "#:~AqQ~A" c c)))))))  
   
 (defun single-escape-p (c)  
   (ignore-errors  
     (string= (symbol-name '#:\') (symbol-name  
                                   (read-from-string (format nil "#:~A'" c))))))  
   
   
   
 (defun macro-char-p (c)  
   "If C is macro-char, return GET-MACRO-CHARACTER"  
   #+allegro (unless  
                 (eql (get-macro-character c) #'excl::read-token)  
               (get-macro-character c))  
   #-allegro (get-macro-character c))  
   
 (defun fill-char-table ()  
   "Returns simple-vector with character syntax classes"  
   (let ((*readtable* (copy-readtable nil))  
         (char-table (make-array 127)))  
     (dotimes (i (length char-table))  
       (let ((c (code-char i)))  
         (setf  
          (svref char-table i)  
          (cond  
            ((eql c #\:) :colon)  
            ((macro-char-p c) :macro)  
            ((does-not-terminate-token-p c) :does-not-terminate-token)  
            ((whitespace[2]-p c) :whitespace[2])  
            ((multiple-escape-p c) :multiple-escape)  
            ((single-escape-p c) :single-escape)))))  
     char-table))  
   
 (defvar *advanced-readtable* (copy-readtable nil))  
 (defvar *colon-readtable* (copy-readtable nil)  
   "Support readtable with colon as whitespace")  
   
 ;;;  
 ;;; Readtable handlers  
 ;;;  
   
 (defpackage #:advanced-readtable.junk)  
   
 (defun read-token (stream)  
   "  
 DO: Reads from STREAM a symbol or number up to whitespace or colon  
 RETURN: symbols name or numbers value"  
   (let ((*readtable* *colon-readtable*)  
         (*package* (cl:find-package '#:advanced-readtable.junk)))  
     (let ((sym (read-preserving-whitespace stream nil)))  
       (if (symbolp sym)  
           (prog1  
               (symbol-name sym)  
             (unintern sym))  
           sym))))  
   
 (defun count-colons (stream)  
   "  
 DO: Reads colons from STREAM  
 RETURN: number of the colons"  
   (let ((c (read-char stream nil)))  
     (if (eql c #\:)  
         (+ 1 (count-colons stream))  
         (progn (unread-char c stream) 0))))  
   
 (defvar *per-package-finders* (make-hash-table :test 'eq)  
   "Hash package -> list of handlers")  
 (defvar *package-finders* nil  
   "List of handlers (lambda (name package) ...) -> package")  
   
 (defun try-funcall (handlers-list name package)  
   (declare (type list handlers-list)  
            (type string name)  
            (type (or null package) package))  
   (when handlers-list  
     (or (funcall (car handlers-list) name package)  
         (try-funcall (cdr handlers-list) name package))))  
   
 (defun find-package (name &optional (current-package *package*))  
   (declare (type (or null package) current-package))  
   (if (typep name 'package) name  
       (let ((sname (string name)))  
         (or (cl:find-package name)  
             (when current-package  
               (try-funcall (package-finders current-package) sname  
                            current-package))  
             (try-funcall *package-finders* sname current-package)))))  
   
 (defvar *package-symbol-finders* (make-hash-table :test 'eq)  
   "Hash package -> list of handlers")  
 (defvar *symbol-finders* nil  
   "List of handlers (lambda (name package) ...) -> symbol")  
   
 (defun find-symbol (name &optional dpackage)  
   (declare (type string name))  
   (let ((package (find-package dpackage)))  
     (macrolet ((mv-or (&rest clauses)  
                  (if clauses  
                      `(multiple-value-bind (symbol status) ,(car clauses)  
                         (if symbol (values symbol status)  
                             (mv-or ,@(cdr clauses))))  
                      `(values nil nil))))  
   
     (mv-or (if package  
             (cl:find-symbol name package)  
             (cl:find-symbol name))  
         (when package  
           (try-funcall (symbol-finders package) name package))  
         (try-funcall *symbol-finders* name package)))))  
   
 (defvar *symbol-readmacros* (make-hash-table :test 'eq))  
 (defvar *disable-symbol-readmacro* nil  
   "Disables processing of symbol-readmacro.")  
   
 (defun def-symbol-readmacro (symbol func)  
   (setf (gethash symbol *symbol-readmacros*) func))  
   
 (defun process-symbol-readmacro (symbol stream)  
   (let ((func (gethash symbol *symbol-readmacros*)))  
     (if func (funcall func symbol stream) symbol)))  
   
 (defun read-token-with-colons (stream char)  
   "Reads token, then analize package part if needed"  
   (unread-char char stream)  
   (if *read-suppress* (let ((*readtable* (copy-readtable nil)))  
                         (read stream))  
       (let* ((tok (read-token stream))  
              ;; We have read something.  
              ;; It may represent either symbol or package designator.  
              ;; Looking after it: do we have a colon?  
              (cnt (count-colons stream))  
              (sym (if (= cnt 0)  
                       (if (stringp tok) (intern tok) tok)  
                       (let ((package (find-package tok *package*)))  
                         (assert package (package) "No package ~a" tok)  
                         (multiple-value-bind (symbol status)  
                             (find-symbol (read-token stream) package)  
                           (when (and (= cnt 1) (not (eq status :external)))  
                             (cerror "Use anyway"  
                                     "Symbol ~A not external" symbol))  
                           symbol)))))  
   
         (if (or *disable-symbol-readmacro*  
                 (not (symbolp sym)) (eql char #\|))  
             sym  
             (process-symbol-readmacro sym stream)))))  
   
   
 ;;;  
 ;;; Prepare readtables  
 ;;;  
   
 (let (initialized)  
   (defun activate (&optional force)  
     "Inits *advanced-readtable* and *colon-readtable*."  
     (when (or force (not initialized))  
       (setq initialized t)  
       (let ((char-table (fill-char-table)))  
         (dotimes (i (length char-table))  
           (let ((b (svref char-table i))  
                 (c (code-char i)))  
             (unless (char= #\# c)  
               (when (member b '(:does-not-terminate-token  
                                 :multiple-escape :single-escape))  
                 ;; will make it non-terminating macro character  
                 ;;    = potentially beginning of the package-name  
                 (set-macro-character c #'read-token-with-colons  
                                      t *advanced-readtable*))))))  
   
       (set-syntax-from-char #\: #\Space *colon-readtable* *colon-readtable*))  
     (setf *readtable* *advanced-readtable*)))  
   
 (defun ! () (activate))  
   
 (defun (setf package-finders) (value &optional (package *package*))  
   (setf (gethash package *per-package-finders*) value))  
   
 (defun package-finders (&optional (package *package*))  
   (gethash package *per-package-finders*))  
   
 (defun (setf symbol-finders) (value &optional (package *package*))  
   (setf (gethash package *package-symbol-finders*) value))  
   
 (defun symbol-finders (&optional (package *package*))  
   (gethash package *package-symbol-finders*))  
   
   
 (defun push-import-prefix (package prefix)  
   (push (lambda (name package)  
           (declare (ignore package))  
           (cl:find-package (concatenate 'string prefix "." name)))  
         (package-finders package)))  
   
 (defun push-local-nickname (long-package nick  
                             &optional (current-package *package*))  
   (let ((long-name (package-name (find-package long-package))))  
     (push (lambda (name package)  
             (declare (ignore package))  
             (when (string= name (string nick)) long-name))  
         (package-finders current-package))))  
   
1    (in-package #:advanced-readtable)
2    
3    ;;;; Advanced-readtable
4    ;;;;
5    ;;;; per-package aliases for packages
6    ;;;; per-package shortcuts for package hierarchies
7    ;;;; extendable find-package and find-symbol
8    ;;;; local use package in form package:(here form where package used)
9    ;;;; local intern package like in SBCL: package::(symbol1 symbol2) will intern
10    ;;;;                                    package::symbol1 and package::symbol2
11    
12    (defvar *per-package-finders* (make-hash-table :test 'eq)
13      "Hash package -> list of handlers. Each handler is a cons (key . function)")
14    (defvar *package-finders* nil
15      "List of handlers. Each handler is a cons (key . function)
16    function = (lambda (name package) ...) -> package")
17    
18    ;;;
19    ;;; Prepare readtables
20    ;;;
21    
22    (defvar *advanced-readtable* (copy-readtable nil))
23    (defvar *colon-readtable* (copy-readtable nil)
24      "Support readtable with colon as whitespace")
25    
26    ;;;
27    ;;; Readtable handlers
28    ;;;
29    
30    (defpackage #:advanced-readtable.junk)
31    
32    (defun try-funcall (handlers-list name package)
33      (declare (type list handlers-list)
34               (type string name)
35               (type (or null package) package))
36      (when handlers-list
37        (or (funcall (cdr (car handlers-list)) name package)
38            (try-funcall (cdr handlers-list) name package))))
39    
40    (defun find-package (name &optional (current-package *package*))
41      "We try to find package.
42    1. By full name with CL:FIND-PACKAGE.
43    2. By per-package handlers. Here we wil try local-nicknames and so on.
44    3. By global handlers. Here we may use, for example, hierarchical packages."
45      (declare (type (or null package) current-package))
46      (if (typep name 'package) name
47          (let ((sname (string name)))
48            (or
49             (cl:find-package name)
50             (when current-package
51               (try-funcall (package-finders current-package)
52                            sname current-package))
53             (try-funcall *package-finders* sname current-package)))))
54    
55    (defvar *package-symbol-finders* (make-hash-table :test 'eq)
56      "Hash package -> list of handlers. Each handler is a cons (key . function)")
57    (defvar *symbol-finders* nil
58      "List of handlers. Each handler is a cons (key . function)
59    function =  (lambda (name package) ...) -> symbol")
60    (defvar *extra-finders* (make-hash-table :test 'eq)
61      "Hash symbol -> list of handlers. Each handler is a cons (key . function)
62    function = (lambda (name package) ...) -> symbol
63    These will be used before CL:FIND-SYMBOL")
64    
65    (defvar *symbol-readmacros* (make-hash-table :test 'eq))
66    (defvar *disable-symbol-readmacro* nil
67      "Disables processing of symbol-readmacro.")
68    
69    (defun def-symbol-readmacro (symbol func)
70      (setf (gethash symbol *symbol-readmacros*) func))
71    
72    (defun set-macro-symbol (symbol func)
73      "Syntax is like set-macro-character,
74    except that FUNC is binded to SYMBOL, not character"
75      (setf (gethash symbol *symbol-readmacros*) func))
76    
77    (defun get-macro-symbol (symbol)
78      "Syntax is like get-macro-character.
79    Returns function, assigned by set-macro-symbol"
80      (gethash symbol *symbol-readmacros*))
81    
82    (defun process-symbol-readmacro (symbol stream)
83      (let ((func (gethash symbol *symbol-readmacros*)))
84        (if func (funcall func stream symbol) symbol)))
85    
86    ;;; Internal special variables. Do not export
87    
88    (defvar *extra-symbol-finders* nil
89      "List of handlers: handlers for symbol, car of list")
90    (defvar *car-list* nil "Boolean: iff reader in list and car is not read")
91    (defvar *local-packages* nil "List of packages: for pack:( ... pack2:(...))")
92    
93    (defun try-local-packages (packages name)
94      (when packages
95        (multiple-value-bind (symbol status) (cl:find-symbol name (car packages))
96          (if symbol
97              (values symbol status)
98              (try-local-packages (cdr packages) name)))))
99    
100    (defun try-mv-funcall (handlers-list name package)
101      "Returns symbol, status"
102      (declare (type list handlers-list)
103               (type string name)
104               (type (or null package) package))
105      (when handlers-list
106        (multiple-value-bind (symbol status)
107            (funcall (cdr (car handlers-list)) name package)
108          (if symbol
109              (values symbol status)
110              (try-funcall (cdr handlers-list) name package)))))
111    
112    
113    (defun find-symbol (name &optional dpackage)
114      "We try to find symbol
115    1. In package set with car of list, for example, PUSH-LOCAL-PACKAGE
116    2. By CL-FIND-SYMBOL, when package explicitly given
117    3. By packages added with package:(...)
118    4. By per-package finders
119    5. By global finders
120    6. By CL-FIND-SYMBOL"
121      (declare (type string name))
122      (let ((package (if dpackage (find-package dpackage) *package*)))
123        (macrolet ((mv-or (&rest clauses)
124                     (if clauses
125                         `(multiple-value-bind (symbol status) ,(car clauses)
126                            (if symbol (values symbol status)
127                                (mv-or . ,(cdr clauses))))
128                         `(values nil nil))))
129    
130          (mv-or
131           (try-mv-funcall *extra-symbol-finders* name package)
132           (when dpackage (cl:find-symbol name package))
133           (unless dpackage (try-local-packages *local-packages* name))
134           (try-mv-funcall (symbol-finders package) name package)
135           (try-mv-funcall *symbol-finders* name package)
136           (unless dpackage (cl:find-symbol name package))))))
137    
138    (defun read-token (stream)
139      "
140    DO: Reads from STREAM a symbol or number up to whitespace or colon
141    RETURN: symbols name or numbers value"
142      (let ((*readtable* *colon-readtable*)
143            (*package* (cl:find-package '#:advanced-readtable.junk)))
144        (read-preserving-whitespace stream nil)))
145    
146    (defun count-colons (stream)
147      "
148    DO: Reads colons from STREAM
149    RETURN: number of the colons"
150      (let ((c (read-char stream nil)))
151        (if (eql c #\:)
152            (+ 1 (count-colons stream))
153            (progn (unread-char c stream) 0))))
154    
155    (defun read-after-colon (stream maybe-package colons)
156      "Read symbol package:sym or list package:(...)"
157      (declare (type stream stream)
158               (type (integer 0 2) colons))
159      (check-type colons (integer 0 2))
160      (when (= colons 0) ; no colon: this is a symbol or an atom
161        (return-from read-after-colon
162          (if (symbolp maybe-package)
163              (prog1
164                  (let ((name (symbol-name maybe-package)))
165                    (or (find-symbol name) (intern name)))
166                (unintern maybe-package))
167              maybe-package)))
168    
169      (let ((package (find-package maybe-package)))
170        (assert package (package) "No package ~a" maybe-package)
171        (unintern maybe-package)
172        (when (eql (peek-char t stream) #\()
173          ;; package:(...) or package::(...)
174          (ecase colons
175            (1 (let ((*local-packages* (cons package *local-packages*)))
176                 (return-from read-after-colon
177                   (read stream nil))))
178            (2 (let ((*package* package))
179                 (return-from read-after-colon
180                   (read stream nil))))))
181    
182        (let ((token (read-token stream)))
183          (check-type token symbol)
184          (multiple-value-bind (symbol status)
185              (find-symbol (symbol-name token) package)
186            (unless status
187              (if (= colons 1) (error "No external symbol ~S in ~S"
188                                      (symbol-name token) package)
189                  (cerror "Intern ~S in ~S" "No such symbol ~S in package ~S"
190                          (symbol-name token) package)))
191            (unintern token)
192            (when (and (= colons 1) (not (eq status :external)))
193              (cerror "Use anyway"
194                      "Symbol ~A not external" symbol))
195            symbol))))
196    
197    
198    
199    (defun read-token-with-colons (stream char)
200      "Reads token, then analize package part if needed"
201      (unread-char char stream)
202      (when *read-suppress*
203        (let ((*readtable* (copy-readtable nil)))
204          (read stream))
205        (return-from read-token-with-colons))
206      (let* ((token (read-token stream))
207             ;; We have read something.
208             ;; It may represent either symbol or package designator.
209             ;; Looking after it: do we have a colon?
210             (colons (count-colons stream))
211             (object (read-after-colon stream token colons)))
212    
213        (when (or *disable-symbol-readmacro*
214                  (not (symbolp object))
215                  (eql char #\|))
216            (return-from read-token-with-colons object))
217    
218        (let ((object (process-symbol-readmacro object stream)))
219          (when *car-list*
220            (setf *car-list* nil
221                  *extra-symbol-finders*
222                  (append (extra-finders object) *extra-symbol-finders*)))
223          object)))
224    
225    (let ((default-open-paren-reader
226           (get-macro-character #\( (copy-readtable nil))))
227      (defun open-paren-reader (stream char)
228        (let ((*car-list* t) (*extra-symbol-finders* *extra-symbol-finders*))
229          (funcall default-open-paren-reader stream char))))
230    
231    
232    
233    (defun (setf package-finders) (value &optional (package *package*))
234      (setf (gethash (find-package package) *per-package-finders*) value))
235    
236    (defun package-finders (&optional (package *package*))
237      (gethash (find-package package) *per-package-finders*))
238    
239    (defun (setf symbol-finders) (value &optional (package *package*))
240      (setf (gethash (find-package package) *package-symbol-finders*) value))
241    
242    (defun symbol-finders (&optional (package *package*))
243      (gethash (find-package package) *package-symbol-finders*))
244    
245    (defun (setf extra-finders) (value symbol)
246      (setf (gethash symbol *extra-finders*) value))
247    
248    (defun extra-finders (symbol)
249      (gethash symbol *extra-finders*))
250    
251    (defmacro set-handler (handler-list key function)
252      "This is middle-level public API for changing handlers for
253    find-symbol and find-package. There are five lists:
254      *package-finders* -- global for find-package
255      *symbol-finders* -- global for find-symbol
256      (package-finders package) -- per-package for find-package
257      (symbol-finders package) -- per-package for find-symbol
258      (extra-finders symbol) -- per-symbol for (symbol ....) package substitution
259    
260    Key should be uniq in the sense of EQUAL in the list. SET-HANDLER adds
261    new handler if it is not already there.
262    "
263      (let ((key-var (gensym "key")))
264        `(let ((,key-var ,key))
265           (unless (assoc ,key-var ,handler-list :test #'equal)
266             (push (cons ,key-var ,function)
267                   ,handler-list)))))
268    
269    (defmacro %set-handler (handler-list key name &body handler-body)
270      "Local macros for push-* functions. No gensyms intended."
271      `(set-handler ,handler-list ,key
272                    (lambda (,name package)
273                      (declare (ignore package)) . ,handler-body)))
274    
275    (defun push-import-prefix (prefix &optional (package *package*))
276      "Enables using package name omitting prefix.
277    For example, you have packages com.clearly-useful.iterator-protocol, com.clearly-useful.reducers, ...
278    You may use them as
279     (push-import-prefix :com.clearly-useful)
280     (iterator-protocol:do-iterator ...)
281     (reducers:r/map #'1+ data)
282    and so on.
283    Package prefix is enabled per package so it is safe to use it in your package.
284    
285    If there is package, which name coincides with shortcut, package name has priority.
286    
287    So, if you make
288     (defpackage :reducers ...)
289    
290    after that reducers:... will refer to new package, not com.clearly-useful.reducers.
291    "
292      (%set-handler (package-finders package) `(:prefix ,prefix) name
293        (cl:find-package (concatenate 'string (string prefix) "." name))))
294    
295    (defun push-local-nickname (long-package nick
296                                &optional (current-package *package*))
297      "Enables package nickname in CURRENT-PACKAGE.
298    For example, you found COM.INFORMATIMAGO.COMMON-LISP.CESARUM.LIST package and want to use
299    it. But don't want to USE-PACKAGE them, because some exported symbols from it are clashing
300    with yours.
301    
302    You may do it right:
303     (push-local-nickname :com.informatimago.common-lisp.cesarum.list :ilist)
304     (ilist:circular-length l)
305    
306    Local-nicknames are local, so you may use it freely.
307    
308    If package A wants  package LIB version 1, and package B wants package
309    LIB version 2, one can simply rename LIB version 1 to LIB1 and rename LIB
310    version 2 to LIB2 and make
311     (push-local-nickname :lib1 :lib :a)
312     (push-local-nickname :lib2 :lib :b)
313    "
314      (let ((dpackage (find-package long-package)))
315        (%set-handler (package-finders current-package) `(:nick ,long-package ,nick) name
316          (when (string= name (string nick)) dpackage))))
317    
318    (defun push-local-package (symbol local-package)
319      "Sets local-package for a symbol. Many macroses use there own clauses.
320    For example, ITERATE uses FOR, COLLECT and so on.
321    If you don't want to USE-PACKAGE iterate, this function will help.
322     (push-local-package 'iter:iter :iterate)
323     (iter:iter (for i from 1 to 10) (collect i))
324    
325    Caution: this function enables package substitution in all cases,
326    where SYMBOL is the car of a list.
327    For example, this will be error:
328     (let (iter:iter for) (list iter:iter for))
329    , because first for is in ITERATE package, but second -- is not.
330    "
331      (let ((dpackage (find-package local-package)))
332        (%set-handler (extra-finders symbol) `(:local ,symbol ,local-package) name
333          (multiple-value-bind (symbol status) (cl:find-symbol name dpackage)
334            (when (eq status :external) symbol)))))
335    
336    ;;;
337    ;;; Readtable analysis and change
338    ;;;
339    
340    (defmacro with-case (case &body body)
341      (let ((save (gensym)))
342        `(let ((,save (readtable-case *readtable*)))
343           (setf (readtable-case *readtable*) ,case)
344           (unwind-protect
345                (progn ,@body)
346             (setf (readtable-case *readtable*) ,save)))))
347    
348    (defun does-not-terminate-token-p (c)
349      (ignore-errors
350        (let ((str (format nil "a~Ab" c)))
351          (string= str (symbol-name
352                        (with-case :preserve
353                          (read-from-string (format nil "#:~A" str))))))))
354    
355    
356    (defun whitespace-p (c)
357      (ignore-errors
358        (= 2 (length (read-from-string (format nil "(#:a~A#:b)" c))))))
359    
360    (defun multiple-escape-p (c)
361      (ignore-errors
362        (string= "qQ" (symbol-name
363                       (with-case :upcase
364                         (read-from-string (format nil "#:~AqQ~A" c c)))))))
365    
366    (defun single-escape-p (c)
367      (ignore-errors
368        (string= (symbol-name '#:\ ) (symbol-name
369                                      (read-from-string (format nil "#:~A'" c))))))
370    
371    
372    
373    (defun macro-char-p (c)
374      "If C is macro-char, return GET-MACRO-CHARACTER"
375      #+allegro (unless
376                    (eql (get-macro-character c) #'excl::read-token)
377                  (get-macro-character c))
378      #-allegro (get-macro-character c))
379    
380    (defun fill-char-table ()
381      "Returns simple-vector with character syntax classes"
382      (let ((*readtable* (copy-readtable nil))
383            (char-table (make-array 127)))
384        (dotimes (i (length char-table))
385          (let ((c (code-char i)))
386            (setf
387             (svref char-table i)
388             (cond
389               ((eql c #\:) :colon)
390               ((macro-char-p c) :macro)
391               ((does-not-terminate-token-p c) :does-not-terminate-token)
392               ((whitespace-p c) :whitespace)
393               ((multiple-escape-p c) :multiple-escape)
394               ((single-escape-p c) :single-escape)))))
395        char-table))
396    
397    (let (initialized)
398      (defun activate (&optional force)
399        "Inits *advanced-readtable* and *colon-readtable*."
400        (when (or force (not initialized))
401          (setq initialized t)
402          (let ((char-table (fill-char-table)))
403            (dotimes (i (length char-table))
404              (let ((b (svref char-table i))
405                    (c (code-char i)))
406                (unless (char= #\# c)
407                  (when (member b '(:does-not-terminate-token
408                                    :multiple-escape :single-escape))
409                    ;; will make it non-terminating macro character
410                    ;;    = potentially beginning of the package-name
411                    (set-macro-character c #'read-token-with-colons
412                                         t *advanced-readtable*))))))
413    
414          (set-syntax-from-char #\: #\Space *colon-readtable* *colon-readtable*)
415          (set-macro-character #\( #'open-paren-reader nil *advanced-readtable*))
416        (setf *readtable* *advanced-readtable*)))
417    
418    (defun ! () (activate))

Legend:
Removed from v.1  
changed lines
  Added in v.12

  ViewVC Help
Powered by ViewVC 1.1.5