Merge branch 'types-experiment'
[cl-tuples.git] / tuples.lisp
blobc51e6710be50e51649c0bb3317c3f6a4dee31ac2
1 ;;;; tuples.lisp
3 (in-package :cl-tuples)
6 (defun def-tuple (type-name)
7 (tuple-expansion-fn type-name :def-tuple))
9 (defun def-tuple-getter (type-name)
10 "Create an access macro such as (vector3d vec) that takes an instance of an array and unpacks it to tuples (aka multiple values)"
11 (tuple-expansion-fn type-name :def-tuple-getter))
13 (defun def-tuple-array-getter (type-name)
14 "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)"
15 (tuple-expansion-fn type-name :def-tuple-array-getter))
18 (defun 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 (defun 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 (defun 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 (defun 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 (defun 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 (defun def-new-tuple (type-name)
39 "Create a function to create an array suitable for holding an individual tuple. eg (new-vector3d)"
40 (tuple-expansion-fn type-name :def-new-tuple))
42 (defun def-tuple-maker (type-name)
43 "Create a function to create an array suitable for holding an individual tuple, and initialise elements from multiple-value tuple. eg (make-vector3d #{ 1.0 2.0 2.0 })"
44 (tuple-expansion-fn type-name :def-tuple-maker))
46 (defun def-tuple-maker* (type-name)
47 "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 ))"
48 (tuple-expansion-fn type-name :def-tuple-maker*))
50 (defun def-tuple-array-maker (type-name)
51 "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)"
52 (tuple-expansion-fn type-name :def-tuple-array-maker))
54 (defun def-tuple-array-dimensions (type-name)
55 "Create a function that will return the number of tuples in the array of array tuples."
56 (tuple-expansion-fn type-name :def-tuple-array-dimensions))
58 (defun def-tuple-setf (type-name)
59 "Create generalised variable macros for tuple of type-name with the given elements."
60 (tuple-expansion-fn type-name :def-tuple-setf))
62 (defun def-tuple-array-setf (type-name)
63 (tuple-expansion-fn type-name :def-tuple-array-setf))
65 (defun def-tuple-map (type-name)
66 "Creates a macro called maps-{tuple-type}-values. Which maps a the
67 function across a list of values, where it expects to recieve the same
68 number of values as the named type.
69 e.g (def-tuple-map vector2d) produces (map-vector2d-values fn &rest values)"
70 (tuple-expansion-fn type-name :def-tuple-map))
73 (defun def-tuple-reduce (type-name)
74 "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)"
75 (tuple-expansion-fn type-name :def-tuple-reduce))
77 (defun document-tuple-type (type-name)
78 `(progn
79 ;; instead of setf, need some form that can use the symbol in the format
80 (setf (documentation ',(make-suffixed-symbol type-name "TUPLE") 'function) "Convert forms to tuple values.")
81 (setf (documentation ',type-name 'function) "Unpack array and convert to tuple values.")
82 (setf (documentation ','(make-suffixed-symbol type-name "AREF") 'function) "Unpack individual tuple from an array of tuples.")
83 (setf (documentation ','(make-adorned-symbol type-name :prefix "WITH") 'function) "Bind members of the tuple values to symbols.")))
86 (defmacro make-tuple-operations (type-name)
87 `(progn
88 (def-tuple ',type-name)
89 (def-tuple-array-dimensions ',type-name)
90 (def-tuple-getter ',type-name)
91 (def-tuple-array-getter ',type-name)
92 (def-with-tuple ',type-name)
93 (def-with-tuple* ',type-name)
94 (def-with-tuple-aref ',type-name)
95 (def-tuple-setter ',type-name)
96 (def-tuple-aref-setter ',type-name)
97 (def-new-tuple ',type-name)
98 (def-tuple-maker ',type-name)
99 (def-tuple-maker* ',type-name)
100 (def-tuple-array-maker ',type-name)
101 (def-tuple-setf ',type-name)
102 (def-tuple-array-setf ',type-name)
103 (def-tuple-map ',type-name)
104 (def-tuple-reduce ',type-name)))
106 ;; possibly we also need a deftype form to describe a tuple array?
108 (defmacro def-tuple-type (tuple-type-name &key tuple-element-type elements)
109 "Create a tuple type. To be used from the top level.
110 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)."
111 `(eval-when (:compile-toplevel :execute :load-toplevel)
112 (make-tuple-symbol ',tuple-type-name ',tuple-element-type ',elements)
113 (make-tuple-operations ,tuple-type-name)
114 (document-tuple-type ',tuple-type-name)))
117 ;; this needs some way of having the names as meaningful symbols
118 ;; also a way of specifying type of return value and non-tuple parameters
119 (defmacro def-tuple-op (name args &body forms)
120 "Macro to define a tuple operator. The name of the operator is
121 name. The operator arguments are determined by args, which is a
122 list of the form ((argument-name argument-type (elements) ..)).
123 Within the forms the tuple value form is bound to the argument-name
124 and the tuple elements are bound to the symbols in the element list"
125 (let ((arg-names (mapcar #'car args))
126 (arg-typenames (mapcar #'cadr args))
127 (arg-elements (mapcar #'caddr args)))
128 `(progn
129 (defmacro ,name ,arg-names
130 ,(arg-expander-fn arg-names arg-typenames arg-elements forms))
131 ,(when (stringp (first forms))
132 `(setf (documentation ',name 'function) ,(first forms))))))