Skip to content

Commit

Permalink
Merge branch 'master' of github.com:slburson/fset
Browse files Browse the repository at this point in the history
  • Loading branch information
slburson committed Jan 14, 2025
2 parents 1e886d1 + 9a4bf6d commit ad07fbd
Show file tree
Hide file tree
Showing 7 changed files with 260 additions and 85 deletions.
10 changes: 6 additions & 4 deletions Code/defs.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
#:define-tuple-key #:def-tuple-key #:get-tuple-key #:tuple-key-name #:tuple-key?
#:tuple-merge
#:fset-setup-readtable #:*fset-readtable*
#:fset-setup-rereading-readtable #:*fset-rereading-readtable*
#:$ #:% ; for the 'map' and 'bag' constructor macros
#:? ; for `query' on 'list-relation'
;; Used by the bag methods that convert to and from lists.
Expand All @@ -101,8 +102,8 @@
#:all-queries #:do-all-queries #:lookup-multi #:forward-key #:lookup-restricted
#:lookup-multi-restricted

;; named-readtable readtable
#:fset-readtable))
;; named-readtable readtables
#:fset-readtable #:fset-rereading-readtable))


;;; The need has arisen to define a second FSet package. There are two motivations:
Expand Down Expand Up @@ -183,6 +184,7 @@
#:define-tuple-key #:def-tuple-key #:get-tuple-key #:tuple-key-name #:tuple-key?
#:tuple-merge
#:fset-setup-readtable #:*fset-readtable*
#:fset-setup-rereading-readtable #:*fset-rereading-readtable*
#:$ #:% ; for the 'map' and 'bag' constructor macros
#:? ; for `query' on 'list-relation'
;; Used by the bag methods that convert to and from lists.
Expand All @@ -205,8 +207,8 @@
#:all-queries #:do-all-queries #:lookup-multi #:forward-key #:lookup-restricted
#:lookup-multi-restricted

;; named-readtable readtable
#:fset-readtable))
;; named-readtable readtables
#:fset-readtable #:fset-rereading-readtable))


;;; A convenient package for experimenting with FSet. Also serves as an example
Expand Down
16 changes: 10 additions & 6 deletions Code/fset.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -2285,9 +2285,11 @@ the default implementation of maps in FSet."
(if (member comp '(:less :greater))
comp
(let ((def-comp (compare (map-default map1) (map-default map2))))
(if (or (eq comp ':unequal) (eq def-comp ':unequal))
':unequal
':equal)))))
(if (member def-comp '(:less :greater))
def-comp
(if (or (eq comp ':unequal) (eq def-comp ':unequal))
':unequal
':equal))))))

(defgeneric internal-do-map (map elt-fn &optional value-fn)
(:documentation
Expand Down Expand Up @@ -2975,9 +2977,11 @@ This is the default implementation of seqs in FSet."
(if (member comp '(:less :greater))
comp
(let ((def-comp (compare (seq-default s1) (seq-default s2))))
(if (or (eq comp ':unequal) (eq def-comp ':unequal))
':unequal
':equal)))))
(if (member def-comp '(:less :greater))
def-comp
(if (or (eq comp ':unequal) (eq def-comp ':unequal))
':unequal
':equal))))))

(defmethod compare-lexicographically ((s1 wb-seq) (s2 wb-seq))
(WB-Seq-Tree-Compare-Lexicographically (wb-seq-contents s1) (wb-seq-contents s2)))
Expand Down
6 changes: 6 additions & 0 deletions Code/macros.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,12 @@ However, the implementation tries very hard to prevent this."
(defun ximage (coll fn)
(image fn coll))

(define-modify-macro updatef (fn &rest keys)
xupdate)

(defun xupdate (coll fn &rest keys)
(apply #'update fn coll keys))

(define-modify-macro composef (fn)
compose)

Expand Down
116 changes: 76 additions & 40 deletions Code/reader.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,13 @@
;;;
;;; The reader macros expand directly into invocations of the constructor macros,
;;; so the syntax is similar. Loading this file does _not_ cause these macros
;;; to be defined in the current readtable; see `fset-setup-readtable' below.
;;; to be defined in the current readtable. To use them, the recommended approach
;;; is to load system Named-Readables (it's in Quicklisp), and then do:
;;;
;;; > (named-readtables:in-readtable fset:fset-readtable)
;;;
;;; If you don't want to do that, you can use `*fset-readtable', or call
;;; `fset-setup-readtable' on an existing readtable.
;;;
;;; Set syntax:
;;;
Expand Down Expand Up @@ -551,6 +557,7 @@ contains the pairs <1, a>, <1, b>, <2, a>, and <2, b>."
;;; ================================================================================
;;; Reader macros

;;; See the discussion at the top of this file before using these.
(defun |#{-reader| (stream subchar arg)
(declare (ignore subchar arg))
(case (peek-char nil stream t nil t)
Expand All @@ -566,6 +573,16 @@ contains the pairs <1, a>, <1, b>, <2, a>, and <2, b>."
(read-delimited-list #\% stream t)
(unless (eql (read-char stream) #\})
(error "Incorrect #{% ... %} syntax")))))
(#\=
(read-char stream t nil t)
(if (eql (peek-char nil stream t nil t) #\|)
(progn
(read-char stream t nil t)
`(replay-map . ,(prog1
(read-delimited-list #\| stream t)
(unless (eql (read-char stream) #\})
(error "Incorrect #{=| ... |} syntax")))))
`(replay-set . ,(read-delimited-list #\} stream t))))
(otherwise
`(set . ,(read-delimited-list #\} stream t)))))

Expand Down Expand Up @@ -593,49 +610,69 @@ contains the pairs <1, a>, <1, b>, <2, a>, and <2, b>."

(defun fset-setup-readtable (readtable)
"Adds FSet reader macros to `readtable'. Returns `readtable'."
(set-dispatch-macro-character #\# #\{ #'|#{-reader| readtable)
(set-dispatch-macro-character #\# #\{ '|#{-reader| readtable)
(set-macro-character #\} (get-macro-character #\)) nil readtable)
(set-dispatch-macro-character #\# #\[ #'|#[-reader| readtable)
(set-dispatch-macro-character #\# #\[ '|#[-reader| readtable)
(set-macro-character #\] (get-macro-character #\)) nil readtable)
(set-dispatch-macro-character #\# #\~ #'|#~-reader| readtable)
(set-dispatch-macro-character #\# #\$ #'|#$-reader| readtable)
(set-dispatch-macro-character #\# #\% #'|#%-reader| readtable)
(set-dispatch-macro-character #\# #\~ '|#~-reader| readtable)
(set-dispatch-macro-character #\# #\$ '|#$-reader| readtable)
(set-dispatch-macro-character #\# #\% '|#%-reader| readtable)
readtable)

(defvar *fset-readtable* (fset-setup-readtable (copy-readtable nil))
"A copy of the standard readtable with FSet reader macros installed.")

;;; Named-Readtables provides a better way to switch readtables.
(named-readtables:defreadtable fset-readtable
(:merge :standard)
(:dispatch-macro-char #\# #\{ '|#{-reader|)
(:macro-char #\} (get-macro-character #\)) nil)
(:dispatch-macro-char #\# #\[ '|#[-reader|)
(:macro-char #\] (get-macro-character #\)) nil)
(:dispatch-macro-char #\# #\~ '|#~-reader|)
(:dispatch-macro-char #\# #\$ '|#$-reader|)
(:dispatch-macro-char #\# #\% '|#%-reader|))


;;; These function in the traditional Lisp manner, constructing the structures
;;; at read time. They can therefore be used to read back previously printed
;;; structure containing FSet collections.
(defun |rereading-#{-reader| (stream subchar arg)
(declare (ignore subchar arg)
(notinline empty-bag))
(case (peek-char nil stream t nil t)
(#\|
(read-char stream t nil t)
(let ((map (convert 'map (read-delimited-list #\| stream t) :value-fn #'cadr)))
(unless (eql (read-char stream) #\})
(error "Incorrect #{| ... |} syntax"))
(if (eql #\/ (peek-char nil stream nil nil t))
(progn
(read-char stream t nil t)
(with-default map (read stream t nil t)))
map)))
(#\%
(read-char stream t nil t)
(let ((stuff (read-delimited-list #\% stream t))
(result (empty-bag)))
(unless (eql (read-char stream) #\})
(error "Incorrect #{% ... %} syntax"))
(dolist (x stuff)
(if (and (consp x) (eq (car x) '%))
(adjoinf result (cadr x) (caddr x))
(adjoinf result x)))
result))
(otherwise
(convert 'set (read-delimited-list #\} stream t)))))
(flet ((read-map (tag)
(read-char stream t nil t)
(let ((pairs (read-delimited-list #\| stream t)))
(unless (eql (read-char stream) #\})
(error "Incorrect #{~A| ... |} syntax" tag))
(if (eql #\/ (peek-char nil stream nil nil t))
(progn
(read-char stream t nil t)
(values pairs (read stream t nil t)))
(values pairs nil)))))
(case (peek-char nil stream t nil t)
(#\|
(let ((pairs default (read-map "")))
(with-default (convert 'map pairs :value-fn #'cadr) default)))
(#\%
(read-char stream t nil t)
(let ((stuff (read-delimited-list #\% stream t))
(result (empty-bag)))
(unless (eql (read-char stream) #\})
(error "Incorrect #{% ... %} syntax"))
(dolist (x stuff)
(if (and (consp x) (eq (car x) '%))
(adjoinf result (cadr x) (caddr x))
(adjoinf result x)))
result))
(#\=
(read-char stream t nil t)
(if (eql (peek-char nil stream t nil t) #\|)
(let ((pairs default (read-map "=")))
(with-default (convert 'replay-map pairs :value-fn #'cadr) default))
(convert 'replay-set (read-delimited-list #\} stream t))))
(otherwise
(convert 'set (read-delimited-list #\} stream t))))))

(defun |rereading-#[-reader| (stream subchar arg)
(declare (ignore subchar arg))
Expand All @@ -662,25 +699,24 @@ contains the pairs <1, a>, <1, b>, <2, a>, and <2, b>."
"Adds the FSet rereading reader macros to `readtable'. These reader macros
will correctly read structure printed by the FSet print functions. Returns
`readtable'."
(set-dispatch-macro-character #\# #\{ #'|rereading-#{-reader| readtable)
(set-dispatch-macro-character #\# #\{ '|rereading-#{-reader| readtable)
(set-macro-character #\} (get-macro-character #\)) nil readtable)
(set-dispatch-macro-character #\# #\[ #'|rereading-#[-reader| readtable)
(set-dispatch-macro-character #\# #\[ '|rereading-#[-reader| readtable)
(set-macro-character #\] (get-macro-character #\)) nil readtable)
(set-dispatch-macro-character #\# #\~ #'|rereading-#~-reader| readtable)
(set-dispatch-macro-character #\# #\% #'|#%-reader| readtable)
(set-dispatch-macro-character #\# #\~ '|rereading-#~-reader| readtable)
(set-dispatch-macro-character #\# #\% '|#%-reader| readtable)
readtable)

(defvar *fset-rereading-readtable* (fset-setup-rereading-readtable (copy-readtable nil))
"A copy of the standard readtable with the rereading FSet reader macros
installed. This readtable can be used to read structure printed by the FSet
print functions.")

(named-readtables:defreadtable fset-readtable
(named-readtables:defreadtable fset-rereading-readtable
(:merge :standard)
(:dispatch-macro-char #\# #\{ #'|#{-reader|)
(:dispatch-macro-char #\# #\{ '|rereading-#{-reader|)
(:macro-char #\} (get-macro-character #\)) nil)
(:dispatch-macro-char #\# #\[ #'|#[-reader|)
(:dispatch-macro-char #\# #\[ '|rereading-#[-reader|)
(:macro-char #\] (get-macro-character #\)) nil)
(:dispatch-macro-char #\# #\~ #'|#~-reader|)
(:dispatch-macro-char #\# #\$ #'|#$-reader|)
(:dispatch-macro-char #\# #\% #'|#%-reader|))
(:dispatch-macro-char #\# #\~ '|rereading-#~-reader|)
(:dispatch-macro-char #\# #\% '|rereading-#%-reader|))
Loading

0 comments on commit ad07fbd

Please sign in to comment.