-
-
Notifications
You must be signed in to change notification settings - Fork 33
/
builder.lisp
72 lines (69 loc) · 2.61 KB
/
builder.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
(defpackage lack/builder
(:nicknames :lack.builder)
(:use :cl)
(:import-from :lack/component
:to-app)
(:import-from :lack/util
:find-middleware)
(:export :builder))
(in-package :lack/builder)
(defun clack-middleware-symbol-p (symbol)
(and (symbolp symbol)
(find-package :clack.middleware)
(find-class symbol nil)
(subtypep (find-class symbol)
(intern (string :<middleware>)
:clack.middleware))))
(defun convert-to-middleware-form (mw)
(let ((app (gensym "APP"))
(res-mw (gensym "RES-MW")))
(etypecase mw
(null)
(function mw)
(keyword `(find-middleware ,mw))
;; for old Clack middlewares
(symbol (if (clack-middleware-symbol-p mw)
`(lambda (,app)
(funcall (intern (string :wrap) :clack.middleware)
(make-instance ',mw)
,app))
mw))
(cons
(typecase (car mw)
(keyword `(lambda (,app)
(funcall (find-middleware ,(car mw)) ,app
,@(cdr mw))))
(symbol
;; for old Clack middlewares
(if (clack-middleware-symbol-p (car mw))
`(lambda (,app)
(funcall (intern (string :wrap) :clack.middleware)
(make-instance ',(car mw) ,@(cdr mw))
,app))
;; Normal form
(let ((res (gensym "RES")))
;; reconvert the result of the form
`(let ((,res ,mw))
(typecase ,res
(keyword (find-middleware ,res))
(cons (if (keywordp (car ,res))
(let ((,res-mw (find-middleware (car ,res))))
(lambda (,app)
(apply ,res-mw ,app (cdr ,res))))
,res))
(standard-object
(lambda (,app)
(funcall (intern (string :wrap) :clack.middleware) ,res ,app)))
(otherwise ,res))))))
(otherwise mw))))))
(defmacro builder (&rest app-or-middlewares)
(let ((middlewares (butlast app-or-middlewares)))
`(reduce #'funcall
(remove-if
#'null
(list
,@(loop for mw in middlewares
when mw
collect (convert-to-middleware-form mw))))
:initial-value (to-app ,(car (last app-or-middlewares)))
:from-end t)))