Added tuple-typespec function
[cl-tuples.git] / tuples.lisp
blobfb348ccd0dacf3eb830efc694dfb975cbf689993
1 ;;;; tuples.lisp
3 (in-package :cl-tuples)
6 (defmacro def-tuple (type-name)
7 "Create an alias for values for this tuple.eg (vector3d-tuple #{ 1.0 0.0 0.0 })"
8 (tuple-expansion-fn type-name :def-tuple))
10 (defmacro def-tuple-getter (type-name)
11 "Create an access macro such as (vector3d vec) that takes an instance of an array and unpacks it to tuples (aka multiple values)"
12 (tuple-expansion-fn type-name :def-tuple-getter))
14 (defmacro def-tuple-aref (type-name)
15 "Create a tuple aref macro for unpacking individual tuple from an array of tuples. eg (vector3d-aref up 5) => (values 0.0 1.0 0.0)"
16 (tuple-expansion-fn type-name :def-tuple-aref))
18 (defmacro def-with-tuple (type-name)
19 "Create a macro that can be used to bind members of a value tuple to symbols to symbols e-g (with-vector thing-vec (x y z w) &body forms)"
20 (tuple-expansion-fn type-name :def-with-tuple))
22 (defmacro def-with-tuple* (type-name)
23 "Create a macro that can be used to bind members of the tuples array to symbols to symbols e-g (with-vector* thing-vec #(x y z w) &body forms)"
24 (tuple-expansion-fn type-name :def-with-tuple*))
26 (defmacro def-with-tuple-aref (type-name)
27 "Create a macro that can be used to bind elements of an array of tuples to symbols to symbols e-g (with-vector3d-aref (thing-vec 5 (x y z w)) (+ x y z w))"
28 (tuple-expansion-fn type-name :def-with-tuple-aref))
30 (defmacro def-tuple-setter (type-name)
31 "Creates a tuple-setter for setting a tuple array from a mutiple-value tuple. eg (vector3d-setter up #{ 0.0 1.0 0.0 })"
32 (tuple-expansion-fn type-name :def-tuple-setter))
34 (defmacro def-tuple-aref-setter (type-name)
35 "Create an aref-setter macro for setting an element in an array of tuples from a multiple-value tuple. eg (vector3d-aref-setter up 2 #{ 0.0 1.0 0.0 })"
36 (tuple-expansion-fn type-name :def-tuple-aref-setter))
38 (defmacro def-tuple-vector-push (type-name)
39 (tuple-expansion-fn type-name :def-tuple-vector-push))
41 (defmacro def-tuple-vector-push-extend (type-name)
42 (tuple-expansion-fn type-name :def-tuple-vector-push-extend))
44 (defmacro def-new-tuple (type-name)
45 "Create a function to create an array suitable for holding an individual tuple. eg (new-vector3d)"
46 (tuple-expansion-fn type-name :def-new-tuple))
48 (defmacro def-tuple-maker (type-name)
49 "Create a function to create an array suitable for holding an individual tuple, and initialise elements from multiple-value tuple. eg (make-vector3d (values 1.0 2.0 2.0 ))"
50 (tuple-expansion-fn type-name :def-tuple-maker))
52 (defmacro def-tuple-maker* (type-name)
53 "Create a function to create an array suitable for holding an individual tuple, and initialise elements from array tuple. eg (make-vector3d* #( 1.0 2.0 2.0 ))"
54 (tuple-expansion-fn type-name :def-tuple-maker*))
56 (defmacro def-tuple-array-maker (type-name)
57 "Create a function to create an array suitable for holding an number of individual tuples. ie an array of array tuples. eg (make-vector3d-array 5 :adjustable t)"
58 (tuple-expansion-fn type-name :def-tuple-array-maker))
60 (defmacro def-tuple-array-dimensions (type-name)
61 "Create a function that will return the number of tuples in the array of array tuples."
62 (tuple-expansion-fn type-name :def-tuple-array-dimensions))
64 (defmacro def-tuple-setf (type-name)
65 "Create generalised variable macros for tuple of type-name with the given elements."
66 (tuple-expansion-fn type-name :def-tuple-setf))
68 (defmacro def-tuple-array-setf (type-name)
69 (tuple-expansion-fn type-name :def-tuple-array-setf))
71 (defmacro def-tuple-map (type-name)
72 "Creates a macro called maps-{tuple-type}-values. Which maps a the
73 function across a list of values, where it expects to recieve the same
74 number of values as the named type.
75 e.g (def-tuple-map vector2d) produces (map-vector2d-values fn &rest values)"
76 (tuple-expansion-fn type-name :def-tuple-map))
78 (defmacro def-tuple-reduce (type-name)
79 "Creates a macro called reduce-{tuple-type}-values. Which applies the reduction function to each value in it's second parameter, where it expects to recieve the same number of values as the named type. e.g (def-tuple-reduce vector2d) produces (reduce-vector2d-values fn tuples)"
80 (tuple-expansion-fn type-name :def-tuple-reduce))
82 (defun document-tuple-type (type-name)
83 `(progn
84 ;; instead of setf, need some form that can use the symbol in the format
85 (setf (documentation ',(make-suffixed-symbol type-name "TUPLE") 'function) "Convert forms to tuple values.")
86 (setf (documentation ',type-name 'function) "Unpack array and convert to tuple values.")
87 (setf (documentation ','(make-suffixed-symbol type-name "AREF") 'function) "Unpack individual tuple from an array of tuples.")
88 (setf (documentation ','(make-adorned-symbol type-name :prefix "WITH") 'function) "Bind members of the tuple values to symbols.")))
91 (defmacro make-tuple-operations (type-name)
92 `(progn
93 (def-tuple ,type-name)
94 (def-tuple-array-dimensions ,type-name)
95 (def-tuple-getter ,type-name)
96 (def-tuple-aref ,type-name)
97 (def-with-tuple ,type-name)
98 (def-with-tuple* ,type-name)
99 (def-with-tuple-aref ,type-name)
100 (def-tuple-setter ,type-name)
101 (def-tuple-aref-setter ,type-name)
102 (def-tuple-vector-push ,type-name)
103 (def-tuple-vector-push-extend ,type-name)
104 (def-new-tuple ,type-name)
105 (def-tuple-maker ,type-name)
106 (def-tuple-maker* ,type-name)
107 (def-tuple-array-maker ,type-name)
108 (def-tuple-setf ,type-name)
109 (def-tuple-array-setf ,type-name)
110 (def-tuple-map ,type-name)
111 (def-tuple-reduce ,type-name)))
113 (defmacro export-tuple-operations (type-name)
114 `(progn
115 ,@(loop for kw in *tuple-expander-keywords* collect `(export (tuple-symbol (quote ,type-name) ,kw)))))
118 ;; possibly we also need a deftype form to describe a tuple array?
120 (defmacro def-tuple-type (tuple-type-name &key tuple-element-type elements)
121 "Create a tuple type. To be used from the top level.
122 For example (def-tuple-type vector3d single-float (x y z)) will create several macros and functions. Firstly, the accessor functions (vector3d array) (vector3d-aref array index). Secondly, the context macros (with-vector3d tuple (element-symbols) forms..) and (with-vector3d-array tuple (element-symbols) index forms..), thirdly the constructors (new-vector3d) and (make-vector3d tuple), (make-vector3d-array dimensions &key adjustable fill-pointer), forthly generalised access as in (setf (vector3d array) tuple) and (setf (vector3d-aref array) index tuple), fiftly and finally, the funcional macros (map-vector3d fn tuples..) (reduce-vector3d fn tuple)."
123 `(eval-when (:compile-toplevel :execute :load-toplevel)
124 (make-tuple-symbol ',tuple-type-name ',tuple-element-type ',elements)
125 (make-tuple-operations ,tuple-type-name)
126 (document-tuple-type ',tuple-type-name)))
129 ;; this needs some way of having the names as meaningful symbols
130 ;; also a way of specifying type of return value and non-tuple parameters
131 (defmacro def-tuple-op (name args &body forms)
132 "Macro to define a tuple operator. The name of the operator is
133 name. The operator arguments are determined by args, which is a
134 list of the form ((argument-name argument-type (elements) ..)).
135 Within the forms the tuple value form is bound to the argument-name
136 and the tuple elements are bound to the symbols in the element list"
137 (let ((arg-names (mapcar #'car args))
138 (arg-typenames (mapcar #'cadr args))
139 (arg-elements (mapcar #'caddr args)))
140 `(progn
141 (defmacro ,name ,arg-names
142 ,(arg-expander-fn arg-names arg-typenames arg-elements forms))
143 ,(when (stringp (first forms))
144 `(setf (documentation ',name 'function) ,(first forms))))))