-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathunparse.lisp
116 lines (95 loc) · 4.56 KB
/
unparse.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
(in-package #:first-class-lambda-lists)
(defgeneric fcll:unparse (object))
(defmethod print-object ((parameter parameter) stream)
(print-unreadable-object (parameter stream :type t)
(prin1 (fcll:unparse parameter) stream)))
(defmethod print-object ((section fcll:standard-lambda-list-section) stream)
(print-unreadable-object (section stream :type t)
(format stream "~S~{ ~S~}"
(defsys:name (fcll:lambda-list-keyword section))
(mapcar #'fcll:unparse (parameters section)))))
;;; Parameters
(defun %unparse-recursable-variable (variable-or-lambda-list)
(etypecase variable-or-lambda-list
(symbol variable-or-lambda-list)
(fcll:lambda-list (fcll:unparse variable-or-lambda-list))))
(defmethod fcll:unparse ((parameter simple-parameter))
(variable parameter))
(defmethod fcll:unparse ((parameter required-parameter))
(%unparse-recursable-variable (variable parameter)))
(defmethod fcll:unparse ((parameter specializable-parameter))
(let ((variable (variable parameter))
(specializer (specializer parameter)))
(if (and (eq specializer t) (not (typep variable 'fcll:lambda-list)))
variable
(list (%unparse-recursable-variable variable) specializer))))
(defmethod fcll:unparse ((parameter optional-parameter))
(let* ((variable (variable parameter))
(initform (initform parameter))
(initform-not-default-p (not (%default-initform initform)))
(suppliedp-variable (suppliedp-variable parameter))
(initform-or-suppliedp (or initform-not-default-p suppliedp-variable)))
(if (or initform-or-suppliedp (typep variable 'fcll:lambda-list))
`(,(%unparse-recursable-variable variable)
,@(when initform-or-suppliedp (list initform))
,@(when suppliedp-variable (list suppliedp-variable)))
variable)))
(defmethod fcll:unparse ((parameter optional-no-defaulting-parameter))
(variable parameter))
(defmethod fcll:unparse ((parameter key-parameter))
(let ((variable (variable parameter))
(keyword-name (keyword-name parameter))
(initform (initform parameter))
(suppliedp-variable (suppliedp-variable parameter)))
(let ((custom-keyword-name-p (or (not (keywordp keyword-name))
(string/= (symbol-name keyword-name)
(symbol-name variable))))
(initform-not-default-p (not (%default-initform initform)))
(recursivep :untested))
;; Do the "expensive" TYPEP only once, and only as a last resort.
(if (or custom-keyword-name-p initform-not-default-p suppliedp-variable
(setf recursivep (typep variable 'fcll:lambda-list)))
`(,(if (or custom-keyword-name-p (if (eq recursivep :untested)
(typep variable 'fcll:lambda-list)
recursivep))
(list keyword-name (%unparse-recursable-variable variable))
variable)
,@(when (or initform-not-default-p suppliedp-variable) (list initform))
,@(when suppliedp-variable (list suppliedp-variable)))
variable))))
(defmethod fcll:unparse ((parameter key-no-defaulting-parameter))
(let ((variable (variable parameter))
(keyword-name (keyword-name parameter)))
(let ((custom-keyword-name-p (or (not (keywordp keyword-name))
(string/= (symbol-name keyword-name)
(symbol-name variable)))))
(if custom-keyword-name-p
`((,keyword-name ,variable))
variable))))
(defmethod fcll:unparse ((parameter aux-parameter))
(let ((variable (variable parameter))
(initform (initform parameter)))
(if initform
`(,variable ,initform)
variable)))
;;; Sections
(defmethod fcll:unparse ((section fcll:standard-lambda-list-section))
(let ((introducer (introducer (fcll:lambda-list-keyword section)))
(parameters (mapcar #'fcll:unparse (parameters section))))
(if introducer
(cons introducer parameters)
parameters)))
(defmethod fcll:unparse ((section standard-&key-section))
(if (allow-other-keys-p section)
(append (call-next-method) '(&allow-other-keys))
(call-next-method)))
;;; Lambda lists
(defmethod fcll:unparse ((lambda-list fcll:standard-lambda-list))
(%call-with-root-lambda-list-setup
lambda-list
(lambda ()
(reduce #'append
(%sections lambda-list)
:from-end t
:key #'fcll:unparse
:initial-value nil))))