0.7.7.12:
[sbcl/lichteblau.git] / src / compiler / parse-lambda-list.lisp
bloba8e128301fa1ce07d85a27c55177a523fa551372
1 ;;;; This software is part of the SBCL system. See the README file for
2 ;;;; more information.
3 ;;;;
4 ;;;; This software is derived from the CMU CL system, which was
5 ;;;; written at Carnegie Mellon University and released into the
6 ;;;; public domain. The software is in the public domain and is
7 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
8 ;;;; files for more information.
10 (in-package "SB!C")
12 (/show0 "parse-lambda-list.lisp 12")
14 ;;; Break something like a lambda list (but not necessarily actually a
15 ;;; lambda list, e.g. the representation of argument types which is
16 ;;; used within an FTYPE specification) into its component parts. We
17 ;;; return twelve values:
18 ;;; 1. a list of the required args;
19 ;;; 2. a list of the &OPTIONAL arg specs;
20 ;;; 3. true if a &REST arg was specified;
21 ;;; 4. the &REST arg;
22 ;;; 5. true if &KEY args are present;
23 ;;; 6. a list of the &KEY arg specs;
24 ;;; 7. true if &ALLOW-OTHER-KEYS was specified.;
25 ;;; 8. true if any &AUX is present (new in SBCL vs. CMU CL);
26 ;;; 9. a list of the &AUX specifiers;
27 ;;; 10. true if a &MORE arg was specified;
28 ;;; 11. the &MORE context var;
29 ;;; 12. the &MORE count var.
30 ;;;
31 ;;; The top level lambda list syntax is checked for validity, but the
32 ;;; arg specifiers are just passed through untouched. If something is
33 ;;; wrong, we use COMPILER-ERROR, aborting compilation to the last
34 ;;; recovery point.
35 (declaim (ftype (function (list)
36 (values list list boolean t boolean list boolean
37 boolean list boolean t t))
38 parse-lambda-list-like-thing
39 parse-lambda-list))
40 (defun parse-lambda-list-like-thing (list)
41 (collect ((required)
42 (optional)
43 (keys)
44 (aux))
45 (let ((restp nil)
46 (rest nil)
47 (morep nil)
48 (more-context nil)
49 (more-count nil)
50 (keyp nil)
51 (auxp nil)
52 (allowp nil)
53 (state :required))
54 (declare (type (member :allow-other-keys :aux
55 :key
56 :more-context :more-count
57 :optional
58 :post-more :post-rest
59 :required :rest)
60 state))
61 (dolist (arg list)
62 (if (and (symbolp arg)
63 (let ((name (symbol-name arg)))
64 (and (plusp (length name))
65 (char= (char name 0) #\&))))
66 (case arg
67 (&optional
68 (unless (eq state :required)
69 (compiler-error "misplaced &OPTIONAL in lambda list: ~S"
70 list))
71 (setq state :optional))
72 (&rest
73 (unless (member state '(:required :optional))
74 (compiler-error "misplaced &REST in lambda list: ~S" list))
75 (setq state :rest))
76 (&more
77 (unless (member state '(:required :optional))
78 (compiler-error "misplaced &MORE in lambda list: ~S" list))
79 (setq morep t
80 state :more-context))
81 (&key
82 (unless (member state
83 '(:required :optional :post-rest :post-more))
84 (compiler-error "misplaced &KEY in lambda list: ~S" list))
85 (setq keyp t
86 state :key))
87 (&allow-other-keys
88 (unless (eq state ':key)
89 (compiler-error "misplaced &ALLOW-OTHER-KEYS in ~
90 lambda list: ~S"
91 list))
92 (setq allowp t
93 state :allow-other-keys))
94 (&aux
95 (when (member state '(:rest :more-context :more-count))
96 (compiler-error "misplaced &AUX in lambda list: ~S" list))
97 (setq auxp t
98 state :aux))
99 ;; FIXME: I don't think ANSI says this is an error. (It
100 ;; should certainly be good for a STYLE-WARNING,
101 ;; though.)
103 (compiler-error "unknown &KEYWORD in lambda list: ~S" arg)))
104 (case state
105 (:required (required arg))
106 (:optional (optional arg))
107 (:rest
108 (setq restp t
109 rest arg
110 state :post-rest))
111 (:more-context
112 (setq more-context arg
113 state :more-count))
114 (:more-count
115 (setq more-count arg
116 state :post-more))
117 (:key (keys arg))
118 (:aux (aux arg))
120 (compiler-error "found garbage in lambda list when expecting ~
121 a keyword: ~S"
122 arg)))))
123 (when (eq state :rest)
124 (compiler-error "&REST without rest variable"))
126 (values (required) (optional) restp rest keyp (keys) allowp auxp (aux)
127 morep more-context more-count))))
129 ;;; like PARSE-LAMBDA-LIST-LIKE-THING, except our LAMBDA-LIST argument
130 ;;; really *is* a lambda list, not just a "lambda-list-like thing", so
131 ;;; can barf on things which're illegal as arguments in lambda lists
132 ;;; even if they could conceivably be legal in not-quite-a-lambda-list
133 ;;; weirdosities
134 (defun parse-lambda-list (lambda-list)
136 ;; Classify parameters without checking their validity individually.
137 (multiple-value-bind (required optional restp rest keyp keys allowp auxp aux
138 morep more-context more-count)
139 (parse-lambda-list-like-thing lambda-list)
141 ;; Check validity of parameters.
142 (flet ((need-symbol (x why)
143 (unless (symbolp x)
144 (compiler-error "~A is not a symbol: ~S" why x))))
145 (dolist (i required)
146 (need-symbol i "Required argument"))
147 (dolist (i optional)
148 (typecase i
149 (symbol)
150 (cons
151 (destructuring-bind (var &optional init-form supplied-p) i
152 (declare (ignore init-form supplied-p))
153 (need-symbol var "&OPTIONAL parameter name")))
155 (compiler-error "&OPTIONAL parameter is not a symbol or cons: ~S"
156 i))))
157 (when restp
158 (need-symbol rest "&REST argument"))
159 (when keyp
160 (dolist (i keys)
161 (typecase i
162 (symbol)
163 (cons
164 (destructuring-bind (var-or-kv &optional init-form supplied-p) i
165 (declare (ignore init-form supplied-p))
166 (if (consp var-or-kv)
167 (destructuring-bind (keyword-name var) var-or-kv
168 (declare (ignore keyword-name))
169 (need-symbol var "&KEY parameter name"))
170 (need-symbol var-or-kv "&KEY parameter name"))))
172 (compiler-error "&KEY parameter is not a symbol or cons: ~S"
173 i))))))
175 ;; Voila.
176 (values required optional restp rest keyp keys allowp auxp aux
177 morep more-context more-count)))
179 (/show0 "parse-lambda-list.lisp end of file")