-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlambda-list-cores.lisp
133 lines (111 loc) · 5.64 KB
/
lambda-list-cores.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
(in-package #:first-class-lambda-lists)
(defclass lambda-list-core () ())
(defclass raw-lambda-list-core (lambda-list-core)
())
(defgeneric raw-lambda-list-core (object))
(defmethod raw-lambda-list-core ((core raw-lambda-list-core))
core)
(defclass lambda-list-core-slots-mixin ()
((%keywords-set :reader keywords-set
:type fcll:lambda-list-keywords-set)
(%keyword-order :reader keyword-order
:type fcll:lambda-list-keyword-order)
(%keyword-conflicts :reader keyword-conflicts
:type fcll:lambda-list-keyword-conflicts)))
(defmethod print-object ((core lambda-list-core-slots-mixin) stream)
(print-unreadable-object (core stream :type t)
(prin1 (lambda-list-keywords (keywords-set core)) stream)))
(defclass lambda-list-core-mixin ()
((%core :initarg :core
:reader core
:type lambda-list-core
:initform (error ":core argument is required."))))
(defclass standard-raw-lambda-list-core (raw-lambda-list-core
lambda-list-core-slots-mixin)
((%keywords-set :initarg :keywords-set)
(%keyword-order :initarg :keyword-order)
(%keyword-conflicts :initarg :keyword-conflicts)))
(defclass derived-raw-lambda-list-core (raw-lambda-list-core
lambda-list-core-slots-mixin)
((%from :initarg :from
:reader from
:type raw-lambda-list-core)
(%keyword-order :initarg :keyword-order)
(%keyword-conflicts :initarg :keyword-conflicts)))
(defmethod shared-initialize :around ((instance derived-raw-lambda-list-core) slot-names &rest initargs &key (from :ordinary from-p) add remove replace)
(declare (ignore add remove replace))
(if (or from-p (eq slot-names t) (member '%from slot-names))
(apply #'call-next-method instance slot-names :from (raw-lambda-list-core from) initargs)
(call-next-method)))
(defmethod shared-initialize :after ((instance derived-raw-lambda-list-core) slot-names &rest initargs)
(let ((from (from instance)))
(setf (slot-value instance '%keywords-set)
(apply #'make-instance 'derived-lambda-list-keywords-set
:keywords-set (keywords-set from)
(%mappcon (lambda (key value)
(when (member key '(:add :remove :replace))
(list key value)))
initargs)))
(unless (slot-boundp instance '%keyword-order)
(setf (slot-value instance '%keyword-order)
(keyword-order from)))
(unless (slot-boundp instance '%keyword-conflicts)
(setf (slot-value instance '%keyword-conflicts)
(keyword-conflicts from)))))
(defclass coherent-lambda-list-core (lambda-list-core)
())
(defgeneric coherent-lambda-list-core (lambda-list-core))
(defmethod coherent-lambda-list-core ((core raw-lambda-list-core))
(make-instance 'standard-coherent-lambda-list-core
:core core))
(defmethod coherent-lambda-list-core ((core coherent-lambda-list-core))
core)
(defclass standard-coherent-lambda-list-core (coherent-lambda-list-core
lambda-list-core-slots-mixin
lambda-list-core-mixin)
())
(defmethod shared-initialize :after ((instance standard-coherent-lambda-list-core) slot-names
&key (core nil core-supplied-p))
(declare (ignore slot-names))
(when core-supplied-p
(check-type core lambda-list-core)
(let ((keywords-set (keywords-set core)))
(setf (slot-value instance '%keywords-set)
keywords-set
(slot-value instance '%keyword-order)
(make-instance 'scoped-lambda-list-keyword-order
:keyword-order (keyword-order core)
:keywords-set keywords-set)
(slot-value instance '%keyword-conflicts)
(make-instance 'scoped-lambda-list-keyword-conflicts
:keyword-conflicts (keyword-conflicts core)
:keywords-set keywords-set)))))
(defclass mapped-lambda-list-core (coherent-lambda-list-core
lambda-list-core-slots-mixin
lambda-list-core-mixin
mapper-mixin)
((%core :type coherent-lambda-list-core)))
(defmethod shared-initialize :after ((instance mapped-lambda-list-core) slot-names
&key (core nil core-supplied-p))
(declare (ignore slot-names))
(when core-supplied-p
(check-type core coherent-lambda-list-core)
(let* ((keywords-set (keywords-set core))
(mapped-lambda-list-keywords-set
(make-instance 'mapped-lambda-list-keywords-set
:keywords-set keywords-set
:mapper (mapper instance)))
(mapper (let ((mappings (mappings mapped-lambda-list-keywords-set)))
(lambda (lambda-list-keyword)
(or (cdr (assoc lambda-list-keyword mappings :test #'eq))
(error "Mapping error."))))))
(setf (slot-value instance '%keywords-set)
mapped-lambda-list-keywords-set
(slot-value instance '%keyword-order)
(make-instance 'mapped-lambda-list-keyword-order
:keyword-order (keyword-order core)
:mapper mapper)
(slot-value instance '%keyword-conflicts)
(make-instance 'mapped-lambda-list-keyword-conflicts
:keyword-conflicts (keyword-conflicts core)
:mapper mapper)))))