Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1620 lines
67 KiB

5 years ago
  1. ;;; swank-arglists.lisp --- arglist related code ??
  2. ;;
  3. ;; Authors: Matthias Koeppe <mkoeppe@mail.math.uni-magdeburg.de>
  4. ;; Tobias C. Rittweiler <tcr@freebits.de>
  5. ;; and others
  6. ;;
  7. ;; License: Public Domain
  8. ;;
  9. (in-package :swank)
  10. (eval-when (:compile-toplevel :load-toplevel :execute)
  11. (swank-require :swank-c-p-c))
  12. ;;;; Utilities
  13. (defun compose (&rest functions)
  14. "Compose FUNCTIONS right-associatively, returning a function"
  15. #'(lambda (x)
  16. (reduce #'funcall functions :initial-value x :from-end t)))
  17. (defun length= (seq n)
  18. "Test for whether SEQ contains N number of elements. I.e. it's equivalent
  19. to (= (LENGTH SEQ) N), but besides being more concise, it may also be more
  20. efficiently implemented."
  21. (etypecase seq
  22. (list (do ((i n (1- i))
  23. (list seq (cdr list)))
  24. ((or (<= i 0) (null list))
  25. (and (zerop i) (null list)))))
  26. (sequence (= (length seq) n))))
  27. (declaim (inline memq))
  28. (defun memq (item list)
  29. (member item list :test #'eq))
  30. (defun exactly-one-p (&rest values)
  31. "If exactly one value in VALUES is non-NIL, this value is returned.
  32. Otherwise NIL is returned."
  33. (let ((found nil))
  34. (dolist (v values)
  35. (when v (if found
  36. (return-from exactly-one-p nil)
  37. (setq found v))))
  38. found))
  39. (defun valid-operator-symbol-p (symbol)
  40. "Is SYMBOL the name of a function, a macro, or a special-operator?"
  41. (or (fboundp symbol)
  42. (macro-function symbol)
  43. (special-operator-p symbol)
  44. (member symbol '(declare declaim))))
  45. (defun function-exists-p (form)
  46. (and (valid-function-name-p form)
  47. (fboundp form)
  48. t))
  49. (defmacro multiple-value-or (&rest forms)
  50. (if (null forms)
  51. nil
  52. (let ((first (first forms))
  53. (rest (rest forms)))
  54. `(let* ((values (multiple-value-list ,first))
  55. (primary-value (first values)))
  56. (if primary-value
  57. (values-list values)
  58. (multiple-value-or ,@rest))))))
  59. (defun arglist-available-p (arglist)
  60. (not (eql arglist :not-available)))
  61. (defmacro with-available-arglist ((var &rest more-vars) form &body body)
  62. `(multiple-value-bind (,var ,@more-vars) ,form
  63. (if (eql ,var :not-available)
  64. :not-available
  65. (progn ,@body))))
  66. ;;;; Arglist Definition
  67. (defstruct (arglist (:conc-name arglist.) (:predicate arglist-p))
  68. provided-args ; list of the provided actual arguments
  69. required-args ; list of the required arguments
  70. optional-args ; list of the optional arguments
  71. key-p ; whether &key appeared
  72. keyword-args ; list of the keywords
  73. rest ; name of the &rest or &body argument (if any)
  74. body-p ; whether the rest argument is a &body
  75. allow-other-keys-p ; whether &allow-other-keys appeared
  76. aux-args ; list of &aux variables
  77. any-p ; whether &any appeared
  78. any-args ; list of &any arguments [*]
  79. known-junk ; &whole, &environment
  80. unknown-junk) ; unparsed stuff
  81. ;;;
  82. ;;; [*] The &ANY lambda keyword is an extension to ANSI Common Lisp,
  83. ;;; and is only used to describe certain arglists that cannot be
  84. ;;; described in another way.
  85. ;;;
  86. ;;; &ANY is very similiar to &KEY but while &KEY is based upon
  87. ;;; the idea of a plist (key1 value1 key2 value2), &ANY is a
  88. ;;; cross between &OPTIONAL, &KEY and *FEATURES* lists:
  89. ;;;
  90. ;;; a) (&ANY :A :B :C) means that you can provide any (non-null)
  91. ;;; set consisting of the keywords `:A', `:B', or `:C' in
  92. ;;; the arglist. E.g. (:A) or (:C :B :A).
  93. ;;;
  94. ;;; (This is not restricted to keywords only, but any self-evaluating
  95. ;;; expression is allowed.)
  96. ;;;
  97. ;;; b) (&ANY (key1 v1) (key2 v2) (key3 v3)) means that you can
  98. ;;; provide any (non-null) set consisting of lists where
  99. ;;; the CAR of the list is one of `key1', `key2', or `key3'.
  100. ;;; E.g. ((key1 100) (key3 42)), or ((key3 66) (key2 23))
  101. ;;;
  102. ;;;
  103. ;;; For example, a) let us describe the situations of EVAL-WHEN as
  104. ;;;
  105. ;;; (EVAL-WHEN (&ANY :compile-toplevel :load-toplevel :execute) &BODY body)
  106. ;;;
  107. ;;; and b) let us describe the optimization qualifiers that are valid
  108. ;;; in the declaration specifier `OPTIMIZE':
  109. ;;;
  110. ;;; (DECLARE (OPTIMIZE &ANY (compilation-speed 1) (safety 1) ...))
  111. ;;;
  112. ;; This is a wrapper object around anything that came from Slime and
  113. ;; could not reliably be read.
  114. (defstruct (arglist-dummy
  115. (:conc-name #:arglist-dummy.)
  116. (:constructor make-arglist-dummy (string-representation)))
  117. string-representation)
  118. (defun empty-arg-p (dummy)
  119. (and (arglist-dummy-p dummy)
  120. (zerop (length (arglist-dummy.string-representation dummy)))))
  121. (eval-when (:compile-toplevel :load-toplevel :execute)
  122. (defparameter +lambda-list-keywords+
  123. '(&provided &required &optional &rest &key &any)))
  124. (defmacro do-decoded-arglist (decoded-arglist &body clauses)
  125. (assert (loop for clause in clauses
  126. thereis (member (car clause) +lambda-list-keywords+)))
  127. (flet ((parse-clauses (clauses)
  128. (let* ((size (length +lambda-list-keywords+))
  129. (initial (make-hash-table :test #'eq :size size))
  130. (main (make-hash-table :test #'eq :size size))
  131. (final (make-hash-table :test #'eq :size size)))
  132. (loop for clause in clauses
  133. for lambda-list-keyword = (first clause)
  134. for clause-parameter = (second clause)
  135. do
  136. (case clause-parameter
  137. (:initially
  138. (setf (gethash lambda-list-keyword initial) clause))
  139. (:finally
  140. (setf (gethash lambda-list-keyword final) clause))
  141. (t
  142. (setf (gethash lambda-list-keyword main) clause)))
  143. finally
  144. (return (values initial main final)))))
  145. (generate-main-clause (clause arglist)
  146. (dcase clause
  147. ((&provided (&optional arg) . body)
  148. (let ((gensym (gensym "PROVIDED-ARG+")))
  149. `(dolist (,gensym (arglist.provided-args ,arglist))
  150. (declare (ignorable ,gensym))
  151. (let (,@(when arg `((,arg ,gensym))))
  152. ,@body))))
  153. ((&required (&optional arg) . body)
  154. (let ((gensym (gensym "REQUIRED-ARG+")))
  155. `(dolist (,gensym (arglist.required-args ,arglist))
  156. (declare (ignorable ,gensym))
  157. (let (,@(when arg `((,arg ,gensym))))
  158. ,@body))))
  159. ((&optional (&optional arg init) . body)
  160. (let ((optarg (gensym "OPTIONAL-ARG+")))
  161. `(dolist (,optarg (arglist.optional-args ,arglist))
  162. (declare (ignorable ,optarg))
  163. (let (,@(when arg
  164. `((,arg (optional-arg.arg-name ,optarg))))
  165. ,@(when init
  166. `((,init (optional-arg.default-arg ,optarg)))))
  167. ,@body))))
  168. ((&key (&optional keyword arg init) . body)
  169. (let ((keyarg (gensym "KEY-ARG+")))
  170. `(dolist (,keyarg (arglist.keyword-args ,arglist))
  171. (declare (ignorable ,keyarg))
  172. (let (,@(when keyword
  173. `((,keyword (keyword-arg.keyword ,keyarg))))
  174. ,@(when arg
  175. `((,arg (keyword-arg.arg-name ,keyarg))))
  176. ,@(when init
  177. `((,init (keyword-arg.default-arg ,keyarg)))))
  178. ,@body))))
  179. ((&rest (&optional arg body-p) . body)
  180. `(when (arglist.rest ,arglist)
  181. (let (,@(when arg `((,arg (arglist.rest ,arglist))))
  182. ,@(when body-p `((,body-p (arglist.body-p ,arglist)))))
  183. ,@body)))
  184. ((&any (&optional arg) . body)
  185. (let ((gensym (gensym "REQUIRED-ARG+")))
  186. `(dolist (,gensym (arglist.any-args ,arglist))
  187. (declare (ignorable ,gensym))
  188. (let (,@(when arg `((,arg ,gensym))))
  189. ,@body)))))))
  190. (let ((arglist (gensym "DECODED-ARGLIST+")))
  191. (multiple-value-bind (initially-clauses main-clauses finally-clauses)
  192. (parse-clauses clauses)
  193. `(let ((,arglist ,decoded-arglist))
  194. (block do-decoded-arglist
  195. ,@(loop for keyword in '(&provided &required
  196. &optional &rest &key &any)
  197. append (cddr (gethash keyword initially-clauses))
  198. collect (let ((clause (gethash keyword main-clauses)))
  199. (when clause
  200. (generate-main-clause clause arglist)))
  201. append (cddr (gethash keyword finally-clauses)))))))))
  202. ;;;; Arglist Printing
  203. (defun undummy (x)
  204. (if (typep x 'arglist-dummy)
  205. (arglist-dummy.string-representation x)
  206. (prin1-to-string x)))
  207. (defun print-decoded-arglist (arglist &key operator provided-args highlight)
  208. (let ((first-space-after-operator (and operator t)))
  209. (macrolet ((space ()
  210. ;; Kludge: When OPERATOR is not given, we don't want to
  211. ;; print a space for the first argument.
  212. `(if (not operator)
  213. (setq operator t)
  214. (progn (write-char #\space)
  215. (if first-space-after-operator
  216. (setq first-space-after-operator nil)
  217. (pprint-newline :fill)))))
  218. (with-highlighting ((&key index) &body body)
  219. `(if (eql ,index (car highlight))
  220. (progn (princ "===> ") ,@body (princ " <==="))
  221. (progn ,@body)))
  222. (print-arglist-recursively (argl &key index)
  223. `(if (eql ,index (car highlight))
  224. (print-decoded-arglist ,argl :highlight (cdr highlight))
  225. (print-decoded-arglist ,argl))))
  226. (let ((index 0))
  227. (pprint-logical-block (nil nil :prefix "(" :suffix ")")
  228. (when operator
  229. (print-arg operator)
  230. (pprint-indent :current 1)) ; 1 due to possibly added space
  231. (do-decoded-arglist (remove-given-args arglist provided-args)
  232. (&provided (arg)
  233. (space)
  234. (print-arg arg :literal-strings t)
  235. (incf index))
  236. (&required (arg)
  237. (space)
  238. (if (arglist-p arg)
  239. (print-arglist-recursively arg :index index)
  240. (with-highlighting (:index index)
  241. (print-arg arg)))
  242. (incf index))
  243. (&optional :initially
  244. (when (arglist.optional-args arglist)
  245. (space)
  246. (princ '&optional)))
  247. (&optional (arg init-value)
  248. (space)
  249. (if (arglist-p arg)
  250. (print-arglist-recursively arg :index index)
  251. (with-highlighting (:index index)
  252. (if (null init-value)
  253. (print-arg arg)
  254. (format t "~:@<~A ~A~@:>"
  255. (undummy arg) (undummy init-value)))))
  256. (incf index))
  257. (&key :initially
  258. (when (arglist.key-p arglist)
  259. (space)
  260. (princ '&key)))
  261. (&key (keyword arg init)
  262. (space)
  263. (if (arglist-p arg)
  264. (pprint-logical-block (nil nil :prefix "(" :suffix ")")
  265. (prin1 keyword) (space)
  266. (print-arglist-recursively arg :index keyword))
  267. (with-highlighting (:index keyword)
  268. (cond ((and init (keywordp keyword))
  269. (format t "~:@<~A ~A~@:>" keyword (undummy init)))
  270. (init
  271. (format t "~:@<(~A ..) ~A~@:>"
  272. (undummy keyword) (undummy init)))
  273. ((not (keywordp keyword))
  274. (format t "~:@<(~S ..)~@:>" keyword))
  275. (t
  276. (princ keyword))))))
  277. (&key :finally
  278. (when (arglist.allow-other-keys-p arglist)
  279. (space)
  280. (princ '&allow-other-keys)))
  281. (&any :initially
  282. (when (arglist.any-p arglist)
  283. (space)
  284. (princ '&any)))
  285. (&any (arg)
  286. (space)
  287. (print-arg arg))
  288. (&rest (args bodyp)
  289. (space)
  290. (princ (if bodyp '&body '&rest))
  291. (space)
  292. (if (arglist-p args)
  293. (print-arglist-recursively args :index index)
  294. (with-highlighting (:index index)
  295. (print-arg args))))
  296. ;; FIXME: add &UNKNOWN-JUNK?
  297. ))))))
  298. (defun print-arg (arg &key literal-strings)
  299. (let ((arg (if (arglist-dummy-p arg)
  300. (arglist-dummy.string-representation arg)
  301. arg)))
  302. (if (or
  303. (and literal-strings
  304. (stringp arg))
  305. (keywordp arg))
  306. (prin1 arg)
  307. (princ arg))))
  308. (defun print-decoded-arglist-as-template (decoded-arglist &key
  309. (prefix "(") (suffix ")"))
  310. (let ((first-p t))
  311. (flet ((space ()
  312. (unless first-p
  313. (write-char #\space))
  314. (setq first-p nil))
  315. (print-arg-or-pattern (arg)
  316. (etypecase arg
  317. (symbol (if (keywordp arg) (prin1 arg) (princ arg)))
  318. (string (princ arg))
  319. (list (princ arg))
  320. (arglist-dummy (princ
  321. (arglist-dummy.string-representation arg)))
  322. (arglist (print-decoded-arglist-as-template arg)))
  323. (pprint-newline :fill)))
  324. (pprint-logical-block (nil nil :prefix prefix :suffix suffix)
  325. (do-decoded-arglist decoded-arglist
  326. (&provided ()) ; do nothing; provided args are in the buffer already.
  327. (&required (arg)
  328. (space) (print-arg-or-pattern arg))
  329. (&optional (arg)
  330. (space) (princ "[") (print-arg-or-pattern arg) (princ "]"))
  331. (&key (keyword arg)
  332. (space)
  333. (prin1 (if (keywordp keyword) keyword `',keyword))
  334. (space)
  335. (print-arg-or-pattern arg)
  336. (pprint-newline :linear))
  337. (&any (arg)
  338. (space) (print-arg-or-pattern arg))
  339. (&rest (args)
  340. (when (or (not (arglist.keyword-args decoded-arglist))
  341. (arglist.allow-other-keys-p decoded-arglist))
  342. (space)
  343. (format t "~A..." args))))))))
  344. (defvar *arglist-pprint-bindings*
  345. '((*print-case* . :downcase)
  346. (*print-pretty* . t)
  347. (*print-circle* . nil)
  348. (*print-readably* . nil)
  349. (*print-level* . 10)
  350. (*print-length* . 20)
  351. (*print-escape* . nil)))
  352. (defvar *arglist-show-packages* t)
  353. (defmacro with-arglist-io-syntax (&body body)
  354. (let ((package (gensym)))
  355. `(let ((,package *package*))
  356. (with-standard-io-syntax
  357. (let ((*package* (if *arglist-show-packages*
  358. *package*
  359. ,package)))
  360. (with-bindings *arglist-pprint-bindings*
  361. ,@body))))))
  362. (defun decoded-arglist-to-string (decoded-arglist
  363. &key operator highlight
  364. print-right-margin)
  365. (with-output-to-string (*standard-output*)
  366. (with-arglist-io-syntax
  367. (let ((*print-right-margin* print-right-margin))
  368. (print-decoded-arglist decoded-arglist
  369. :operator operator
  370. :highlight highlight)))))
  371. (defun decoded-arglist-to-template-string (decoded-arglist
  372. &key (prefix "(") (suffix ")"))
  373. (with-output-to-string (*standard-output*)
  374. (with-arglist-io-syntax
  375. (print-decoded-arglist-as-template decoded-arglist
  376. :prefix prefix
  377. :suffix suffix))))
  378. ;;;; Arglist Decoding / Encoding
  379. (defun decode-required-arg (arg)
  380. "ARG can be a symbol or a destructuring pattern."
  381. (etypecase arg
  382. (symbol arg)
  383. (arglist-dummy arg)
  384. (list (decode-arglist arg))))
  385. (defun encode-required-arg (arg)
  386. (etypecase arg
  387. (symbol arg)
  388. (arglist (encode-arglist arg))))
  389. (defstruct (keyword-arg
  390. (:conc-name keyword-arg.)
  391. (:constructor %make-keyword-arg))
  392. keyword
  393. arg-name
  394. default-arg)
  395. (defun canonicalize-default-arg (form)
  396. (if (equalp ''nil form)
  397. nil
  398. form))
  399. (defun make-keyword-arg (keyword arg-name default-arg)
  400. (%make-keyword-arg :keyword keyword
  401. :arg-name arg-name
  402. :default-arg (canonicalize-default-arg default-arg)))
  403. (defun decode-keyword-arg (arg)
  404. "Decode a keyword item of formal argument list.
  405. Return three values: keyword, argument name, default arg."
  406. (flet ((intern-as-keyword (arg)
  407. (intern (etypecase arg
  408. (symbol (symbol-name arg))
  409. (arglist-dummy (arglist-dummy.string-representation arg)))
  410. keyword-package)))
  411. (cond ((or (symbolp arg) (arglist-dummy-p arg))
  412. (make-keyword-arg (intern-as-keyword arg) arg nil))
  413. ((and (consp arg)
  414. (consp (car arg)))
  415. (make-keyword-arg (caar arg)
  416. (decode-required-arg (cadar arg))
  417. (cadr arg)))
  418. ((consp arg)
  419. (make-keyword-arg (intern-as-keyword (car arg))
  420. (car arg) (cadr arg)))
  421. (t
  422. (error "Bad keyword item of formal argument list")))))
  423. (defun encode-keyword-arg (arg)
  424. (cond
  425. ((arglist-p (keyword-arg.arg-name arg))
  426. ;; Destructuring pattern
  427. (let ((keyword/name (list (keyword-arg.keyword arg)
  428. (encode-required-arg
  429. (keyword-arg.arg-name arg)))))
  430. (if (keyword-arg.default-arg arg)
  431. (list keyword/name
  432. (keyword-arg.default-arg arg))
  433. (list keyword/name))))
  434. ((eql (intern (symbol-name (keyword-arg.arg-name arg))
  435. keyword-package)
  436. (keyword-arg.keyword arg))
  437. (if (keyword-arg.default-arg arg)
  438. (list (keyword-arg.arg-name arg)
  439. (keyword-arg.default-arg arg))
  440. (keyword-arg.arg-name arg)))
  441. (t
  442. (let ((keyword/name (list (keyword-arg.keyword arg)
  443. (keyword-arg.arg-name arg))))
  444. (if (keyword-arg.default-arg arg)
  445. (list keyword/name
  446. (keyword-arg.default-arg arg))
  447. (list keyword/name))))))
  448. (progn
  449. (assert (equalp (decode-keyword-arg 'x)
  450. (make-keyword-arg :x 'x nil)))
  451. (assert (equalp (decode-keyword-arg '(x t))
  452. (make-keyword-arg :x 'x t)))
  453. (assert (equalp (decode-keyword-arg '((:x y)))
  454. (make-keyword-arg :x 'y nil)))
  455. (assert (equalp (decode-keyword-arg '((:x y) t))
  456. (make-keyword-arg :x 'y t))))
  457. ;;; FIXME suppliedp?
  458. (defstruct (optional-arg
  459. (:conc-name optional-arg.)
  460. (:constructor %make-optional-arg))
  461. arg-name
  462. default-arg)
  463. (defun make-optional-arg (arg-name default-arg)
  464. (%make-optional-arg :arg-name arg-name
  465. :default-arg (canonicalize-default-arg default-arg)))
  466. (defun decode-optional-arg (arg)
  467. "Decode an optional item of a formal argument list.
  468. Return an OPTIONAL-ARG structure."
  469. (etypecase arg
  470. (symbol (make-optional-arg arg nil))
  471. (arglist-dummy (make-optional-arg arg nil))
  472. (list (make-optional-arg (decode-required-arg (car arg))
  473. (cadr arg)))))
  474. (defun encode-optional-arg (optional-arg)
  475. (if (or (optional-arg.default-arg optional-arg)
  476. (arglist-p (optional-arg.arg-name optional-arg)))
  477. (list (encode-required-arg
  478. (optional-arg.arg-name optional-arg))
  479. (optional-arg.default-arg optional-arg))
  480. (optional-arg.arg-name optional-arg)))
  481. (progn
  482. (assert (equalp (decode-optional-arg 'x)
  483. (make-optional-arg 'x nil)))
  484. (assert (equalp (decode-optional-arg '(x t))
  485. (make-optional-arg 'x t))))
  486. (define-modify-macro nreversef () nreverse "Reverse the list in PLACE.")
  487. (defun decode-arglist (arglist)
  488. "Parse the list ARGLIST and return an ARGLIST structure."
  489. (etypecase arglist
  490. ((eql :not-available) (return-from decode-arglist
  491. :not-available))
  492. (list))
  493. (loop
  494. with mode = nil
  495. with result = (make-arglist)
  496. for arg = (if (consp arglist)
  497. (pop arglist)
  498. (progn
  499. (prog1 arglist
  500. (setf mode '&rest
  501. arglist nil))))
  502. do (cond
  503. ((eql mode '&unknown-junk)
  504. ;; don't leave this mode -- we don't know how the arglist
  505. ;; after unknown lambda-list keywords is interpreted
  506. (push arg (arglist.unknown-junk result)))
  507. ((eql arg '&allow-other-keys)
  508. (setf (arglist.allow-other-keys-p result) t))
  509. ((eql arg '&key)
  510. (setf (arglist.key-p result) t
  511. mode arg))
  512. ((memq arg '(&optional &rest &body &aux))
  513. (setq mode arg))
  514. ((memq arg '(&whole &environment))
  515. (setq mode arg)
  516. (push arg (arglist.known-junk result)))
  517. ((and (symbolp arg)
  518. (string= (symbol-name arg) (string '#:&any))) ; may be interned
  519. (setf (arglist.any-p result) t) ; in any *package*.
  520. (setq mode '&any))
  521. ((memq arg lambda-list-keywords)
  522. (setq mode '&unknown-junk)
  523. (push arg (arglist.unknown-junk result)))
  524. (t
  525. (ecase mode
  526. (&key
  527. (push (decode-keyword-arg arg)
  528. (arglist.keyword-args result)))
  529. (&optional
  530. (push (decode-optional-arg arg)
  531. (arglist.optional-args result)))
  532. (&body
  533. (setf (arglist.body-p result) t
  534. (arglist.rest result) arg))
  535. (&rest
  536. (setf (arglist.rest result) arg))
  537. (&aux
  538. (push (decode-optional-arg arg)
  539. (arglist.aux-args result)))
  540. ((nil)
  541. (push (decode-required-arg arg)
  542. (arglist.required-args result)))
  543. ((&whole &environment)
  544. (setf mode nil)
  545. (push arg (arglist.known-junk result)))
  546. (&any
  547. (push arg (arglist.any-args result))))))
  548. until (null arglist)
  549. finally (nreversef (arglist.required-args result))
  550. finally (nreversef (arglist.optional-args result))
  551. finally (nreversef (arglist.keyword-args result))
  552. finally (nreversef (arglist.aux-args result))
  553. finally (nreversef (arglist.any-args result))
  554. finally (nreversef (arglist.known-junk result))
  555. finally (nreversef (arglist.unknown-junk result))
  556. finally (assert (or (and (not (arglist.key-p result))
  557. (not (arglist.any-p result)))
  558. (exactly-one-p (arglist.key-p result)
  559. (arglist.any-p result))))
  560. finally (return result)))
  561. (defun encode-arglist (decoded-arglist)
  562. (append (mapcar #'encode-required-arg
  563. (arglist.required-args decoded-arglist))
  564. (when (arglist.optional-args decoded-arglist)
  565. '(&optional))
  566. (mapcar #'encode-optional-arg
  567. (arglist.optional-args decoded-arglist))
  568. (when (arglist.key-p decoded-arglist)
  569. '(&key))
  570. (mapcar #'encode-keyword-arg
  571. (arglist.keyword-args decoded-arglist))
  572. (when (arglist.allow-other-keys-p decoded-arglist)
  573. '(&allow-other-keys))
  574. (when (arglist.any-args decoded-arglist)
  575. `(&any ,@(arglist.any-args decoded-arglist)))
  576. (cond ((not (arglist.rest decoded-arglist))
  577. '())
  578. ((arglist.body-p decoded-arglist)
  579. `(&body ,(arglist.rest decoded-arglist)))
  580. (t
  581. `(&rest ,(arglist.rest decoded-arglist))))
  582. (when (arglist.aux-args decoded-arglist)
  583. `(&aux ,(arglist.aux-args decoded-arglist)))
  584. (arglist.known-junk decoded-arglist)
  585. (arglist.unknown-junk decoded-arglist)))
  586. ;;;; Arglist Enrichment
  587. (defun arglist-keywords (lambda-list)
  588. "Return the list of keywords in ARGLIST.
  589. As a secondary value, return whether &allow-other-keys appears."
  590. (let ((decoded-arglist (decode-arglist lambda-list)))
  591. (values (arglist.keyword-args decoded-arglist)
  592. (arglist.allow-other-keys-p decoded-arglist))))
  593. (defun methods-keywords (methods)
  594. "Collect all keywords in the arglists of METHODS.
  595. As a secondary value, return whether &allow-other-keys appears somewhere."
  596. (let ((keywords '())
  597. (allow-other-keys nil))
  598. (dolist (method methods)
  599. (multiple-value-bind (kw aok)
  600. (arglist-keywords
  601. (swank-mop:method-lambda-list method))
  602. (setq keywords (remove-duplicates (append keywords kw)
  603. :key #'keyword-arg.keyword)
  604. allow-other-keys (or allow-other-keys aok))))
  605. (values keywords allow-other-keys)))
  606. (defun generic-function-keywords (generic-function)
  607. "Collect all keywords in the methods of GENERIC-FUNCTION.
  608. As a secondary value, return whether &allow-other-keys appears somewhere."
  609. (methods-keywords
  610. (swank-mop:generic-function-methods generic-function)))
  611. (defun applicable-methods-keywords (generic-function arguments)
  612. "Collect all keywords in the methods of GENERIC-FUNCTION that are
  613. applicable for argument of CLASSES. As a secondary value, return
  614. whether &allow-other-keys appears somewhere."
  615. (methods-keywords
  616. (multiple-value-bind (amuc okp)
  617. (swank-mop:compute-applicable-methods-using-classes
  618. generic-function (mapcar #'class-of arguments))
  619. (if okp
  620. amuc
  621. (compute-applicable-methods generic-function arguments)))))
  622. (defgeneric extra-keywords (operator args)
  623. (:documentation "Return a list of extra keywords of OPERATOR (a
  624. symbol) when applied to the (unevaluated) ARGS.
  625. As a secondary value, return whether other keys are allowed.
  626. As a tertiary value, return the initial sublist of ARGS that was needed
  627. to determine the extra keywords."))
  628. ;;; We make sure that symbol-from-KEYWORD-using keywords come before
  629. ;;; symbol-from-arbitrary-package-using keywords. And we sort the
  630. ;;; latter according to how their home-packages relate to *PACKAGE*.
  631. ;;;
  632. ;;; Rationale is to show those key parameters first which make most
  633. ;;; sense in the current context. And in particular: to put
  634. ;;; implementation-internal stuff last.
  635. ;;;
  636. ;;; This matters tremendeously on Allegro in combination with
  637. ;;; AllegroCache as that does some evil tinkering with initargs,
  638. ;;; obfuscating the arglist of MAKE-INSTANCE.
  639. ;;;
  640. (defmethod extra-keywords :around (op args)
  641. (declare (ignorable op args))
  642. (multiple-value-bind (keywords aok enrichments) (call-next-method)
  643. (values (sort-extra-keywords keywords) aok enrichments)))
  644. (defun make-package-comparator (reference-packages)
  645. "Returns a two-argument test function which compares packages
  646. according to their used-by relation with REFERENCE-PACKAGES. Packages
  647. will be sorted first which appear first in the PACKAGE-USE-LIST of the
  648. reference packages."
  649. (let ((package-use-table (make-hash-table :test 'eq)))
  650. ;; Walk the package dependency graph breadth-fist, and fill
  651. ;; PACKAGE-USE-TABLE accordingly.
  652. (loop with queue = (copy-list reference-packages)
  653. with bfn = 0 ; Breadth-First Number
  654. for p = (pop queue)
  655. unless (gethash p package-use-table)
  656. do (setf (gethash p package-use-table) (shiftf bfn (1+ bfn)))
  657. and do (setf queue (nconc queue (copy-list (package-use-list p))))
  658. while queue)
  659. #'(lambda (p1 p2)
  660. (let ((bfn1 (gethash p1 package-use-table))
  661. (bfn2 (gethash p2 package-use-table)))
  662. (cond ((and bfn1 bfn2) (<= bfn1 bfn2))
  663. (bfn1 bfn1)
  664. (bfn2 nil) ; p2 is used, p1 not
  665. (t (string<= (package-name p1) (package-name p2))))))))
  666. (defun sort-extra-keywords (kwds)
  667. (stable-sort kwds (make-package-comparator (list keyword-package *package*))
  668. :key (compose #'symbol-package #'keyword-arg.keyword)))
  669. (defun keywords-of-operator (operator)
  670. "Return a list of KEYWORD-ARGs that OPERATOR accepts.
  671. This function is useful for writing EXTRA-KEYWORDS methods for
  672. user-defined functions which are declared &ALLOW-OTHER-KEYS and which
  673. forward keywords to OPERATOR."
  674. (with-available-arglist (arglist) (arglist-from-form (ensure-list operator))
  675. (values (arglist.keyword-args arglist)
  676. (arglist.allow-other-keys-p arglist))))
  677. (defmethod extra-keywords (operator args)
  678. ;; default method
  679. (declare (ignore args))
  680. (let ((symbol-function (symbol-function operator)))
  681. (if (typep symbol-function 'generic-function)
  682. (generic-function-keywords symbol-function)
  683. nil)))
  684. (defun class-from-class-name-form (class-name-form)
  685. (when (and (listp class-name-form)
  686. (= (length class-name-form) 2)
  687. (eq (car class-name-form) 'quote))
  688. (let* ((class-name (cadr class-name-form))
  689. (class (find-class class-name nil)))
  690. (when (and class
  691. (not (swank-mop:class-finalized-p class)))
  692. ;; Try to finalize the class, which can fail if
  693. ;; superclasses are not defined yet
  694. (ignore-errors (swank-mop:finalize-inheritance class)))
  695. class)))
  696. (defun extra-keywords/slots (class)
  697. (multiple-value-bind (slots allow-other-keys-p)
  698. (if (swank-mop:class-finalized-p class)
  699. (values (swank-mop:class-slots class) nil)
  700. (values (swank-mop:class-direct-slots class) t))
  701. (let ((slot-init-keywords
  702. (loop for slot in slots append
  703. (mapcar (lambda (initarg)
  704. (make-keyword-arg
  705. initarg
  706. (swank-mop:slot-definition-name slot)
  707. (and (swank-mop:slot-definition-initfunction slot)
  708. (swank-mop:slot-definition-initform slot))))
  709. (swank-mop:slot-definition-initargs slot)))))
  710. (values slot-init-keywords allow-other-keys-p))))
  711. (defun extra-keywords/make-instance (operator args)
  712. (declare (ignore operator))
  713. (unless (null args)
  714. (let* ((class-name-form (car args))
  715. (class (class-from-class-name-form class-name-form)))
  716. (when class
  717. (multiple-value-bind (slot-init-keywords class-aokp)
  718. (extra-keywords/slots class)
  719. (multiple-value-bind (allocate-instance-keywords ai-aokp)
  720. (applicable-methods-keywords
  721. #'allocate-instance (list class))
  722. (multiple-value-bind (initialize-instance-keywords ii-aokp)
  723. (ignore-errors
  724. (applicable-methods-keywords
  725. #'initialize-instance
  726. (list (swank-mop:class-prototype class))))
  727. (multiple-value-bind (shared-initialize-keywords si-aokp)
  728. (ignore-errors
  729. (applicable-methods-keywords
  730. #'shared-initialize
  731. (list (swank-mop:class-prototype class) t)))
  732. (values (append slot-init-keywords
  733. allocate-instance-keywords
  734. initialize-instance-keywords
  735. shared-initialize-keywords)
  736. (or class-aokp ai-aokp ii-aokp si-aokp)
  737. (list class-name-form))))))))))
  738. (defun extra-keywords/change-class (operator args)
  739. (declare (ignore operator))
  740. (unless (null args)
  741. (let* ((class-name-form (car args))
  742. (class (class-from-class-name-form class-name-form)))
  743. (when class
  744. (multiple-value-bind (slot-init-keywords class-aokp)
  745. (extra-keywords/slots class)
  746. (declare (ignore class-aokp))
  747. (multiple-value-bind (shared-initialize-keywords si-aokp)
  748. (ignore-errors
  749. (applicable-methods-keywords
  750. #'shared-initialize
  751. (list (swank-mop:class-prototype class) t)))
  752. ;; FIXME: much as it would be nice to include the
  753. ;; applicable keywords from
  754. ;; UPDATE-INSTANCE-FOR-DIFFERENT-CLASS, I don't really see
  755. ;; how to do it: so we punt, always declaring
  756. ;; &ALLOW-OTHER-KEYS.
  757. (declare (ignore si-aokp))
  758. (values (append slot-init-keywords shared-initialize-keywords)
  759. t
  760. (list class-name-form))))))))
  761. (defmethod extra-keywords ((operator (eql 'make-instance))
  762. args)
  763. (multiple-value-or (extra-keywords/make-instance operator args)
  764. (call-next-method)))
  765. (defmethod extra-keywords ((operator (eql 'make-condition))
  766. args)
  767. (multiple-value-or (extra-keywords/make-instance operator args)
  768. (call-next-method)))
  769. (defmethod extra-keywords ((operator (eql 'error))
  770. args)
  771. (multiple-value-or (extra-keywords/make-instance operator args)
  772. (call-next-method)))
  773. (defmethod extra-keywords ((operator (eql 'signal))
  774. args)
  775. (multiple-value-or (extra-keywords/make-instance operator args)
  776. (call-next-method)))
  777. (defmethod extra-keywords ((operator (eql 'warn))
  778. args)
  779. (multiple-value-or (extra-keywords/make-instance operator args)
  780. (call-next-method)))
  781. (defmethod extra-keywords ((operator (eql 'cerror))
  782. args)
  783. (multiple-value-bind (keywords aok determiners)
  784. (extra-keywords/make-instance operator (cdr args))
  785. (if keywords
  786. (values keywords aok
  787. (cons (car args) determiners))
  788. (call-next-method))))
  789. (defmethod extra-keywords ((operator (eql 'change-class))
  790. args)
  791. (multiple-value-bind (keywords aok determiners)
  792. (extra-keywords/change-class operator (cdr args))
  793. (if keywords
  794. (values keywords aok
  795. (cons (car args) determiners))
  796. (call-next-method))))
  797. (defun enrich-decoded-arglist-with-keywords (decoded-arglist keywords
  798. allow-other-keys-p)
  799. "Modify DECODED-ARGLIST using KEYWORDS and ALLOW-OTHER-KEYS-P."
  800. (when keywords
  801. (setf (arglist.key-p decoded-arglist) t)
  802. (setf (arglist.keyword-args decoded-arglist)
  803. (remove-duplicates
  804. (append (arglist.keyword-args decoded-arglist)
  805. keywords)
  806. :key #'keyword-arg.keyword)))
  807. (setf (arglist.allow-other-keys-p decoded-arglist)
  808. (or (arglist.allow-other-keys-p decoded-arglist)
  809. allow-other-keys-p)))
  810. (defun enrich-decoded-arglist-with-extra-keywords (decoded-arglist form)
  811. "Determine extra keywords from the function call FORM, and modify
  812. DECODED-ARGLIST to include them. As a secondary return value, return
  813. the initial sublist of ARGS that was needed to determine the extra
  814. keywords. As a tertiary return value, return whether any enrichment
  815. was done."
  816. (multiple-value-bind (extra-keywords extra-aok determining-args)
  817. (extra-keywords (car form) (cdr form))
  818. ;; enrich the list of keywords with the extra keywords
  819. (enrich-decoded-arglist-with-keywords decoded-arglist
  820. extra-keywords extra-aok)
  821. (values decoded-arglist
  822. determining-args
  823. (or extra-keywords extra-aok))))
  824. (defgeneric compute-enriched-decoded-arglist (operator-form argument-forms)
  825. (:documentation
  826. "Return three values: DECODED-ARGLIST, DETERMINING-ARGS, and
  827. ANY-ENRICHMENT, just like enrich-decoded-arglist-with-extra-keywords.
  828. If the arglist is not available, return :NOT-AVAILABLE."))
  829. (defmethod compute-enriched-decoded-arglist (operator-form argument-forms)
  830. (with-available-arglist (decoded-arglist)
  831. (decode-arglist (arglist operator-form))
  832. (enrich-decoded-arglist-with-extra-keywords decoded-arglist
  833. (cons operator-form
  834. argument-forms))))
  835. (defmethod compute-enriched-decoded-arglist
  836. ((operator-form (eql 'with-open-file)) argument-forms)
  837. (declare (ignore argument-forms))
  838. (multiple-value-bind (decoded-arglist determining-args)
  839. (call-next-method)
  840. (let ((first-arg (first (arglist.required-args decoded-arglist)))
  841. (open-arglist (compute-enriched-decoded-arglist 'open nil)))
  842. (when (and (arglist-p first-arg) (arglist-p open-arglist))
  843. (enrich-decoded-arglist-with-keywords
  844. first-arg
  845. (arglist.keyword-args open-arglist)
  846. nil)))
  847. (values decoded-arglist determining-args t)))
  848. (defmethod compute-enriched-decoded-arglist ((operator-form (eql 'apply))
  849. argument-forms)
  850. (let ((function-name-form (car argument-forms)))
  851. (when (and (listp function-name-form)
  852. (length= function-name-form 2)
  853. (memq (car function-name-form) '(quote function)))
  854. (let ((function-name (cadr function-name-form)))
  855. (when (valid-operator-symbol-p function-name)
  856. (let ((function-arglist
  857. (compute-enriched-decoded-arglist function-name
  858. (cdr argument-forms))))
  859. (return-from compute-enriched-decoded-arglist
  860. (values
  861. (make-arglist :required-args
  862. (list 'function)
  863. :optional-args
  864. (append
  865. (mapcar #'(lambda (arg)
  866. (make-optional-arg arg nil))
  867. (arglist.required-args function-arglist))
  868. (arglist.optional-args function-arglist))
  869. :key-p
  870. (arglist.key-p function-arglist)
  871. :keyword-args
  872. (arglist.keyword-args function-arglist)
  873. :rest
  874. 'args
  875. :allow-other-keys-p
  876. (arglist.allow-other-keys-p function-arglist))
  877. (list function-name-form)
  878. t)))))))
  879. (call-next-method))
  880. (defmethod compute-enriched-decoded-arglist
  881. ((operator-form (eql 'multiple-value-call)) argument-forms)
  882. (compute-enriched-decoded-arglist 'apply argument-forms))
  883. (defun delete-given-args (decoded-arglist args)
  884. "Delete given ARGS from DECODED-ARGLIST."
  885. (macrolet ((pop-or-return (list)
  886. `(if (null ,list)
  887. (return-from do-decoded-arglist)
  888. (pop ,list))))
  889. (do-decoded-arglist decoded-arglist
  890. (&provided ()
  891. (assert (eq (pop-or-return args)
  892. (pop (arglist.provided-args decoded-arglist)))))
  893. (&required ()
  894. (pop-or-return args)
  895. (pop (arglist.required-args decoded-arglist)))
  896. (&optional ()
  897. (pop-or-return args)
  898. (pop (arglist.optional-args decoded-arglist)))
  899. (&key (keyword)
  900. ;; N.b. we consider a keyword to be given only when the keyword
  901. ;; _and_ a value has been given for it.
  902. (loop for (key value) on args by #'cddr
  903. when (and (eq keyword key) value)
  904. do (setf (arglist.keyword-args decoded-arglist)
  905. (remove keyword (arglist.keyword-args decoded-arglist)
  906. :key #'keyword-arg.keyword))))))
  907. decoded-arglist)
  908. (defun remove-given-args (decoded-arglist args)
  909. ;; FIXME: We actually needa deep copy here.
  910. (delete-given-args (copy-arglist decoded-arglist) args))
  911. ;;;; Arglist Retrieval
  912. (defun arglist-from-form (form)
  913. (if (null form)
  914. :not-available
  915. (arglist-dispatch (car form) (cdr form))))
  916. (export 'arglist-dispatch)
  917. (defgeneric arglist-dispatch (operator arguments)
  918. ;; Default method
  919. (:method (operator arguments)
  920. (unless (and (symbolp operator) (valid-operator-symbol-p operator))
  921. (return-from arglist-dispatch :not-available))
  922. (when (equalp (package-name (symbol-package operator)) "closer-mop")
  923. (let ((standard-symbol (or (find-symbol (symbol-name operator) :cl)
  924. (find-symbol (symbol-name operator) :swank-mop))))
  925. (when standard-symbol
  926. (return-from arglist-dispatch
  927. (arglist-dispatch standard-symbol arguments)))))
  928. (multiple-value-bind (decoded-arglist determining-args)
  929. (compute-enriched-decoded-arglist operator arguments)
  930. (with-available-arglist (arglist) decoded-arglist
  931. ;; replace some formal args by determining actual args
  932. (setf arglist (delete-given-args arglist determining-args))
  933. (setf (arglist.provided-args arglist) determining-args)
  934. arglist))))
  935. (defmethod arglist-dispatch ((operator (eql 'defmethod)) arguments)
  936. (match (cons operator arguments)
  937. (('defmethod (#'function-exists-p gf-name) . rest)
  938. (let ((gf (fdefinition gf-name)))
  939. (when (typep gf 'generic-function)
  940. (with-available-arglist (arglist) (decode-arglist (arglist gf))
  941. (let ((qualifiers (loop for x in rest
  942. until (or (listp x) (empty-arg-p x))
  943. collect x)))
  944. (return-from arglist-dispatch
  945. (make-arglist :provided-args (cons gf-name qualifiers)
  946. :required-args (list arglist)
  947. :rest "body" :body-p t)))))))
  948. (_)) ; Fall through
  949. (call-next-method))
  950. (defmethod arglist-dispatch ((operator (eql 'define-compiler-macro)) arguments)
  951. (match (cons operator arguments)
  952. (('define-compiler-macro (#'function-exists-p gf-name) . _)
  953. (let ((gf (fdefinition gf-name)))
  954. (with-available-arglist (arglist) (decode-arglist (arglist gf))
  955. (return-from arglist-dispatch
  956. (make-arglist :provided-args (list gf-name)
  957. :required-args (list arglist)
  958. :rest "body" :body-p t)))))
  959. (_)) ; Fall through
  960. (call-next-method))
  961. (defmethod arglist-dispatch ((operator (eql 'eval-when)) arguments)
  962. (declare (ignore arguments))
  963. (let ((eval-when-args '(:compile-toplevel :load-toplevel :execute)))
  964. (make-arglist
  965. :required-args (list (make-arglist :any-p t :any-args eval-when-args))
  966. :rest '#:body :body-p t)))
  967. (defmethod arglist-dispatch ((operator (eql 'declare)) arguments)
  968. (let* ((declaration (cons operator (last arguments)))
  969. (typedecl-arglist (arglist-for-type-declaration declaration)))
  970. (if (arglist-available-p typedecl-arglist)
  971. typedecl-arglist
  972. (match declaration
  973. (('declare ((#'consp typespec) . decl-args))
  974. (with-available-arglist (typespec-arglist)
  975. (decoded-arglist-for-type-specifier typespec)
  976. (make-arglist
  977. :required-args (list (make-arglist
  978. :required-args (list typespec-arglist)
  979. :rest '#:variables)))))
  980. (('declare (decl-identifier . decl-args))
  981. (decoded-arglist-for-declaration decl-identifier decl-args))
  982. (_ (make-arglist :rest '#:declaration-specifiers))))))
  983. (defmethod arglist-dispatch ((operator (eql 'declaim)) arguments)
  984. (arglist-dispatch 'declare arguments))
  985. (defun arglist-for-type-declaration (declaration)
  986. (flet ((%arglist-for-type-declaration (identifier typespec rest-var-name)
  987. (with-available-arglist (typespec-arglist)
  988. (decoded-arglist-for-type-specifier typespec)
  989. (make-arglist
  990. :required-args (list (make-arglist
  991. :provided-args (list identifier)
  992. :required-args (list typespec-arglist)
  993. :rest rest-var-name))))))
  994. (match declaration
  995. (('declare ('type (#'consp typespec) . decl-args))
  996. (%arglist-for-type-declaration 'type typespec '#:variables))
  997. (('declare ('ftype (#'consp typespec) . decl-args))
  998. (%arglist-for-type-declaration 'ftype typespec '#:function-names))
  999. (('declare ((#'consp typespec) . decl-args))
  1000. (with-available-arglist (typespec-arglist)
  1001. (decoded-arglist-for-type-specifier typespec)
  1002. (make-arglist
  1003. :required-args (list (make-arglist
  1004. :required-args (list typespec-arglist)
  1005. :rest '#:variables)))))
  1006. (_ :not-available))))
  1007. (defun decoded-arglist-for-declaration (decl-identifier decl-args)
  1008. (declare (ignore decl-args))
  1009. (with-available-arglist (arglist)
  1010. (decode-arglist (declaration-arglist decl-identifier))
  1011. (setf (arglist.provided-args arglist) (list decl-identifier))
  1012. (make-arglist :required-args (list arglist))))
  1013. (defun decoded-arglist-for-type-specifier (type-specifier)
  1014. (etypecase type-specifier
  1015. (arglist-dummy :not-available)
  1016. (cons (decoded-arglist-for-type-specifier (car type-specifier)))
  1017. (symbol
  1018. (with-available-arglist (arglist)
  1019. (decode-arglist (type-specifier-arglist type-specifier))
  1020. (setf (arglist.provided-args arglist) (list type-specifier))
  1021. arglist))))
  1022. ;;; Slimefuns
  1023. ;;; We work on a RAW-FORM, or BUFFER-FORM, which represent the form at
  1024. ;;; user's point in Emacs. A RAW-FORM looks like
  1025. ;;;
  1026. ;;; ("FOO" ("BAR" ...) "QUUX" ("ZURP" SWANK::%CURSOR-MARKER%))
  1027. ;;;
  1028. ;;; The expression before the cursor marker is the expression where
  1029. ;;; user's cursor points at. An explicit marker is necessary to
  1030. ;;; disambiguate between
  1031. ;;;
  1032. ;;; ("IF" ("PRED")
  1033. ;;; ("F" "X" "Y" %CURSOR-MARKER%))
  1034. ;;;
  1035. ;;; and
  1036. ;;; ("IF" ("PRED")
  1037. ;;; ("F" "X" "Y") %CURSOR-MARKER%)
  1038. ;;; Notice that for a form like (FOO (BAR |) QUUX), where | denotes
  1039. ;;; user's point, the following should be sent ("FOO" ("BAR" ""
  1040. ;;; %CURSOR-MARKER%)). Only the forms up to point should be
  1041. ;;; considered.
  1042. (defslimefun autodoc (raw-form &key print-right-margin)
  1043. "Return a list of two elements.
  1044. First, a string representing the arglist for the deepest subform in
  1045. RAW-FORM that does have an arglist. The highlighted parameter is
  1046. wrapped in ===> X <===.
  1047. Second, a boolean value telling whether the returned string can be cached."
  1048. (handler-bind ((serious-condition
  1049. #'(lambda (c)
  1050. (unless (debug-on-swank-error)
  1051. (let ((*print-right-margin* print-right-margin))
  1052. (return-from autodoc
  1053. (format nil "Arglist Error: \"~A\"" c)))))))
  1054. (with-buffer-syntax ()
  1055. (multiple-value-bind (form arglist obj-at-cursor form-path)
  1056. (find-subform-with-arglist (parse-raw-form raw-form))
  1057. (cond ((boundp-and-interesting obj-at-cursor)
  1058. (list (print-variable-to-string obj-at-cursor) nil))
  1059. (t
  1060. (list
  1061. (with-available-arglist (arglist) arglist
  1062. (decoded-arglist-to-string
  1063. arglist
  1064. :print-right-margin print-right-margin
  1065. :operator (car form)
  1066. :highlight (form-path-to-arglist-path form-path
  1067. form
  1068. arglist)))
  1069. t)))))))
  1070. (defun boundp-and-interesting (symbol)
  1071. (and symbol
  1072. (symbolp symbol)
  1073. (boundp symbol)
  1074. (not (memq symbol '(cl:t cl:nil)))
  1075. (not (keywordp symbol))))
  1076. (defun print-variable-to-string (symbol)
  1077. "Return a short description of VARIABLE-NAME, or NIL."
  1078. (let ((*print-pretty* t) (*print-level* 4)
  1079. (*print-length* 10) (*print-lines* 1)
  1080. (*print-readably* nil)
  1081. (value (symbol-value symbol)))
  1082. (call/truncated-output-to-string
  1083. 75 (lambda (s)
  1084. (without-printing-errors (:object value :stream s)
  1085. (format s "~A ~A~S" symbol *echo-area-prefix* value))))))
  1086. (defslimefun complete-form (raw-form)
  1087. "Read FORM-STRING in the current buffer package, then complete it
  1088. by adding a template for the missing arguments."
  1089. ;; We do not catch errors here because COMPLETE-FORM is an
  1090. ;; interactive command, not automatically run in the background like
  1091. ;; ARGLIST-FOR-ECHO-AREA.
  1092. (with-buffer-syntax ()
  1093. (multiple-value-bind (arglist provided-args)
  1094. (find-immediately-containing-arglist (parse-raw-form raw-form))
  1095. (with-available-arglist (arglist) arglist
  1096. (decoded-arglist-to-template-string
  1097. (delete-given-args arglist
  1098. (remove-if #'empty-arg-p provided-args
  1099. :from-end t :count 1))
  1100. :prefix "" :suffix "")))))
  1101. (defslimefun completions-for-keyword (keyword-string raw-form)
  1102. "Return a list of possible completions for KEYWORD-STRING relative
  1103. to the context provided by RAW-FORM."
  1104. (with-buffer-syntax ()
  1105. (let ((arglist (find-immediately-containing-arglist
  1106. (parse-raw-form raw-form))))
  1107. (when (arglist-available-p arglist)
  1108. ;; It would be possible to complete keywords only if we are in
  1109. ;; a keyword position, but it is not clear if we want that.
  1110. (let* ((keywords
  1111. (append (mapcar #'keyword-arg.keyword
  1112. (arglist.keyword-args arglist))
  1113. (remove-if-not #'keywordp (arglist.any-args arglist))))
  1114. (keyword-name
  1115. (tokenize-symbol keyword-string))
  1116. (matching-keywords
  1117. (find-matching-symbols-in-list
  1118. keyword-name keywords (make-compound-prefix-matcher #\-)))
  1119. (converter (completion-output-symbol-converter keyword-string))
  1120. (strings
  1121. (mapcar converter
  1122. (mapcar #'symbol-name matching-keywords)))
  1123. (completion-set
  1124. (format-completion-set strings nil "")))
  1125. (list completion-set
  1126. (longest-compound-prefix completion-set)))))))
  1127. (defparameter +cursor-marker+ '%cursor-marker%)
  1128. (defun find-subform-with-arglist (form)
  1129. "Returns four values:
  1130. The appropriate subform of `form' which is closest to the
  1131. +CURSOR-MARKER+ and whose operator is valid and has an
  1132. arglist. The +CURSOR-MARKER+ is removed from that subform.
  1133. Second value is the arglist. Local function and macro definitions
  1134. appearing in `form' into account.
  1135. Third value is the object in front of +CURSOR-MARKER+.
  1136. Fourth value is a form path to that object."
  1137. (labels
  1138. ((yield-success (form local-ops)
  1139. (multiple-value-bind (form obj-at-cursor form-path)
  1140. (extract-cursor-marker form)
  1141. (values form
  1142. (let ((entry (assoc (car form) local-ops :test #'op=)))
  1143. (if entry
  1144. (decode-arglist (cdr entry))
  1145. (arglist-from-form form)))
  1146. obj-at-cursor
  1147. form-path)))
  1148. (yield-failure ()
  1149. (values nil :not-available))
  1150. (operator-p (operator local-ops)
  1151. (or (and (symbolp operator) (valid-operator-symbol-p operator))
  1152. (assoc operator local-ops :test #'op=)))
  1153. (op= (op1 op2)
  1154. (cond ((and (symbolp op1) (symbolp op2))
  1155. (eq op1 op2))
  1156. ((and (arglist-dummy-p op1) (arglist-dummy-p op2))
  1157. (string= (arglist-dummy.string-representation op1)
  1158. (arglist-dummy.string-representation op2)))))
  1159. (grovel-form (form local-ops)
  1160. "Descend FORM top-down, always taking the rightest branch,
  1161. until +CURSOR-MARKER+."
  1162. (assert (listp form))
  1163. (destructuring-bind (operator . args) form
  1164. ;; N.b. the user's cursor is at the rightmost, deepest
  1165. ;; subform right before +CURSOR-MARKER+.
  1166. (let ((last-subform (car (last form)))
  1167. (new-ops))
  1168. (cond
  1169. ((eq last-subform +cursor-marker+)
  1170. (if (operator-p operator local-ops)
  1171. (yield-success form local-ops)
  1172. (yield-failure)))
  1173. ((not (operator-p operator local-ops))
  1174. (grovel-form last-subform local-ops))
  1175. ;; Make sure to pick up the arglists of local
  1176. ;; function/macro definitions.
  1177. ((setq new-ops (extract-local-op-arglists operator args))
  1178. (multiple-value-or (grovel-form last-subform
  1179. (nconc new-ops local-ops))
  1180. (yield-success form local-ops)))
  1181. ;; Some typespecs clash with function names, so we make
  1182. ;; sure to bail out early.
  1183. ((member operator '(cl:declare cl:declaim))
  1184. (yield-success form local-ops))
  1185. ;; Mostly uninteresting, hence skip.
  1186. ((memq operator '(cl:quote cl:function))
  1187. (yield-failure))
  1188. (t
  1189. (multiple-value-or (grovel-form last-subform local-ops)
  1190. (yield-success form local-ops))))))))
  1191. (if (null form)
  1192. (yield-failure)
  1193. (grovel-form form '()))))
  1194. (defun extract-cursor-marker (form)
  1195. "Returns three values: normalized `form' without +CURSOR-MARKER+,
  1196. the object in front of +CURSOR-MARKER+, and a form path to that
  1197. object."
  1198. (labels ((grovel (form last path)
  1199. (let ((result-form))
  1200. (loop for (car . cdr) on form do
  1201. (cond ((eql car +cursor-marker+)
  1202. (decf (first path))
  1203. (return-from grovel
  1204. (values (nreconc result-form cdr)
  1205. last
  1206. (nreverse path))))
  1207. ((consp car)
  1208. (multiple-value-bind (new-car new-last new-path)
  1209. (grovel car last (cons 0 path))
  1210. (when new-path ; CAR contained cursor-marker?
  1211. (return-from grovel
  1212. (values (nreconc
  1213. (cons new-car result-form) cdr)
  1214. new-last
  1215. new-path))))))
  1216. (push car result-form)
  1217. (setq last car)
  1218. (incf (first path))
  1219. finally
  1220. (return-from grovel
  1221. (values (nreverse result-form) nil nil))))))
  1222. (grovel form nil (list 0))))
  1223. (defgeneric extract-local-op-arglists (operator args)
  1224. (:documentation
  1225. "If the form `(OPERATOR ,@ARGS) is a local operator binding form,
  1226. return a list of pairs (OP . ARGLIST) for each locally bound op.")
  1227. (:method (operator args)
  1228. (declare (ignore operator args))
  1229. nil)
  1230. ;; FLET
  1231. (:method ((operator (eql 'cl:flet)) args)
  1232. (let ((defs (first args))
  1233. (body (rest args)))
  1234. (cond ((null body) nil) ; `(flet ((foo (x) |'
  1235. ((atom defs) nil) ; `(flet ,foo (|'
  1236. (t (%collect-op/argl-alist defs)))))
  1237. ;; LABELS
  1238. (:method ((operator (eql 'cl:labels)) args)
  1239. ;; Notice that we only have information to "look backward" and
  1240. ;; show arglists of previously occuring local functions.
  1241. (destructuring-bind (defs . body) args
  1242. (unless (or (atom defs) (null body)) ; `(labels ,foo (|'
  1243. (let ((current-def (car (last defs))))
  1244. (cond ((atom current-def) nil) ; `(labels ((foo (x) ...)|'
  1245. ((not (null body))
  1246. (extract-local-op-arglists 'cl:flet args))
  1247. (t
  1248. (let ((def.body (cddr current-def)))
  1249. (when def.body
  1250. (%collect-op/argl-alist defs)))))))))
  1251. ;; MACROLET
  1252. (:method ((operator (eql 'cl:macrolet)) args)
  1253. (extract-local-op-arglists 'cl:labels args)))
  1254. (defun %collect-op/argl-alist (defs)
  1255. (setq defs (remove-if-not #'(lambda (x)
  1256. ;; Well-formed FLET/LABELS def?
  1257. (and (consp x) (second x)))
  1258. defs))
  1259. (loop for (name arglist . nil) in defs
  1260. collect (cons name arglist)))
  1261. (defun find-immediately-containing-arglist (form)
  1262. "Returns the arglist of the subform _immediately_ containing
  1263. +CURSOR-MARKER+ in `form'. Notice, however, that +CURSOR-MARKER+ may
  1264. be in a nested arglist \(e.g. `(WITH-OPEN-FILE (<here>'\), and the
  1265. arglist of the appropriate parent form \(WITH-OPEN-FILE\) will be
  1266. returned in that case."
  1267. (flet ((try (form-path form arglist)
  1268. (let* ((arglist-path (form-path-to-arglist-path form-path
  1269. form
  1270. arglist))
  1271. (argl (apply #'arglist-ref
  1272. arglist
  1273. arglist-path))
  1274. (args (apply #'provided-arguments-ref
  1275. (cdr form)
  1276. arglist
  1277. arglist-path)))
  1278. (when (and (arglist-p argl) (listp args))
  1279. (values argl args)))))
  1280. (multiple-value-bind (form arglist obj form-path)
  1281. (find-subform-with-arglist form)
  1282. (declare (ignore obj))
  1283. (with-available-arglist (arglist) arglist
  1284. ;; First try the form the cursor is in (in case of a normal
  1285. ;; form), then try the surrounding form (in case of a nested
  1286. ;; macro form).
  1287. (multiple-value-or (try form-path form arglist)
  1288. (try (butlast form-path) form arglist)
  1289. :not-available)))))
  1290. (defun form-path-to-arglist-path (form-path form arglist)
  1291. "Convert a form path to an arglist path consisting of arglist
  1292. indices."
  1293. (labels ((convert (path args arglist)
  1294. (if (null path)
  1295. nil
  1296. (let* ((idx (car path))
  1297. (idx* (arglist-index idx args arglist))
  1298. (arglist* (and idx* (arglist-ref arglist idx*)))
  1299. (args* (and idx* (provided-arguments-ref args
  1300. arglist
  1301. idx*))))
  1302. ;; The FORM-PATH may be more detailed than ARGLIST;
  1303. ;; consider (defun foo (x y) ...), a form path may
  1304. ;; point into the function's lambda-list, but the
  1305. ;; arglist of DEFUN won't contain as much information.
  1306. ;; So we only recurse if possible.
  1307. (cond ((null idx*)
  1308. nil)
  1309. ((arglist-p arglist*)
  1310. (cons idx* (convert (cdr path) args* arglist*)))
  1311. (t
  1312. (list idx*)))))))
  1313. (convert
  1314. ;; FORM contains irrelevant operator. Adjust FORM-PATH.
  1315. (cond ((null form-path) nil)
  1316. ((equal form-path '(0)) nil)
  1317. (t
  1318. (destructuring-bind (car . cdr) form-path
  1319. (cons (1- car) cdr))))
  1320. (cdr form)
  1321. arglist)))
  1322. (defun arglist-index (provided-argument-index provided-arguments arglist)
  1323. "Return the arglist index into `arglist' for the parameter belonging
  1324. to the argument (NTH `provided-argument-index' `provided-arguments')."
  1325. (let ((positional-args# (positional-args-number arglist))
  1326. (arg-index provided-argument-index))
  1327. (with-struct (arglist. key-p rest) arglist
  1328. (cond
  1329. ((< arg-index positional-args#) ; required + optional
  1330. arg-index)
  1331. ((and (not key-p) (not rest)) ; more provided than allowed
  1332. nil)
  1333. ((not key-p) ; rest + body
  1334. (assert (arglist.rest arglist))
  1335. positional-args#)
  1336. (t ; key
  1337. ;; Find last provided &key parameter
  1338. (let* ((argument (nth arg-index provided-arguments))
  1339. (provided-keys (subseq provided-arguments positional-args#)))
  1340. (loop for (key value) on provided-keys by #'cddr
  1341. when (eq value argument)
  1342. return (match key
  1343. (('quote symbol) symbol)
  1344. (_ key)))))))))
  1345. (defun arglist-ref (arglist &rest indices)
  1346. "Returns the parameter in ARGLIST along the INDICIES path. Numbers
  1347. represent positional parameters (required, optional), keywords
  1348. represent key parameters."
  1349. (flet ((ref-positional-arg (arglist index)
  1350. (check-type index (integer 0 *))
  1351. (with-struct (arglist. provided-args required-args
  1352. optional-args rest)
  1353. arglist
  1354. (loop for args in (list provided-args required-args
  1355. (mapcar #'optional-arg.arg-name
  1356. optional-args))
  1357. for args# = (length args)
  1358. if (< index args#)
  1359. return (nth index args)
  1360. else
  1361. do (decf index args#)
  1362. finally (return (or rest nil)))))
  1363. (ref-keyword-arg (arglist keyword)
  1364. ;; keyword argument may be any symbol,
  1365. ;; not only from the KEYWORD package.
  1366. (let ((keyword (match keyword
  1367. (('quote symbol) symbol)
  1368. (_ keyword))))
  1369. (do-decoded-arglist arglist
  1370. (&key (kw arg) (when (eq kw keyword)
  1371. (return-from ref-keyword-arg arg)))))
  1372. nil))
  1373. (dolist (index indices)
  1374. (assert (arglist-p arglist))
  1375. (setq arglist (if (numberp index)
  1376. (ref-positional-arg arglist index)
  1377. (ref-keyword-arg arglist index))))
  1378. arglist))
  1379. (defun provided-arguments-ref (provided-args arglist &rest indices)
  1380. "Returns the argument in PROVIDED-ARGUMENT along the INDICES path
  1381. relative to ARGLIST."
  1382. (check-type arglist arglist)
  1383. (flet ((ref (provided-args arglist index)
  1384. (if (numberp index)
  1385. (nth index provided-args)
  1386. (let ((provided-keys (subseq provided-args
  1387. (positional-args-number arglist))))
  1388. (loop for (key value) on provided-keys
  1389. when (eq key index)
  1390. return value)))))
  1391. (dolist (idx indices)
  1392. (setq provided-args (ref provided-args arglist idx))
  1393. (setq arglist (arglist-ref arglist idx)))
  1394. provided-args))
  1395. (defun positional-args-number (arglist)
  1396. (+ (length (arglist.provided-args arglist))
  1397. (length (arglist.required-args arglist))
  1398. (length (arglist.optional-args arglist))))
  1399. (defun parse-raw-form (raw-form)
  1400. "Parse a RAW-FORM into a Lisp form. I.e. substitute strings by
  1401. symbols if already interned. For strings not already interned, use
  1402. ARGLIST-DUMMY."
  1403. (unless (null raw-form)
  1404. (loop for element in raw-form
  1405. collect (etypecase element
  1406. (string (read-conversatively element))
  1407. (list (parse-raw-form element))
  1408. (symbol (prog1 element
  1409. ;; Comes after list, so ELEMENT can't be NIL.
  1410. (assert (eq element +cursor-marker+))))))))
  1411. (defun read-conversatively (string)
  1412. "Tries to find the symbol that's represented by STRING.
  1413. If it can't, this either means that STRING does not represent a
  1414. symbol, or that the symbol behind STRING would have to be freshly
  1415. interned. Because this function is supposed to be called from the
  1416. automatic arglist display stuff from Slime, interning freshly
  1417. symbols is a big no-no.
  1418. In such a case (that no symbol could be found), an object of type
  1419. ARGLIST-DUMMY is returned instead, which works as a placeholder
  1420. datum for subsequent logics to rely on."
  1421. (let* ((string (string-left-trim '(#\Space #\Tab #\Newline) string))
  1422. (length (length string))
  1423. (type (cond ((zerop length) nil)
  1424. ((eql (aref string 0) #\')
  1425. :quoted-symbol)
  1426. ((search "#'" string :end2 (min length 2))
  1427. :sharpquoted-symbol)
  1428. ((char= (char string 0) (char string (1- length))
  1429. #\")
  1430. :string)
  1431. (t
  1432. :symbol))))
  1433. (multiple-value-bind (symbol found?)
  1434. (case type
  1435. (:symbol (parse-symbol string))
  1436. (:quoted-symbol (parse-symbol (subseq string 1)))
  1437. (:sharpquoted-symbol (parse-symbol (subseq string 2)))
  1438. (:string (values string t))
  1439. (t (values string nil)))
  1440. (if found?
  1441. (ecase type
  1442. (:symbol symbol)
  1443. (:quoted-symbol `(quote ,symbol))
  1444. (:sharpquoted-symbol `(function ,symbol))
  1445. (:string (if (> length 1)
  1446. (subseq string 1 (1- length))
  1447. string)))
  1448. (make-arglist-dummy string)))))
  1449. (defun test-print-arglist ()
  1450. (flet ((test (arglist &rest strings)
  1451. (let* ((*package* (find-package :swank))
  1452. (actual (decoded-arglist-to-string
  1453. (decode-arglist arglist)
  1454. :print-right-margin 1000)))
  1455. (unless (loop for string in strings
  1456. thereis (string= actual string))
  1457. (warn "Test failed: ~S => ~S~% Expected: ~A"
  1458. arglist actual
  1459. (if (cdr strings)
  1460. (format nil "One of: ~{~S~^, ~}" strings)
  1461. (format nil "~S" (first strings))))))))
  1462. (test '(function cons) "(function cons)")
  1463. (test '(quote cons) "(quote cons)")
  1464. (test '(&key (function #'+))
  1465. "(&key (function #'+))" "(&key (function (function +)))")
  1466. (test '(&whole x y z) "(y z)")
  1467. (test '(x &aux y z) "(x)")
  1468. (test '(x &environment env y) "(x y)")
  1469. (test '(&key ((function f))) "(&key ((function ..)))")
  1470. (test
  1471. '(eval-when (&any :compile-toplevel :load-toplevel :execute) &body body)
  1472. "(eval-when (&any :compile-toplevel :load-toplevel :execute) &body body)")
  1473. (test '(declare (optimize &any (speed 1) (safety 1)))
  1474. "(declare (optimize &any (speed 1) (safety 1)))")))
  1475. (defun test-arglist-ref ()
  1476. (macrolet ((soft-assert (form)
  1477. `(unless ,form
  1478. (warn "Assertion failed: ~S~%" ',form))))
  1479. (let ((sample (decode-arglist '(x &key ((:k (y z)))))))
  1480. (soft-assert (eq (arglist-ref sample 0) 'x))
  1481. (soft-assert (eq (arglist-ref sample :k 0) 'y))
  1482. (soft-assert (eq (arglist-ref sample :k 1) 'z))
  1483. (soft-assert (eq (provided-arguments-ref '(a :k (b c)) sample 0)
  1484. 'a))
  1485. (soft-assert (eq (provided-arguments-ref '(a :k (b c)) sample :k 0)
  1486. 'b))
  1487. (soft-assert (eq (provided-arguments-ref '(a :k (b c)) sample :k 1)
  1488. 'c)))))
  1489. (test-print-arglist)
  1490. (test-arglist-ref)
  1491. (provide :swank-arglists)