Advertisement
Guest User

Untitled

a guest
Feb 21st, 2018
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 24.80 KB | None | 0 0
  1. (in-package :optima)
  2.  
  3. ;;; Data Destructor
  4.  
  5. (defstruct destructor
  6. bindings
  7. predicate-form
  8. accessor-forms)
  9.  
  10. ;;; Pattern Data Structure
  11.  
  12. (defstruct pattern)
  13.  
  14. (defstruct (variable-pattern (:include pattern)
  15. (:constructor %make-variable-pattern (name)))
  16. name)
  17.  
  18. (defun make-variable-pattern (&optional name)
  19. (when (or (eq name 'otherwise)
  20. (string= name "_"))
  21. (setq name nil))
  22. (%make-variable-pattern name))
  23.  
  24. (defstruct (place-pattern (:include pattern)
  25. (:constructor make-place-pattern (name)))
  26. name)
  27.  
  28. (defstruct (constant-pattern (:include pattern)
  29. (:constructor make-constant-pattern (value)))
  30. value)
  31.  
  32. (defstruct (complex-pattern (:include pattern))
  33. subpatterns)
  34.  
  35. (defstruct (guard-pattern (:include complex-pattern)
  36. (:constructor make-guard-pattern (subpattern test-form
  37. &aux (subpatterns (list subpattern)))))
  38. test-form)
  39.  
  40. (defun guard-pattern-subpattern (pattern)
  41. (first (complex-pattern-subpatterns pattern)))
  42.  
  43. (defstruct (not-pattern (:include complex-pattern)
  44. (:constructor make-not-pattern (subpattern
  45. &aux (subpatterns (list subpattern))))))
  46.  
  47. (defun not-pattern-subpattern (pattern)
  48. (first (complex-pattern-subpatterns pattern)))
  49.  
  50. (defstruct (or-pattern (:include complex-pattern)
  51. (:constructor make-or-pattern (&rest subpatterns))))
  52.  
  53. (defstruct (and-pattern (:include complex-pattern)
  54. (:constructor make-and-pattern (&rest subpatterns))))
  55.  
  56. (defstruct (constructor-pattern (:include complex-pattern)))
  57.  
  58. (defun constructor-pattern-arity (pattern)
  59. (length (constructor-pattern-subpatterns pattern)))
  60.  
  61. (defgeneric constructor-pattern-destructor-sharable-p (x y))
  62. (defgeneric constructor-pattern-make-destructor (pattern var))
  63.  
  64. (defstruct (cons-pattern (:include constructor-pattern)
  65. (:constructor make-cons-pattern (car-pattern cdr-pattern
  66. &aux (subpatterns (list car-pattern
  67. cdr-pattern))))))
  68.  
  69. (defun cons-pattern-car-pattern (pattern)
  70. (first (constructor-pattern-subpatterns pattern)))
  71.  
  72. (defun cons-pattern-cdr-pattern (pattern)
  73. (second (constructor-pattern-subpatterns pattern)))
  74.  
  75. (defmethod constructor-pattern-destructor-sharable-p ((x cons-pattern) (y cons-pattern))
  76. t)
  77.  
  78. (defmethod constructor-pattern-make-destructor ((pattern cons-pattern) var)
  79. (make-destructor :predicate-form `(consp ,var)
  80. :accessor-forms (list `(car ,var) `(cdr ,var))))
  81.  
  82. (defstruct (assoc-pattern (:include constructor-pattern)
  83. (:constructor make-assoc-pattern (item value-pattern
  84. &key key test
  85. &aux (subpatterns (list value-pattern)))))
  86. item key test)
  87.  
  88. (defun assoc-pattern-value-pattern (pattern)
  89. (first (constructor-pattern-subpatterns pattern)))
  90.  
  91. (defmethod constructor-pattern-destructor-sharable-p ((x assoc-pattern) (y assoc-pattern))
  92. (and (eq (assoc-pattern-key x)
  93. (assoc-pattern-key y))
  94. (eq (assoc-pattern-test x)
  95. (assoc-pattern-test y))
  96. ;; FIXME: Don't use EQL
  97. (eql (assoc-pattern-item x)
  98. (assoc-pattern-item y))))
  99.  
  100. (defmethod constructor-pattern-make-destructor ((pattern assoc-pattern) var)
  101. (with-slots (item key test) pattern
  102. (with-unique-names (it)
  103. (make-destructor :bindings `((,it (%assoc ',item ,var
  104. ,@(when key `(:key #',key))
  105. ,@(when test `(:test #',test)))))
  106. :predicate-form it
  107. :accessor-forms (list `(cdr ,it))))))
  108.  
  109. (defstruct (property-pattern (:include constructor-pattern)
  110. (:constructor make-property-pattern (item value-pattern
  111. &aux (subpatterns (list value-pattern)))))
  112. item)
  113.  
  114. (defun property-pattern-value-pattern (pattern)
  115. (first (constructor-pattern-subpatterns pattern)))
  116.  
  117. (defmethod constructor-pattern-destructor-sharable-p ((x property-pattern) (y property-pattern))
  118. (eq (property-pattern-item x) (property-pattern-item y)))
  119.  
  120. (defmethod constructor-pattern-make-destructor ((pattern property-pattern) var)
  121. (with-slots (item) pattern
  122. (with-unique-names (it)
  123. (make-destructor :bindings `((,it (%get-property ',item ,var)))
  124. :predicate-form it
  125. :accessor-forms (list `(car ,it))))))
  126.  
  127. (defstruct (vector-pattern (:include constructor-pattern)
  128. (:constructor make-vector-pattern (&rest subpatterns))))
  129.  
  130. (defmethod constructor-pattern-destructor-sharable-p ((x vector-pattern) (y vector-pattern))
  131. (= (constructor-pattern-arity x)
  132. (constructor-pattern-arity y)))
  133.  
  134. (defmethod constructor-pattern-make-destructor ((pattern vector-pattern) var)
  135. (make-destructor :predicate-form `(typep ,var '(vector * ,(constructor-pattern-arity pattern)))
  136. :accessor-forms (loop for i from 0 below (constructor-pattern-arity pattern)
  137. collect `(aref ,var ,i))))
  138.  
  139. (defstruct (simple-vector-pattern (:include constructor-pattern)
  140. (:constructor make-simple-vector-pattern (&rest subpatterns))))
  141.  
  142. (defmethod constructor-pattern-destructor-sharable-p ((x simple-vector-pattern) (y simple-vector-pattern))
  143. (= (constructor-pattern-arity x)
  144. (constructor-pattern-arity y)))
  145.  
  146. (defmethod constructor-pattern-make-destructor ((pattern simple-vector-pattern) var)
  147. (make-destructor :predicate-form `(typep ,var '(simple-vector ,(constructor-pattern-arity pattern)))
  148. :accessor-forms (loop for i from 0 below (constructor-pattern-arity pattern)
  149. collect `(svref ,var ,i))))
  150.  
  151. (defstruct (class-pattern (:include constructor-pattern)
  152. (:constructor %make-class-pattern))
  153. class-name slot-names)
  154.  
  155. (defun make-class-pattern (class-name &rest slot-specs)
  156. (%make-class-pattern :class-name class-name
  157. :slot-names (mapcar #'first slot-specs)
  158. :subpatterns (mapcar #'second slot-specs)))
  159.  
  160. (defmethod constructor-pattern-destructor-sharable-p ((x class-pattern) (y class-pattern))
  161. (and (eq (class-pattern-class-name x)
  162. (class-pattern-class-name y))
  163. (equal (class-pattern-slot-names x)
  164. (class-pattern-slot-names y))))
  165.  
  166. (defmethod constructor-pattern-make-destructor ((pattern class-pattern) var)
  167. (make-destructor :predicate-form `(typep ,var ',(class-pattern-class-name pattern))
  168. :accessor-forms (loop for slot-name in (class-pattern-slot-names pattern)
  169. collect `(slot-value ,var ',slot-name))))
  170.  
  171. (defstruct (structure-pattern (:include constructor-pattern)
  172. (:constructor %make-structure-pattern))
  173. conc-name slot-names)
  174.  
  175. (defun make-structure-pattern (conc-name &rest slot-specs)
  176. (%make-structure-pattern :conc-name conc-name
  177. :slot-names (mapcar #'first slot-specs)
  178. :subpatterns (mapcar #'second slot-specs)))
  179.  
  180. (defmethod constructor-pattern-destructor-sharable-p ((x structure-pattern) (y structure-pattern))
  181. (and (string= (structure-pattern-conc-name x)
  182. (structure-pattern-conc-name y))
  183. (equal (structure-pattern-slot-names x)
  184. (structure-pattern-slot-names y))))
  185.  
  186. (defmethod constructor-pattern-make-destructor ((pattern structure-pattern) var)
  187. (make-destructor :predicate-form `(,(symbolicate (structure-pattern-conc-name pattern) :p) ,var)
  188. :accessor-forms (loop with conc-name = (structure-pattern-conc-name pattern)
  189. for slot-name in (structure-pattern-slot-names pattern)
  190. collect `(,(symbolicate conc-name slot-name) ,var))))
  191.  
  192. ;;; Pattern Utilities
  193.  
  194. (defun pattern-variables (pattern)
  195. "Returns the set of variables in PATTERN. If PATTERN is not linear,
  196. an error will be raised."
  197. (flet ((check (vars)
  198. (loop for var in vars
  199. if (find var seen)
  200. do (error "Non-linear pattern: ~S"
  201. (unparse-pattern pattern))
  202. collect var into seen
  203. finally (return vars))))
  204. (typecase pattern
  205. (variable-pattern
  206. (if-let ((name (variable-pattern-name pattern)))
  207. (list name)))
  208. (or-pattern
  209. (let ((vars (mappend #'pattern-variables (or-pattern-subpatterns pattern))))
  210. (check (remove-duplicates vars))))
  211. (complex-pattern
  212. (check (mappend #'pattern-variables (complex-pattern-subpatterns pattern)))))))
  213.  
  214. (defun place-pattern-included-p (pattern)
  215. (typecase pattern
  216. (place-pattern t)
  217. (complex-pattern
  218. (some #'place-pattern-included-p
  219. (complex-pattern-subpatterns pattern)))))
  220.  
  221. (defun check-patterns (patterns)
  222. "Check if PATTERNS are valid. Otherwise, an error will be raised."
  223. (loop for var in (mappend #'pattern-variables patterns)
  224. if (find var seen)
  225. do (error "Non-linear patterns: ~S"
  226. (mapcar #'unparse-pattern patterns))
  227. collect var into seen
  228. finally (return t)))
  229.  
  230. (defun lift-guard-patterns-1 (pattern)
  231. "Lifts GUARD patterns in PATTERN so that the guards can see
  232. any variables in PATTERN. The transform looks like:
  233.  
  234. (list x (guard y (equal x y)))
  235. => (guard (list x y) (equal x y))
  236.  
  237. Multiple guards will be connected with conjunction in order of
  238. occurence like:
  239.  
  240. (list (guard x (consp x)) (guard y (eq y (car x))))
  241. => (guard (list x (guard y (eq y (car x)))) (consp x))
  242. => (guard (guard (list x y) (eq y (car x))) (consp x))
  243. => (guard (list x y) (and (consp x) (eq y (car x))))"
  244. (cond
  245. ((guard-pattern-p pattern)
  246. (let ((subpattern (lift-guard-patterns (guard-pattern-subpattern pattern)))
  247. (test-form (guard-pattern-test-form pattern)))
  248. (if (guard-pattern-p subpattern)
  249. ;; Connect with conjunction like:
  250. ;; (guard (guard p g2) g1) => (guard p (and g1 g2))
  251. (let ((test-form `(and ,test-form ,(guard-pattern-test-form subpattern)))
  252. (subpattern (guard-pattern-subpattern subpattern)))
  253. (make-guard-pattern subpattern test-form))
  254. pattern)))
  255. ((not-pattern-p pattern)
  256. ;; Stop lifting on not pattern.
  257. (let* ((subpattern (not-pattern-subpattern pattern))
  258. (lifted-subpattern (lift-guard-patterns subpattern)))
  259. (if (and (not (guard-pattern-p subpattern))
  260. (guard-pattern-p lifted-subpattern))
  261. (make-not-pattern lifted-subpattern)
  262. pattern)))
  263. ((or-pattern-p pattern)
  264. ;; OR local lift.
  265. (let* ((subpatterns (or-pattern-subpatterns pattern))
  266. (lifted-subpatterns (mapcar #'lift-guard-patterns subpatterns)))
  267. (if (every #'eq subpatterns lifted-subpatterns)
  268. pattern
  269. (apply #'make-or-pattern lifted-subpatterns))))
  270. ((complex-pattern-p pattern)
  271. (let ((subpatterns (mapcar #'lift-guard-patterns (complex-pattern-subpatterns pattern))))
  272. (if (some #'guard-pattern-p subpatterns)
  273. ;; Lift guard patterns like:
  274. ;; (c ... (guard p g) ...) => (guard (c ... p ...) g)
  275. (loop for subpattern in subpatterns
  276. if (guard-pattern-p subpattern)
  277. collect (guard-pattern-test-form subpattern) into test-forms
  278. and do (setq subpattern (guard-pattern-subpattern subpattern))
  279. collect subpattern into new-subpatterns
  280. finally
  281. (let ((pattern (copy-structure pattern)))
  282. (setf (complex-pattern-subpatterns pattern) new-subpatterns)
  283. (return (make-guard-pattern pattern `(and ,.test-forms)))))
  284. ;; Otherwise, just return the original pattern
  285. pattern)))
  286. (t pattern)))
  287.  
  288. (defun lift-guard-patterns-2 (pattern)
  289. "Lifts OR patterns that include guards like:
  290.  
  291. (list 3 (or 1 (guard x (evenp x))))
  292. => (or (list 3 1) (list 3 (guard x (evenp x))))
  293. => (or (list 3 1) (guard (list 3 x) (evenp x)))"
  294. (flet ((guards-or-pattern-p (p)
  295. (and (or-pattern-p p)
  296. (some #'guard-pattern-p (or-pattern-subpatterns p)))))
  297. (cond
  298. ((or-pattern-p pattern)
  299. (let ((subpatterns (mapcar #'lift-guard-patterns (or-pattern-subpatterns pattern))))
  300. (if (some #'or-pattern-p subpatterns)
  301. ;; Expand nested OR patterns
  302. (loop for subpattern in subpatterns
  303. if (or-pattern-p subpattern)
  304. append (or-pattern-subpatterns subpattern) into new-subpatterns
  305. else
  306. collect subpattern into new-subpatterns
  307. finally (return (lift-guard-patterns (apply #'make-or-pattern new-subpatterns))))
  308. pattern)))
  309. ((complex-pattern-p pattern)
  310. (let ((subpatterns (mapcar #'lift-guard-patterns (complex-pattern-subpatterns pattern))))
  311. (if (some #'guards-or-pattern-p subpatterns)
  312. ;; Lift first OR pattern that include GUARD patterns like:
  313. ;; (c ... (or ... (guard p g) ...) ...) => (or ... (c ... (guard p g) ...) ...)
  314. (loop for i from 0
  315. for subpattern in subpatterns
  316. if (guards-or-pattern-p subpattern)
  317. return (loop for subpat in (or-pattern-subpatterns subpattern)
  318. for pat = (copy-structure pattern)
  319. for pat-subpats = (copy-list (complex-pattern-subpatterns pat))
  320. do (setf (nth i pat-subpats) subpat
  321. (complex-pattern-subpatterns pat) pat-subpats)
  322. collect pat into new-pats
  323. finally (return (lift-guard-patterns (apply #'make-or-pattern new-pats)))))
  324. ;; Otherwise, just return the original pattern
  325. pattern)))
  326. (t pattern))))
  327.  
  328. (defun lift-guard-patterns (pattern)
  329. (let ((new-pattern (lift-guard-patterns-1 (lift-guard-patterns-2 (lift-guard-patterns-1 pattern)))))
  330. (if (eq pattern new-pattern)
  331. new-pattern
  332. (lift-guard-patterns new-pattern))))
  333.  
  334. ;;; Pattern Specifier
  335.  
  336. (defun pattern-expand-function (name)
  337. (get name 'pattern-expand-function))
  338.  
  339. (eval-when (:compile-toplevel :load-toplevel :execute)
  340. (defun (setf pattern-expand-function) (function name)
  341. (setf (get name 'pattern-expand-function) function)))
  342.  
  343. (defun pattern-expand-1 (pattern)
  344. (if-let (it (and (consp pattern)
  345. (symbolp (car pattern))
  346. (pattern-expand-function (car pattern))))
  347. (apply it (cdr pattern))
  348. pattern))
  349.  
  350. (defun pattern-expand (pattern)
  351. (let ((expansion (pattern-expand-1 pattern)))
  352. (if (eq pattern expansion)
  353. pattern
  354. (pattern-expand expansion))))
  355.  
  356. (defun pattern-expand-all (pattern)
  357. (setq pattern (pattern-expand pattern))
  358. (if (consp pattern)
  359. (cons (car pattern)
  360. (mapcar #'pattern-expand-all (cdr pattern)))
  361. pattern))
  362.  
  363. (defmacro defpattern (name lambda-list &body body)
  364. "Defines a derived pattern specifier named NAME. This is analogous
  365. to DEFTYPE.
  366.  
  367. Examples:
  368.  
  369. ;; Defines a LIST pattern.
  370. (defpattern list (&rest args)
  371. (when args
  372. `(cons ,(car args) (list ,@(cdr args)))))"
  373. `(eval-when (:compile-toplevel :load-toplevel :execute)
  374. (setf (pattern-expand-function ',name) (lambda ,lambda-list ,@body))))
  375.  
  376. (defpattern list (&rest args)
  377. (when args
  378. `(cons ,(car args) (list ,@(cdr args)))))
  379.  
  380. (defpattern list* (arg &rest args)
  381. (if (null args)
  382. `,arg
  383. `(cons ,arg (list* ,@args))))
  384.  
  385. (defpattern satisfies (predicate-name)
  386. (with-unique-names (it)
  387. `(guard ,it (,predicate-name ,it))))
  388.  
  389. (defpattern eq (arg)
  390. (with-unique-names (it)
  391. `(guard ,it (eq ,it ,arg))))
  392.  
  393. (defpattern eql (arg)
  394. (with-unique-names (it)
  395. `(guard ,it (eql ,it ,arg))))
  396.  
  397. (defpattern equal (arg)
  398. (with-unique-names (it)
  399. `(guard ,it (equal ,it ,arg))))
  400.  
  401. (defpattern equalp (arg)
  402. (with-unique-names (it)
  403. `(guard ,it (equalp ,it ,arg))))
  404.  
  405. (defpattern type (type-specifier)
  406. (with-unique-names (it)
  407. `(guard ,it (typep ,it ',type-specifier))))
  408.  
  409. ;;; Pattern Specifier Parser
  410.  
  411. (defun parse-pattern (pattern)
  412. (when (pattern-p pattern)
  413. (return-from parse-pattern pattern))
  414. (setq pattern (pattern-expand pattern))
  415. (typecase pattern
  416. ((or (eql t) null keyword)
  417. (make-constant-pattern pattern))
  418. (symbol
  419. (make-variable-pattern pattern))
  420. (cons
  421. (destructuring-case pattern
  422. ((variable name)
  423. (make-variable-pattern name))
  424. ((place name)
  425. (make-place-pattern name))
  426. ((quote value)
  427. (make-constant-pattern value))
  428. ((guard subpattern test-form)
  429. (make-guard-pattern (parse-pattern subpattern) test-form))
  430. ((not subpattern)
  431. (make-not-pattern (parse-pattern subpattern)))
  432. ((or &rest subpatterns)
  433. (if (= (length subpatterns) 1)
  434. (parse-pattern (first subpatterns))
  435. (let ((subpatterns (mapcar #'parse-pattern subpatterns)))
  436. (when (some #'place-pattern-included-p subpatterns)
  437. (error "Or-pattern can't include place-patterns."))
  438. (apply #'make-or-pattern subpatterns))))
  439. ((and &rest subpatterns)
  440. (if (= (length subpatterns) 1)
  441. (parse-pattern (first subpatterns))
  442. (apply #'make-and-pattern (mapcar #'parse-pattern subpatterns))))
  443. ((otherwise &rest args)
  444. (apply #'parse-constructor-pattern (car pattern) args))))
  445. (otherwise
  446. (make-constant-pattern pattern))))
  447.  
  448. (defgeneric parse-constructor-pattern (name &rest args))
  449.  
  450. (defmethod parse-constructor-pattern ((name (eql 'cons)) &rest args)
  451. (unless (= (length args) 2)
  452. (error "Malformed pattern: ~S" (list* 'cons args)))
  453. (apply #'make-cons-pattern (mapcar #'parse-pattern args)))
  454.  
  455. (defmethod parse-constructor-pattern ((name (eql 'assoc)) &rest args)
  456. (destructuring-bind (item pattern &key key test) args
  457. (make-assoc-pattern item (parse-pattern pattern) :key key :test test)))
  458.  
  459. (defmethod parse-constructor-pattern ((name (eql 'property)) &rest args)
  460. (destructuring-bind (item pattern) args
  461. (make-property-pattern item (parse-pattern pattern))))
  462.  
  463. (defmethod parse-constructor-pattern ((name (eql 'vector)) &rest args)
  464. (apply #'make-vector-pattern (mapcar #'parse-pattern args)))
  465.  
  466. (defmethod parse-constructor-pattern ((name (eql 'simple-vector)) &rest args)
  467. (apply #'make-simple-vector-pattern (mapcar #'parse-pattern args)))
  468.  
  469. (defun parse-class-pattern (class-name &rest slot-specs)
  470. ;; Transform MAKE-INSTANCE style syntax. During the transformation,
  471. ;; we also resolve the slot names via MOP. If no slot found or too
  472. ;; many slots found, we will raise an error.
  473. (when (keywordp (first slot-specs))
  474. (let ((class (find-class class-name nil)))
  475. (unless (closer-mop:class-finalized-p class)
  476. (closer-mop:finalize-inheritance class))
  477. (setq slot-specs
  478. (loop with all-slot-names = (mapcar #'closer-mop:slot-definition-name
  479. (closer-mop:class-slots class))
  480. for (slot-name . pattern) in (plist-alist slot-specs)
  481. for slot-names = (remove-if (lambda (name) (string/= slot-name name))
  482. all-slot-names)
  483. collect (case (length slot-names)
  484. (0 (error "Slot ~S not found" slot-name))
  485. (1 `(,(first slot-names) ,pattern))
  486. (t (error "Ambiguous slot name ~S" slot-name)))))))
  487. (apply #'make-class-pattern class-name
  488. (loop for slot-spec in slot-specs
  489. do (setq slot-spec (ensure-list slot-spec))
  490. collect (let ((slot-name (first slot-spec)))
  491. (list slot-name
  492. (if (rest slot-spec)
  493. (parse-pattern `(and ,@(rest slot-spec)))
  494. (make-variable-pattern slot-name)))))))
  495.  
  496. (defun parse-structure-pattern (conc-name &rest slot-specs)
  497. ;; Transform MAKE-INSTANCE style syntax.
  498. (when (keywordp (first slot-specs))
  499. (setq slot-specs (mapcar (lambda (assoc) (list (car assoc) (cdr assoc)))
  500. (plist-alist slot-specs))))
  501. (apply #'make-structure-pattern conc-name
  502. (loop for slot-spec in slot-specs
  503. do (setq slot-spec (ensure-list slot-spec))
  504. collect (let ((slot-name (first slot-spec)))
  505. (list slot-name
  506. (if (rest slot-spec)
  507. (parse-pattern `(and ,@(rest slot-spec)))
  508. (make-variable-pattern slot-name)))))))
  509.  
  510. (defmethod parse-constructor-pattern ((name (eql 'class)) &rest args)
  511. (apply #'parse-class-pattern args))
  512.  
  513. (defmethod parse-constructor-pattern ((name (eql 'structure)) &rest args)
  514. (apply #'parse-structure-pattern args))
  515.  
  516. (defmethod parse-constructor-pattern (name &rest slot-specs)
  517. (if (find-class name nil)
  518. (apply #'parse-class-pattern name slot-specs)
  519. (apply #'parse-structure-pattern name slot-specs)))
  520.  
  521. ;;; Pattern Specifier Parser
  522.  
  523. (defgeneric unparse-pattern (pattern))
  524.  
  525. (defmethod unparse-pattern ((pattern variable-pattern))
  526. (or (variable-pattern-name pattern) '_))
  527.  
  528. (defmethod unparse-pattern ((pattern place-pattern))
  529. `(place ,(place-pattern-name pattern)))
  530.  
  531. (defmethod unparse-pattern ((pattern constant-pattern))
  532. (with-slots (value) pattern
  533. (cond
  534. ((typep value '(and symbol (not keyword) (not (member nil t))))
  535. `(quote ,value))
  536. ((atom value)
  537. value)
  538. (t
  539. `(quote ,value)))))
  540.  
  541. (defmethod unparse-pattern ((pattern guard-pattern))
  542. `(guard ,(unparse-pattern (guard-pattern-subpattern pattern))
  543. ,(guard-pattern-test-form pattern)))
  544.  
  545. (defmethod unparse-pattern ((pattern not-pattern))
  546. `(not ,(unparse-pattern (not-pattern-subpattern pattern))))
  547.  
  548. (defmethod unparse-pattern ((pattern or-pattern))
  549. `(or ,@(mapcar #'unparse-pattern (or-pattern-subpatterns pattern))))
  550.  
  551. (defmethod unparse-pattern ((pattern and-pattern))
  552. `(and ,@(mapcar #'unparse-pattern (and-pattern-subpatterns pattern))))
  553.  
  554. (defmethod unparse-pattern ((pattern cons-pattern))
  555. `(cons ,(unparse-pattern (cons-pattern-car-pattern pattern))
  556. ,(unparse-pattern (cons-pattern-cdr-pattern pattern))))
  557.  
  558. (defmethod unparse-pattern ((pattern assoc-pattern))
  559. (with-slots (item key test) pattern
  560. `(assoc ,item
  561. ,(unparse-pattern (assoc-pattern-value-pattern pattern))
  562. ,@(when key (list :key key))
  563. ,@(when test (list :test test)))))
  564.  
  565. (defmethod unparse-pattern ((pattern property-pattern))
  566. `(property ,(property-pattern-item pattern)
  567. ,(unparse-pattern (property-pattern-value-pattern pattern))))
  568.  
  569. (defmethod unparse-pattern ((pattern vector-pattern))
  570. `(vector ,@(mapcar #'unparse-pattern (vector-pattern-subpatterns pattern))))
  571.  
  572. (defmethod unparse-pattern ((pattern simple-vector-pattern))
  573. `(simple-vector ,@(mapcar #'unparse-pattern (simple-vector-pattern-subpatterns pattern))))
  574.  
  575. (defmethod unparse-pattern ((pattern class-pattern))
  576. `(class ,(class-pattern-class-name pattern)
  577. ,@(loop for slot-name in (class-pattern-slot-names pattern)
  578. for subpattern in (class-pattern-subpatterns pattern)
  579. collect (list slot-name (unparse-pattern subpattern)))))
  580.  
  581. (defmethod unparse-pattern ((pattern structure-pattern))
  582. `(structure ,(structure-pattern-conc-name pattern)
  583. ,@(loop for slot-name in (structure-pattern-slot-names pattern)
  584. for subpattern in (structure-pattern-subpatterns pattern)
  585. collect (list slot-name (unparse-pattern subpattern)))))
  586.  
  587. (defmethod print-object ((pattern pattern) stream)
  588. ;; NOTE: printing the pattern specifier might not be valid but this
  589. ;; is useful for debugging the process of pattern matching compiler.
  590. (format stream "~S" (unparse-pattern pattern)))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement