20 :apply-unwrapped-values
26 ((value :accessor mal-value
:initarg
:value
)
27 (meta :accessor mal-meta
:initarg
:meta
)
28 (type :accessor mal-type
:initarg
:type
)))
30 (defmethod print-object ((obj mal-type
) out
)
31 (with-slots (value type meta
) obj
32 (format out
"#<mal ~a: ~a (~a)>" type value meta
)))
34 (defun add-mal-meta (value meta
)
35 (setf (slot-value value
'meta
) meta
)
38 (defun mal-value= (value1 value2
)
39 (and (equal (mal-type value1
) (mal-type value2
))
40 (equal (mal-value value1
) (mal-value value2
))))
42 (defun hash-mal-value (value)
43 (sxhash (mal-value value
)))
45 #+sbcl
(sb-ext:define-hash-table-test mal-value
= hash-mal-value
)
46 #+clisp
(ext:define-hash-table-test mal-value
= mal-value
= hash-mal-value
)
48 (defmacro define-mal-type
(type)
49 ;; Create a class for given type and a convenience constructor and also export
51 (let ((name (intern (string-upcase (concatenate 'string
53 (symbol-name type
)))))
54 (constructor (intern (string-upcase (concatenate 'string
56 (symbol-name type
))))))
57 `(progn (defclass ,name
(mal-type)
58 ((type :accessor mal-type
62 (defun ,constructor
(value &optional meta
)
68 (export ',constructor
))))
70 (define-mal-type number
)
71 (define-mal-type symbol
)
72 (define-mal-type keyword
)
73 (define-mal-type string
)
74 (define-mal-type boolean
)
75 (define-mal-type list
)
76 (define-mal-type vector
)
77 (define-mal-type hash-map
)
81 (defvar any
"any-type")
83 (defmacro switch-mal-type
(ast &body forms
)
84 `(let ((type (types:mal-type
,ast
)))
86 ,@(mapcar (lambda (form)
87 (list (if (or (equal (car form
) t
)
88 (equal (car form
) 'any
))
90 (list 'equal
(list 'quote
(car form
)) 'type
))