Browse code
refactor: move patmatch to its own folder and reforma
Ed Langley authored on 03/11/2019 21:48:21
Showing 7 changed files
Showing 7 changed files
- fwoar-lisputils.asd
- fwoar-lisputils.lisp
- patmatch/package.lisp
- patmatch/patmatch.asd
- patmatch/patmatch.lisp
- patmatch/test-fixtures.lisp
- patmatch/test.lisp
... | ... |
@@ -46,22 +46,14 @@ |
46 | 46 |
:author "Ed L <edward@elangley.org>" |
47 | 47 |
:license "MIT" |
48 | 48 |
:depends-on (#:alexandria |
49 |
+ #:closer-mop |
|
50 |
+ #:parachute |
|
51 |
+ #:serapeum |
|
49 | 52 |
#:uiop) |
50 |
- :serial t |
|
51 | 53 |
:components ((:module "patmatch" |
52 | 54 |
:components ((:file "package") |
53 | 55 |
(:file "patmatch" :depends-on ("package")))))) |
54 | 56 |
|
55 |
-(defsystem :fwoar-lisputils/patmatch/test |
|
56 |
- :description "" |
|
57 |
- :author "Ed L <edward@elangley.org>" |
|
58 |
- :license "MIT" |
|
59 |
- :depends-on (:fwoar-lisputils/patmatch |
|
60 |
- :parachute) |
|
61 |
- :serial t |
|
62 |
- :components ((:module "patmatch" |
|
63 |
- :components ((:file "test"))))) |
|
64 |
- |
|
65 | 57 |
(defsystem #:fwoar-lisputils/string-utils |
66 | 58 |
:description "A string splitter" |
67 | 59 |
:author "fiddlerwoaroof <fiddlerwoaroof@gmail.com" |
... | ... |
@@ -1,17 +1,18 @@ |
1 | 1 |
(in-package #:fwoar.lisputils) |
2 | 2 |
|
3 |
-(defmacro neither (&rest forms) `(not (or ,@forms))) |
|
3 |
+(defmacro neither (&rest forms) |
|
4 |
+ `(not (or ,@forms))) |
|
4 | 5 |
|
5 | 6 |
(defmacro neither-null (&rest forms) |
6 | 7 |
`(neither ,@(loop for form |
7 |
- in forms |
|
8 |
- collecting `(null ,form)))) |
|
8 |
+ in forms |
|
9 |
+ collecting `(null ,form)))) |
|
9 | 10 |
|
10 | 11 |
|
11 | 12 |
(defmacro let-each ((&key (be '*)) &body forms) |
12 | 13 |
"Bind each element successively to the symbol specified via :be" |
13 | 14 |
`(let* ,(loop for form in forms |
14 |
- collect (list be form)) |
|
15 |
+ collect (list be form)) |
|
15 | 16 |
,be)) |
16 | 17 |
|
17 | 18 |
(defmacro let-first ((&key (be '*)) bound &body forms) |
... | ... |
@@ -114,10 +115,10 @@ |
114 | 115 |
|
115 | 116 |
(defmacro m-lambda (sym &rest args) |
116 | 117 |
(let ((arglist (loop for x in args |
117 |
- unless (member x (list '&optional '&key '&rest)) |
|
118 |
- collect (ctypecase x |
|
119 |
- (cons (car x)) |
|
120 |
- ((or symbol keyword string) x))))) |
|
118 |
+ unless (member x (list '&optional '&key '&rest)) |
|
119 |
+ collect (ctypecase x |
|
120 |
+ (cons (car x)) |
|
121 |
+ ((or symbol keyword string) x))))) |
|
121 | 122 |
`(lambda (,@args) |
122 | 123 |
(,sym ,@arglist)))) |
123 | 124 |
|
... | ... |
@@ -133,14 +134,14 @@ |
133 | 134 |
args)) |
134 | 135 |
(args (mapcar #'list args args-syms)) |
135 | 136 |
(destructuring-expressions |
136 |
- (rollup-list |
|
137 |
- (loop for (arg arg-sym) in args |
|
138 |
- collect (if (consp arg) |
|
139 |
- `(destructuring-bind ,arg ,arg-sym |
|
140 |
- (declare (ignore ,@ignored) (ignorable ,@ignorable))) |
|
141 |
- `(let ((,arg ,arg-sym)) |
|
142 |
- ,@(generate-declarations-for arg ignored ignorable)))) |
|
143 |
- body))) |
|
137 |
+ (rollup-list |
|
138 |
+ (loop for (arg arg-sym) in args |
|
139 |
+ collect (if (consp arg) |
|
140 |
+ `(destructuring-bind ,arg ,arg-sym |
|
141 |
+ (declare (ignore ,@ignored) (ignorable ,@ignorable))) |
|
142 |
+ `(let ((,arg ,arg-sym)) |
|
143 |
+ ,@(generate-declarations-for arg ignored ignorable)))) |
|
144 |
+ body))) |
|
144 | 145 |
`(lambda ,args-syms |
145 | 146 |
,destructuring-expressions)))) |
146 | 147 |
|
... | ... |
@@ -176,8 +177,9 @@ |
176 | 177 |
(alexandria:once-only (from to) |
177 | 178 |
`(progn |
178 | 179 |
(setf ,@(apply #'append |
179 |
- (iterate:iterate (iterate:for (fro-slot to-slot) iterate:in (ensure-mapping slots)) |
|
180 |
- (iterate:collect `((slot-value ,to ',to-slot) (slot-value ,from ',fro-slot)))))) |
|
180 |
+ (iterate:iterate |
|
181 |
+ (iterate:for (fro-slot to-slot) iterate:in (ensure-mapping slots)) |
|
182 |
+ (iterate:collect `((slot-value ,to ',to-slot) (slot-value ,from ',fro-slot)))))) |
|
181 | 183 |
,to))) |
182 | 184 |
|
183 | 185 |
(defun transform-alist (function alist) |
... | ... |
@@ -207,7 +209,7 @@ |
207 | 209 |
(typecase (cdr form) |
208 | 210 |
(symbol (list (cdr form))) |
209 | 211 |
(cons (loop for thing in (cdr form) |
210 |
- append (find-nonoperator-symbols thing)))))))))) |
|
212 |
+ append (find-nonoperator-symbols thing)))))))))) |
|
211 | 213 |
|
212 | 214 |
(defmacro may ((op arg)) |
213 | 215 |
(alexandria:once-only (arg) |
... | ... |
@@ -237,16 +239,18 @@ |
237 | 239 |
(defun make-pairs (symbols) |
238 | 240 |
;TODO: does this duplicate ensure-mapping? |
239 | 241 |
(cons 'list |
240 |
- (iterate:iterate (iterate:for (key value) in symbols) |
|
241 |
- (iterate:collect `(list* ,(symbol-name key) ,value))))) |
|
242 |
+ (iterate:iterate |
|
243 |
+ (iterate:for (key value) in symbols) |
|
244 |
+ (iterate:collect `(list* ,(symbol-name key) ,value))))) |
|
242 | 245 |
|
243 | 246 |
(defmacro slots-to-pairs (obj (&rest slots)) |
244 | 247 |
(declare (optimize (debug 3))) |
245 | 248 |
"Produce a alist from a set of object slots and their values" |
246 | 249 |
(alexandria:once-only (obj) |
247 | 250 |
(let* ((slots (ensure-mapping slots)) |
248 |
- (bindings (iterate:iterate (iterate:for (slot v &key bind-from) in slots) |
|
249 |
- (iterate:collect (or bind-from slot))))) |
|
251 |
+ (bindings (iterate:iterate |
|
252 |
+ (iterate:for (slot v &key bind-from) in slots) |
|
253 |
+ (iterate:collect (or bind-from slot))))) |
|
250 | 254 |
`(with-slots ,bindings ,obj |
251 | 255 |
,(make-pairs slots))))) |
252 | 256 |
|
9 | 10 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,11 @@ |
1 |
+(in-package :asdf-user) |
|
2 |
+ |
|
3 |
+(defsystem :fwoar-lisputils/patmatch/test |
|
4 |
+ :description "" |
|
5 |
+ :author "Ed L <edward@elangley.org>" |
|
6 |
+ :license "MIT" |
|
7 |
+ :depends-on (#:fwoar-lisputils/patmatch |
|
8 |
+ #:parachute |
|
9 |
+ #:serapeum) |
|
10 |
+ :components ((:file "test-fixtures") |
|
11 |
+ (:file "test" :depends-on ("test-fixtures")))) |
46 | 45 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,36 @@ |
1 |
+(defpackage :patmatch/test |
|
2 |
+ (:use :cl) |
|
3 |
+ (:import-from :parachute |
|
4 |
+ #:true #:false #:fail #:is #:isnt #:is-values #:isnt-values |
|
5 |
+ #:of-type #:finish #:define-test) |
|
6 |
+ (:import-from :patmatch :let-pat*) |
|
7 |
+ (:export )) |
|
8 |
+(in-package :patmatch/test) |
|
9 |
+ |
|
10 |
+(defclass test-base () |
|
11 |
+ ((a :initform 1))) |
|
12 |
+ |
|
13 |
+(defclass test-sub1 (test-base) |
|
14 |
+ ()) |
|
15 |
+ |
|
16 |
+(defclass test-sub2 (test-base) |
|
17 |
+ ((b :initform 2))) |
|
18 |
+ |
|
19 |
+(eval-when (:compile-toplevel :load-toplevel :execute) |
|
20 |
+ (closer-mop:ensure-class 'test-base) |
|
21 |
+ (closer-mop:ensure-class 'test-sub1) |
|
22 |
+ (closer-mop:ensure-class 'test-sub2)) |
|
23 |
+ |
|
24 |
+(defmethod patmatch:handle-pattern append ((pattern test-base) form &rest args) |
|
25 |
+ (alexandria:when-let ((arg (getf args :a))) |
|
26 |
+ (let ((val-sym (gensym "test-base-"))) |
|
27 |
+ `((,val-sym ,form) |
|
28 |
+ ,@(serapeum:unsplice |
|
29 |
+ `(,arg (slot-value ,val-sym 'a))))))) |
|
30 |
+ |
|
31 |
+(defmethod patmatch:handle-pattern append ((pattern test-sub2) form &rest args) |
|
32 |
+ (alexandria:when-let ((arg (getf args :b))) |
|
33 |
+ (let ((val-sym (gensym "test-base-"))) |
|
34 |
+ `((,val-sym ,form) |
|
35 |
+ ,@(serapeum:unsplice |
|
36 |
+ `(,arg (slot-value ,val-sym 'b))))))) |
... | ... |
@@ -1,118 +1,52 @@ |
1 |
-(defpackage :patmatch/test |
|
2 |
- (:use :cl) |
|
3 |
- (:import-from :parachute |
|
4 |
- #:true #:false #:fail #:is #:isnt #:is-values #:isnt-values |
|
5 |
- #:of-type #:finish #:define-test) |
|
6 |
- (:import-from :patmatch :let-pat*) |
|
7 |
- (:export )) |
|
8 | 1 |
(in-package :patmatch/test) |
9 | 2 |
|
10 |
-(define-test add-stuff |
|
11 |
- (is = |
|
12 |
- (progn (sleep 2) |
|
13 |
- 2) |
|
14 |
- 2)) |
|
3 |
+(define-test let-pat*) |
|
15 | 4 |
|
16 | 5 |
(define-test let-pat*-handles-cons |
17 |
- (is = |
|
18 |
- 2 |
|
19 |
- (let-pat* (((cons a b) '(2 . 3))) |
|
20 |
- (declare (ignore b)) |
|
21 |
- a))) |
|
22 |
- |
|
23 |
-#| |
|
24 |
-(deftest let-pat*-handles-cons () |
|
25 |
-"" |
|
26 |
-(should be eql |
|
27 |
-2 |
|
28 |
-(let-pat* (((cons a b) '(2 . 3))) |
|
29 |
-(declare (ignore b)) |
|
30 |
-a)) |
|
31 |
-(should be eql |
|
32 |
-3 |
|
33 |
-(let-pat* (((cons a b) '(2 . 3))) |
|
34 |
-(declare (ignore a)) |
|
35 |
-b))) |
|
36 |
- |
|
37 |
-(deftest let-pat*-handles-vector () |
|
38 |
- "" |
|
39 |
- (should be eql |
|
40 |
- 2 |
|
41 |
- (let-pat* (((vector a b) #(2 3))) |
|
6 |
+ :parent let-pat* |
|
7 |
+ (is = 2 (let-pat* (((cons a b) '(2 . 3))) |
|
42 | 8 |
(declare (ignore b)) |
43 | 9 |
a)) |
44 |
- (should be eql |
|
45 |
- 3 |
|
46 |
- (let-pat* (((vector a b) #(2 3))) |
|
10 |
+ |
|
11 |
+ (is = 3 (let-pat* (((cons a b) '(2 . 3))) |
|
47 | 12 |
(declare (ignore a)) |
48 | 13 |
b))) |
49 | 14 |
|
50 |
-(deftest let-pat*-handles-hash-table () |
|
51 |
- "" |
|
52 |
- (should be eql |
|
53 |
- 2 |
|
54 |
- (let-pat* (((hash-table (:a a) (:b b)) (alexandria:plist-hash-table '(:a 2 :b 3)))) |
|
15 |
+(define-test let-pat*-handles-vector |
|
16 |
+ :parent let-pat* |
|
17 |
+ (is = 2 (let-pat* (((vector a b) #(2 3))) |
|
55 | 18 |
(declare (ignore b)) |
56 | 19 |
a)) |
57 |
- (should be eql |
|
58 |
- 3 |
|
59 |
- (let-pat* (((hash-table (:a a) (:b b)) (alexandria:plist-hash-table '(:a 2 :b 3)))) |
|
20 |
+ (is = 3 (let-pat* (((vector a b) #(2 3))) |
|
60 | 21 |
(declare (ignore a)) |
61 | 22 |
b))) |
62 | 23 |
|
63 |
-(eval-when (:compile-toplevel :load-toplevel :execute) |
|
64 |
- (defclass test-base () |
|
65 |
- ((a :initform 1))) |
|
66 |
- (defclass test-sub1 (test-base) |
|
67 |
- ()) |
|
68 |
- (defclass test-sub2 (test-base) |
|
69 |
- ((b :initform 2))) |
|
70 |
- (closer-mop:ensure-class 'test-base) |
|
71 |
- (closer-mop:ensure-class 'test-sub1) |
|
72 |
- (closer-mop:ensure-class 'test-sub2) |
|
73 |
- ) |
|
74 |
- |
|
75 |
-(defmethod patmatch:handle-pattern append ((pattern test-base) form &rest args) |
|
76 |
- (alexandria:when-let ((arg (getf args :a))) |
|
77 |
- (let ((val-sym (gensym "test-base-"))) |
|
78 |
- `((,val-sym ,form) |
|
79 |
- ,@(serapeum:unsplice |
|
80 |
- `(,arg (slot-value ,val-sym 'a))))))) |
|
24 |
+(define-test let-pat*-handles-hash-table |
|
25 |
+ :parent let-pat* |
|
26 |
+ (is = 2 (let-pat* (((hash-table (:a a) (:b b)) (alexandria:plist-hash-table '(:a 2 :b 3)))) |
|
27 |
+ (declare (ignore b)) |
|
28 |
+ a)) |
|
81 | 29 |
|
82 |
-(defmethod patmatch:handle-pattern append ((pattern test-sub2) form &rest args) |
|
83 |
- (alexandria:when-let ((arg (getf args :b))) |
|
84 |
- (let ((val-sym (gensym "test-base-"))) |
|
85 |
- `((,val-sym ,form) |
|
86 |
- ,@(serapeum:unsplice |
|
87 |
- `(,arg (slot-value ,val-sym 'b))))))) |
|
30 |
+ (is = 3 (let-pat* (((hash-table (:a a) (:b b)) (alexandria:plist-hash-table '(:a 2 :b 3)))) |
|
31 |
+ (declare (ignore a)) |
|
32 |
+ b))) |
|
88 | 33 |
|
89 | 34 |
|
90 |
-(deftest let-pat*-handles-object-destructuring () |
|
91 |
- "" |
|
92 |
- (should be eql |
|
93 |
- 1 |
|
94 |
- (let-pat* (((test-base :a a) (make-instance 'test-base))) |
|
35 |
+(define-test let-pat*-handles-object-destructuring |
|
36 |
+ :parent let-pat* |
|
37 |
+ (is = 1 (let-pat* (((test-base :a a) (make-instance 'test-base))) |
|
95 | 38 |
a))) |
96 | 39 |
|
97 |
-(deftest let-pat*-handles-inheritance () |
|
98 |
-"" |
|
99 |
-(should be eql |
|
100 |
-1 |
|
101 |
-(let-pat* (((test-base :a a) (make-instance 'test-sub1))) |
|
102 |
-a)) |
|
40 |
+(define-test let-pat*-handles-inheritance |
|
41 |
+ :parent let-pat* |
|
42 |
+ (is = 1 (let-pat* (((test-base :a a) (make-instance 'test-sub1))) |
|
43 |
+ a)) |
|
103 | 44 |
|
104 |
-(should be eql |
|
105 |
-1 |
|
106 |
-(let-pat* (((test-sub1 :a a) (make-instance 'test-sub1))) |
|
107 |
-a)) |
|
45 |
+ (is = 1 (let-pat* (((test-sub1 :a a) (make-instance 'test-sub1))) |
|
46 |
+ a)) |
|
108 | 47 |
|
109 |
-(should be eql |
|
110 |
-1 |
|
111 |
-(let-pat* (((test-sub2 :a a) (make-instance 'test-sub2))) |
|
112 |
-a)) |
|
48 |
+ (is = 1 (let-pat* (((test-sub2 :a a) (make-instance 'test-sub2))) |
|
49 |
+ a)) |
|
113 | 50 |
|
114 |
-(should be equal |
|
115 |
-'(1 2) |
|
116 |
-(let-pat* (((test-sub2 :a a :b b) (make-instance 'test-sub2))) |
|
117 |
-(list a b)))) |
|
118 |
-|# |
|
51 |
+ (is equal '(1 2) (let-pat* (((test-sub2 :a a :b b) (make-instance 'test-sub2))) |
|
52 |
+ (list a b)))) |