|
|
1.1 root 1: .\" Copyright (c) 1980 Regents of the University of California.
2: .\" All rights reserved. The Berkeley software License Agreement
3: .\" specifies the terms and conditions for redistribution.
4: .\"
5: .\" @(#)ch9.n 6.2 (Berkeley) 5/14/86
6: .\"
7: ." $Header: ch9.n 1.4 83/07/21 21:08:57 sklower Exp $
8: .Lc Arrays\ and\ Vectors 9
9: .pp
10: Arrays and vectors are two means of expressing aggregate
11: data objects in
12: .Fr .
13: Vectors may be thought of as sequences of data.
14: They are intended as a vehicle for user-defined
15: data types.
16: This use of vectors is still experimental and subject
17: to revision.
18: As a simple data structure, they are similar to
19: hunks and strings.
20: Vectors are used to implement closures,
21: and are useful to communicate with foreign functions.
22: Both of these topics were discussed in Chapter 8.
23: Later in this chapter,
24: we describe the current implementation of vectors, and will
25: advise the user what is most likely to change.
26: .pp
27: Arrays in
28: .Fr
29: provide a programmable data structure access mechanism.
30: One possible use for
31: .Fr
32: arrays is to implement Maclisp style arrays which are simple vectors
33: of fixnums, flonums or general lisp values.
34: This is described in more detail in \(sc9.3 but first
35: we will describe how array references are handled by
36: the lisp system.
37: .pp
38: The structure of an array object is given in \(sc1.3.10 and reproduced here
39: for your convenience.
40: .(b
41: .TS
42: box center ;
43: c | c | c | c .
44: Subpart name Get value Set value Type
45:
46: =
47: access function getaccess putaccess binary, list
48: or symbol
49: _
50: auxiliary getaux putaux lispval
51: _
52: data arrayref replace block of contiguous
53: set lispval
54: _
55: length getlength putlength fixnum
56: _
57: delta getdelta putdelta fixnum
58: .TE
59: .)b
60: .sh 2 "general arrays" \n(ch 1
61: Suppose the evaluator is told to evaluate \fI(foo\ a\ b)\fP
62: and the function cell of the symbol foo contains an array object
63: (which we will call foo_arr_obj).
64: First the evaluator will evaluate and stack the values of
65: .i a
66: and
67: .i b .
68: Next it will stack the array object foo_arr_obj.
69: Finally it will call the access function of foo_arr_obj.
70: The access function should be a lexpr\*[\(dg\*]
71: or a symbol whose
72: function cell contains a lexpr.
73: .(f
74: \*[\(dg\*]A lexpr is a function which accepts any number of arguments
75: which are evaluated before the function is called.
76: .)f
77: The access function is responsible for locating and returning
78: a value from the array.
79: The array access function is free to interpret the arguments as it wishes.
80: The Maclisp compatible array access function which is provided
81: in the standard
82: .Fr
83: system interprets the arguments as subscripts in the same way as
84: languages like Fortran and Pascal.
85: .pp
86: The array access function will also be called upon to store elements in
87: the array.
88: For example, \fI(store\ (foo\ a\ b)\ c)\fP
89: will automatically expand to (foo c a b) and when the evaluator is called
90: to evaluate this, it will evaluate the arguments
91: .i c ,
92: .i b
93: and
94: .i a .
95: Then it will
96: stack the array object (which is stored
97: in the function cell of foo) and call the array access function
98: with (now) four arguments.
99: The array access function must be able to tell this is a store operation,
100: which it can do by checking the number of arguments it has been
101: given (a lexpr can do this very easily).
102: .sh 2 "subparts of an array object"
103: An array is created by allocating an
104: array object with
105: .i marray
106: and filling in the fields.
107: Certain lisp functions interpret the values of the subparts
108: of the array object in special
109: ways as described in the following text.
110: Placing illegal values in these subparts may cause
111: the lisp system to fail.
112: .sh 3 "access function"
113: The purpose of the access function has been described above.
114: The contents of the access function should be a lexpr,
115: either a binary (compiled function) or a list (interpreted function).
116: It may also be a symbol whose function cell contains a function
117: definition.
118: This subpart
119: is used by
120: .i eval ,
121: .i funcall ,
122: and
123: .i apply
124: when evaluating array references.
125: .sh 3 auxiliary
126: This can be used for any purpose. If it is a list and the first element
127: of that list is the symbol unmarked_array then the data subpart will
128: not be marked by the garbage collector (this is used in the Maclisp
129: compatible array package and has the potential for causing strange errors
130: if used incorrectly).
131: .sh 3 data
132: This is either nil or points to a block of data space allocated by
133: .i segment
134: or
135: .i small-segment.
136: .sh 3 length
137: This is a fixnum whose value is the number of elements in the
138: data block. This is used by the garbage collector and by
139: .i arrayref
140: to determine if your index is in bounds.
141: .sh 3 delta
142: This is a fixnum whose value is the number of bytes in each element of
143: the data block.
144: This will be four for an array of fixnums or value cells, and eight
145: for an array of flonums.
146: This is used by the garbage collector and
147: .i arrayref
148: as well.
149: .sh 2 "The Maclisp compatible array package"
150: .pp
151: A Maclisp style array is similar to what is known as arrays in other
152: languages: a block of homogeneous data elements which
153: is indexed by one or more integers called subscripts.
154: The data elements can be all fixnums, flonums or general lisp objects.
155: An array is created by a call to the function
156: .i array
157: or \fI*array\fP.
158: The only difference is that
159: .i *array
160: evaluates its arguments.
161: This call:
162: .i "(array foo t 3 5)"
163: sets up an array called foo of dimensions 3 by 5.
164: The subscripts are zero based.
165: The first element is \fI(foo\ 0\ 0)\fP, the next is \fI(foo\ 0\ 1)\fP
166: and so on up to \fI(foo\ 2\ 4)\fP.
167: The t indicates a general lisp object array which means each element of
168: foo can be any type.
169: Each element can be any type since all that is stored in the array is
170: a pointer to a lisp object, not the object itself.
171: .i Array
172: does this by allocating an array object
173: with
174: .i marray
175: and then allocating a segment of 15 consecutive value cells with
176: .i small-segment
177: and storing a pointer to that segment in the data subpart of the array
178: object.
179: The length and delta subpart of the array object are filled in (with 15
180: and 4 respectively) and the access function subpart is set to point to
181: the appropriate array access function.
182: In this case there is a special access function for two dimensional
183: value cell arrays called arrac-twoD, and this access function is used.
184: The auxiliary subpart is set to (t\ 3\ 5) which describes the type of array
185: and the bounds of the subscripts.
186: Finally this array object is placed in the function cell of the symbol foo.
187: Now when
188: .i "(foo 1 3)"
189: is evaluated, the array access function is invoked with three arguments:
190: 1, 3 and the array object. From the auxiliary field of the
191: array object it gets a description of the particular array.
192: It then determines which element \fI(foo\ 1\ 3)\fP refers to and
193: uses arrayref to extract that element.
194: Since this is an array of value cells, what arrayref returns is a
195: value cell whose value is what we want, so we evaluate the value cell
196: and return it as the value of \fI(foo\ 1\ 3)\fP.
197: .pp
198: In Maclisp the call \fI(array\ foo\ fixnum\ 25)\fP
199: returns an array whose data object is a block of 25 memory words.
200: When fixnums are stored in this array, the actual numbers are
201: stored instead of pointers to the numbers as is done in general lisp
202: object arrays.
203: This is efficient under Maclisp but inefficient in
204: .Fr
205: since every time a value was referenced from an array it had to be copied
206: and a pointer to the copy returned to prevent aliasing\*[\(dg\*].
207: .(f
208: \*[\(dg\*]Aliasing is when two variables are share the same storage location.
209: For example if the copying mentioned weren't done then after
210: \fI(setq\ x\ (foo\ 2))\fP was done, the value of x and
211: (foo\ 2) would share the same
212: location.
213: Then should the value of (foo\ 2) change, x's value would change as well.
214: This is considered dangerous and as a result pointers are never returned
215: into the data space of arrays.
216: .)f
217: Thus t, fixnum and flonum arrays are all implemented in the same
218: manner.
219: This should not affect the compatibility of Maclisp
220: and
221: .Fr .
222: If there is an application where a block of fixnums or flonums is required,
223: then the exact same effect of fixnum and flonum arrays in Maclisp
224: can be achieved by using fixnum-block and flonum-block arrays.
225: Such arrays are required if you want to pass a large number of arguments to a
226: Fortran or C coded function and then get answers back.
227: .pp
228: The Maclisp compatible array package is
229: just one example of how a general array scheme can be implemented.
230: Another type of array you could implement would be hashed arrays.
231: The subscript could be anything, not just a number.
232: The access function would hash the subscript and use the result to
233: select an array element.
234: With the generality of arrays also comes extra cost; if you just
235: want a simple aggregate of (less than 128) general lisp objects
236: you would be wise to look into using hunks.
237: .sh 2 vectors
238: Vectors were invented to fix two shortcommings with hunks.
239: They can be longer than 128 elements. They also have a
240: tag associated with them, which is intended to say, for example,
241: "Think of me as an \fIBlobit\fP." Thus a \fBvector\fP
242: is an arbitrary sized hunk with a property list.
243: .pp
244: Continuing the example,
245: the lisp kernel may not know how to print out
246: or evaluate \fIblobits\fP, but this is information which will
247: be common to all \fIblobits\fP. On the other hand, for each
248: individual blobits there are particulars which are likely to change,
249: (height, weight, eye-color). This is the part that would
250: previously have been stored in the individual entries in the hunk,
251: and are stored in the data slots of the vector.
252: Once again we summarize the structure of a vector in tabular form:
253: .(b
254: .TS
255: box center ;
256: c | c | c | c .
257: Subpart name Get value Set value Type
258:
259: =
260: datum[\fIi\fP] vref vset lispval
261: _
262: property vprop vsetprop lispval
263: vputprop
264: _
265: size vsize \- fixnum
266: .TE
267: .)b
268: Vectors are created specifying size and optional fill value using the
269: function (\fInew-vector\fP 'x_size ['g_fill ['g_prop]]), or by
270: initial values: (\fIvector\fP ['g_val ...]).
271: .sh 2 "anatomy of vectors"
272: There are some technical details about vectors, that the user should
273: know:
274: .sh 3 size
275: The user is not free to alter this. It is noted when the vector
276: is created, and is used by the garbage collector. The garbage
277: collector will coallesce two free vectors, which are neighbors
278: in the heap. Internally, this is kept as the number of bytes
279: of data. Thus, a vector created by (\fIvector\fP 'foo), has a
280: size of 4.
281: .sh 3 property
282: Currently, we expect the property to be either a symbol, or a list
283: whose first entry is a symbol. The symbols \fBfclosure\fP and
284: \fBstructure-value-argument\fP are magic, and their effect is described in
285: Chapter 8. If the property is a (non-null) symbol, the vector
286: will be printed out as <symbol>[<size>].
287: Another case is if the property is actually a (disembodied) property-list, which
288: contains a value for the indicator \fBprint\fP.
289: The value is taken to be a Lisp function, which the printer
290: will invoke with two arguments: the vector and the current output port.
291: Otherwise, the vector will be printed as vector[<size>].
292: We have vague (as yet unimplemented) ideas
293: about similar mechanisms for evaluation properties.
294: Users are cautioned against putting anything other than nil
295: in the property entry of a vector.
296: .sh 3 "internal order"
297: In memory, vectors start with a longword containing the size
298: (which is immediate data within the vector).
299: The next cell contains a pointer to the property.
300: Any remaining cells (if any) are for data.
301: Vectors are handled differently from any other object in
302: .Fr,
303: in that a pointer to a vector is pointer to the first data
304: cell, i.e. a pointer to the \fIthird\fP longword of the structure.
305: This was done for efficiency in compiled code and for uniformity
306: in referencing immediate-vectors (described below).
307: The user should never return a pointer to any other part
308: of a vector, as this may cause the garbage collector to follow an
309: invalid pointer.
310: .sh 2 "immediate-vectors"
311: Immediate-vectors are similar to vectors. They differ, in
312: that binary data are stored in space directly within the vector.
313: Thus the garbage collector will preserve the vector itself (if used),
314: and will only traverse the property cell.
315: The data may be referenced as longwords, shortwords, or even bytes.
316: Shorts and bytes are returned sign-extended.
317: The compiler open-codes such references,
318: and will avoid boxing the resulting integer data, where possible.
319: Thus, immediate vectors may be used for efficiently processing
320: character data.
321: They are also useful in storing results from functions written
322: in other languages.
323: .(b
324: .TS
325: box center ;
326: c | c | c | c .
327: Subpart name Get value Set value Type
328:
329: =
330: datum[\fIi\fP] vrefi-byte vseti-byte fixnum
331: vrefi-word vseti-word fixnum
332: vrefi-long vseti-long fixnum
333: _
334: property vprop vsetprop lispval
335: vputprop
336: _
337: size vsize \- fixnum
338: vsize-byte fixnum
339: vsize-word fixnum
340: .TE
341: .)b
342: To create immediate vectors specifying size and fill data,
343: you can use the functions
344: \fInew-vectori-byte\fP,
345: \fInew-vectori-word\fP,
346: or \fInew-vectori-long\fP.
347: You can also use the functions
348: \fIvectori-byte\fP,
349: \fIvectori-word\fP,
350: or \fIvectori-long\fP.
351: All of these functions are described in
352: chapter 2.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.