0.7.6.20:
[sbcl.git] / src / compiler / parse-lambda-list.lisp
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.
9
10 (in-package "SB!C")
11
12 (/show0 "parse-lambda-list.lisp 12")
13
14 ;;; Break a lambda list into its component parts. We return eleven
15 ;;; values:
16 ;;;  1. a list of the required args;
17 ;;;  2. a list of the &OPTIONAL arg specs;
18 ;;;  3. true if a &REST arg was specified;
19 ;;;  4. the &REST arg;
20 ;;;  5. true if &KEY args are present;
21 ;;;  6. a list of the &KEY arg specs;
22 ;;;  7. true if &ALLOW-OTHER-KEYS was specified.;
23 ;;;  8. a list of the &AUX specifiers;
24 ;;;  9. true if a &MORE arg was specified;
25 ;;; 10. the &MORE context var;
26 ;;; 11. the &MORE count var.
27 ;;;
28 ;;; The top level lambda list syntax is checked for validity, but the
29 ;;; arg specifiers are just passed through untouched. If something is
30 ;;; wrong, we use COMPILER-ERROR, aborting compilation to the last
31 ;;; recovery point.
32 (declaim (ftype (function (list)
33                           (values list list boolean t boolean list boolean
34                                   list boolean t t))
35                 parse-lambda-list))
36 (defun parse-lambda-list (list)
37   (collect ((required)
38             (optional)
39             (keys)
40             (aux))
41     (let ((restp nil)
42           (rest nil)
43           (morep nil)
44           (more-context nil)
45           (more-count nil)
46           (keyp nil)
47           (allowp nil)
48           (state :required))
49       (declare (type (member :allow-other-keys :aux
50                              :key
51                              :more-context :more-count
52                              :optional
53                              :post-more :post-rest
54                              :required :rest)
55                      state))
56       (dolist (arg list)
57         (if (and (symbolp arg)
58                  (let ((name (symbol-name arg)))
59                    (and (plusp (length name))
60                         (char= (char name 0) #\&))))
61             (case arg
62               (&optional
63                (unless (eq state :required)
64                  (compiler-error "misplaced &OPTIONAL in lambda list: ~S"
65                                  list))
66                (setq state :optional))
67               (&rest
68                (unless (member state '(:required :optional))
69                  (compiler-error "misplaced &REST in lambda list: ~S" list))
70                (setq state :rest))
71               (&more
72                (unless (member state '(:required :optional))
73                  (compiler-error "misplaced &MORE in lambda list: ~S" list))
74                (setq morep t
75                      state :more-context))
76               (&key
77                (unless (member state
78                                '(:required :optional :post-rest :post-more))
79                  (compiler-error "misplaced &KEY in lambda list: ~S" list))
80                (setq keyp t
81                      state :key))
82               (&allow-other-keys
83                (unless (eq state ':key)
84                  (compiler-error "misplaced &ALLOW-OTHER-KEYS in ~
85                                   lambda list: ~S"
86                                  list))
87                (setq allowp t
88                      state :allow-other-keys))
89               (&aux
90                (when (member state '(:rest :more-context :more-count))
91                  (compiler-error "misplaced &AUX in lambda list: ~S" list))
92                (setq state :aux))
93               ;; FIXME: I don't think ANSI says this is an error. (It
94               ;; should certainly be good for a STYLE-WARNING,
95               ;; though.)
96               (t
97                (compiler-error "unknown &KEYWORD in lambda list: ~S" arg)))
98             (case state
99               (:required (required arg))
100               (:optional (optional arg))
101               (:rest
102                (setq restp t
103                      rest arg
104                      state :post-rest))
105               (:more-context
106                (setq more-context arg
107                      state :more-count))
108               (:more-count
109                (setq more-count arg
110                      state :post-more))
111               (:key (keys arg))
112               (:aux (aux arg))
113               (t
114                (compiler-error "found garbage in lambda list when expecting ~
115                                 a keyword: ~S"
116                                arg)))))
117       (when (eq state :rest)
118         (compiler-error "&REST without rest variable"))
119       
120       (values (required) (optional) restp rest keyp (keys) allowp (aux)
121               morep more-context more-count))))
122
123 (/show0 "parse-lambda-list.lisp end of file")