-
Notifications
You must be signed in to change notification settings - Fork 14
/
misc.lisp
145 lines (105 loc) · 3.86 KB
/
misc.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
;; -*- lisp -*-
;; This file is part of STMX.
;; Copyright (c) 2013-2016 Massimiliano Ghilardi
;;
;; This library is free software: you can redistribute it and/or
;; modify it under the terms of the Lisp Lesser General Public License
;; (http://opensource.franz.com/preamble.html), known as the LLGPL.
;;
;; This library is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty
;; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
;; See the Lisp Lesser General Public License for more details.
(in-package :stmx.util)
(enable-#?-syntax)
(deftype ufixnum () `(integer 0 ,most-positive-fixnum))
;;;; ** Some simple functions optimized for FIXNUMs
(declaim (inline fixnum< fixnum> fixnum= fixnum/=))
(defun fixnum< (x y)
"Optimized version of (< x y) for FIXNUM arguments"
(declare (type fixnum x y))
(the boolean (< x y)))
(defun fixnum> (x y)
"Optimized version of (> x y) for FIXNUM arguments"
(declare (type fixnum x y))
(the boolean (> x y)))
(defun fixnum= (x y)
"Optimized version of (= x y) for FIXNUM arguments"
(declare (type fixnum x y))
(the boolean (= x y)))
(defun fixnum/= (x y)
"Optimized version of (/= x y) for FIXNUM arguments"
(declare (type fixnum x y))
(the boolean (/= x y)))
;;;; ** generic comparison
#+(and)
(eval-always
(defconstant k< -1)
(defconstant k= 0)
(defconstant k> +1))
#-(and)
(eval-always
(defconstant k< :<)
(defconstant k= :=)
(defconstant k> :>))
(deftype comp-result () `(member ,k< ,k= ,k>))
(declaim (inline compare-keys))
(defun compare-keys (pred key1 key2)
"Compare KEY1 agains KEY2 using the comparison function PRED.
Return K< if KEY1 compares as lesser than KEY2,
return K> if KEY1 compares as greater than KEY2,
return K= if KEY1 and KEY2 compare as equal."
(declare (type function pred))
(the comp-result
(cond
((funcall pred key1 key2) k<)
((funcall pred key2 key1) k>)
(t k=))))
#?+sxhash-equalp
(defmacro %sxhash-equalp (x)
(let ((form (get-feature 'sxhash-equalp)))
(etypecase form
(symbol (list form x))
(cons (substitute x '* form)))))
#?-sxhash-equalp
(defmacro %sxhash-equalp (x)
#.(log:warn "missing SXHASH-EQUALP on this implementation,
falling back on SXHASH.
GHASH-TABLE and THASH-TABLE instances using :test 'EQUALP may not work properly.")
`(sxhash ,x))
(declaim (inline sxhash-equalp))
(defun sxhash-equalp (x)
"Variant of SXHASH designed for EQUALP tests, i.e.
\(equalp x y) implies (= (sxhash-equalp x) (sxhash-equalp y)).
A common use is for ghash-tables and thash-tables that use :test 'equalp"
(%sxhash-equalp x))
;;;; ** Utility macros
;; for some reason, under certain circumstances SBCL invokes
;; slot-value-using-class only from slot accessors, not from (slot-value ...)
;; LispWorks is much more picky: slot accessors systematically bypass slot-value-using-class
;; UNLESS the DECLARED class for the object has the flag :optimize-slot-access nil
;; Instead, (slot-value ...) works fine in LispWorks.
(let ((pkg (find-package (symbol-name 'stmx.util))))
(defmacro _ (obj slot)
`(slot-value ,obj ',(if (eq pkg (symbol-package slot))
slot
(intern (symbol-name slot) pkg)))))
#|
(eval-always
(let1 of (symbol-name '-of)
(defmacro _ (obj slot-name)
(let1 accessor (intern (concatenate 'string (symbol-name slot-name) of))
`(,accessor ,obj)))))
|#
(defmacro with-ro-slots ((&rest slots) instance &body body)
(with-gensym obj
`(let ((,obj ,instance))
(let ,(loop for slot in slots
collect `(,slot (_ ,obj ,slot)))
,@body))))
(defmacro with-rw-slots ((&rest slots) instance &body body)
(with-gensym obj
`(let ((,obj ,instance))
(symbol-macrolet ,(loop for slot in slots
collect `(,slot (_ ,obj ,slot)))
,@body))))