|
|
1.1 ! root 1: ! 2: ! 3: ! 4: ! 5: ! 6: ! 7: ! 8: CHAPTER 9 ! 9: ! 10: ! 11: Arrays and Vectors ! 12: ! 13: ! 14: ! 15: ! 16: Arrays and vectors are two means of expressing aggre- ! 17: gate data objects in FRANZ LISP. Vectors may be thought of ! 18: as sequences of data. They are intended as a vehicle for ! 19: user-defined data types. This use of vectors is still ! 20: experimental and subject to revision. As a simple data ! 21: structure, they are similar to hunks and strings. Vectors ! 22: are used to implement closures, and are useful to communi- ! 23: cate with foreign functions. Both of these topics were dis- ! 24: cussed in Chapter 8. Later in this chapter, we describe the ! 25: current implementation of vectors, and will advise the user ! 26: what is most likely to change. ! 27: ! 28: Arrays in FRANZ LISP provide a programmable data struc- ! 29: ture access mechanism. One possible use for FRANZ LISP ! 30: arrays is to implement Maclisp style arrays which are simple ! 31: vectors of fixnums, flonums or general lisp values. This is ! 32: described in more detail in 9.3 but first we will describe ! 33: how array references are handled by the lisp system. ! 34: ! 35: The structure of an array object is given in 1.3.10 and ! 36: reproduced here for your convenience. ! 37: ! 38: ! 39: 8_______________________________________________________________ ! 40: Subpart name Get value Set value Type ! 41: ! 42: 8______________________________________________________________________________________________________________________________ ! 43: access function getaccess putaccess binary, list ! 44: or symbol ! 45: 8_______________________________________________________________ ! 46: auxiliary getaux putaux lispval ! 47: 8_______________________________________________________________ ! 48: data arrayref replace block of contiguous ! 49: set lispval ! 50: 8_______________________________________________________________ ! 51: length getlength putlength fixnum ! 52: 8_______________________________________________________________ ! 53: delta getdelta putdelta fixnum ! 54: 8_______________________________________________________________ ! 55: 7|7|7|7|7|7|7|7|7|7|7|7| ! 56: ! 57: ! 58: ! 59: ! 60: ! 61: ! 62: ! 63: ! 64: ! 65: ! 66: |7|7|7|7|7|7|7|7|7|7|7| ! 67: ! 68: ! 69: ! 70: ! 71: ! 72: ! 73: ! 74: ! 75: ! 76: ! 77: |7|7|7|7|7|7|7|7|7|7|7| ! 78: ! 79: ! 80: ! 81: ! 82: ! 83: ! 84: ! 85: ! 86: ! 87: ! 88: |7|7|7|7|7|7|7|7|7|7|7| ! 89: ! 90: ! 91: ! 92: ! 93: ! 94: ! 95: ! 96: ! 97: ! 98: ! 99: |7|7|7|7|7|7|7|7|7|7|7| ! 100: ! 101: ! 102: ! 103: ! 104: ! 105: ! 106: ! 107: ! 108: ! 109: ! 110: ! 111: ! 112: ! 113: ! 114: ! 115: 9.1. general arrays Suppose the evaluator is told to ! 116: evaluate (_f_o_o _a _b) and the function cell of the symbol ! 117: foo contains an array object (which we will call ! 118: foo_arr_obj). First the evaluator will evaluate and ! 119: stack the values of _a and _b. Next it will stack the ! 120: ! 121: ! 122: 9Arrays and Vectors 9-1 ! 123: ! 124: ! 125: ! 126: ! 127: ! 128: ! 129: ! 130: Arrays and Vectors 9-2 ! 131: ! 132: ! 133: array object foo_arr_obj. Finally it will call the ! 134: access function of foo_arr_obj. The access function ! 135: should be a lexpr[] or a symbol whose function cell ! 136: contains a lexpr. The access function is responsible ! 137: for locating and returning a value from the array. ! 138: The array access function is free to interpret the ! 139: arguments as it wishes. The Maclisp compatible array ! 140: access function which is provided in the standard ! 141: FRANZ LISP system interprets the arguments as sub- ! 142: scripts in the same way as languages like Fortran and ! 143: Pascal. ! 144: ! 145: The array access function will also be called ! 146: upon to store elements in the array. For example, ! 147: (_s_t_o_r_e (_f_o_o _a _b) _c) will automatically expand to (foo ! 148: c a b) and when the evaluator is called to evaluate ! 149: this, it will evaluate the arguments _c, _b and _a. Then ! 150: it will stack the array object (which is stored in the ! 151: function cell of foo) and call the array access func- ! 152: tion with (now) four arguments. The array access ! 153: function must be able to tell this is a store opera- ! 154: tion, which it can do by checking the number of argu- ! 155: ments it has been given (a lexpr can do this very ! 156: easily). ! 157: ! 158: ! 159: ! 160: 9.2. subparts of an array object An array is created ! 161: by allocating an array object with _m_a_r_r_a_y and filling ! 162: in the fields. Certain lisp functions interpret the ! 163: values of the subparts of the array object in special ! 164: ways as described in the following text. Placing ! 165: illegal values in these subparts may cause the lisp ! 166: system to fail. ! 167: ! 168: ! 169: ! 170: 9.2.1. access function The purpose of the access ! 171: function has been described above. The contents of ! 172: the access function should be a lexpr, either a ! 173: binary (compiled function) or a list (interpreted ! 174: function). It may also be a symbol whose function ! 175: cell contains a function definition. This subpart ! 176: is used by _e_v_a_l, _f_u_n_c_a_l_l, and _a_p_p_l_y when evaluating ! 177: array references. ! 178: ! 179: ! 180: ! 181: ____________________ ! 182: 9 []A lexpr is a function which accepts any number of argu- ! 183: ments which are evaluated before the function is called. ! 184: ! 185: ! 186: ! 187: 9 Printed: July 21, 1983 ! 188: ! 189: ! 190: ! 191: ! 192: ! 193: ! 194: ! 195: Arrays and Vectors 9-3 ! 196: ! 197: ! 198: 9.2.2. auxiliary This can be used for any purpose. ! 199: If it is a list and the first element of that list ! 200: is the symbol unmarked_array then the data subpart ! 201: will not be marked by the garbage collector (this ! 202: is used in the Maclisp compatible array package and ! 203: has the potential for causing strange errors if ! 204: used incorrectly). ! 205: ! 206: ! 207: ! 208: 9.2.3. data This is either nil or points to a block ! 209: of data space allocated by _s_e_g_m_e_n_t or _s_m_a_l_l- ! 210: _s_e_g_m_e_n_t. ! 211: ! 212: ! 213: ! 214: 9.2.4. length This is a fixnum whose value is the ! 215: number of elements in the data block. This is used ! 216: by the garbage collector and by _a_r_r_a_y_r_e_f to deter- ! 217: mine if your index is in bounds. ! 218: ! 219: ! 220: ! 221: 9.2.5. delta This is a fixnum whose value is the ! 222: number of bytes in each element of the data block. ! 223: This will be four for an array of fixnums or value ! 224: cells, and eight for an array of flonums. This is ! 225: used by the garbage collector and _a_r_r_a_y_r_e_f as well. ! 226: ! 227: ! 228: ! 229: 9.3. The Maclisp compatible array package ! 230: ! 231: A Maclisp style array is similar to what is known ! 232: as arrays in other languages: a block of homogeneous ! 233: data elements which is indexed by one or more integers ! 234: called subscripts. The data elements can be all fix- ! 235: nums, flonums or general lisp objects. An array is ! 236: created by a call to the function _a_r_r_a_y or *_a_r_r_a_y. ! 237: The only difference is that *_a_r_r_a_y evaluates its argu- ! 238: ments. This call: (_a_r_r_a_y _f_o_o _t _3 _5) sets up an array ! 239: called foo of dimensions 3 by 5. The subscripts are ! 240: zero based. The first element is (_f_o_o _0 _0), the next ! 241: is (_f_o_o _0 _1) and so on up to (_f_o_o _2 _4). The t indi- ! 242: cates a general lisp object array which means each ! 243: element of foo can be any type. Each element can be ! 244: any type since all that is stored in the array is a ! 245: pointer to a lisp object, not the object itself. ! 246: _A_r_r_a_y does this by allocating an array object with ! 247: _m_a_r_r_a_y and then allocating a segment of 15 consecutive ! 248: value cells with _s_m_a_l_l-_s_e_g_m_e_n_t and storing a pointer ! 249: to that segment in the data subpart of the array ! 250: object. The length and delta subpart of the array ! 251: ! 252: ! 253: Printed: July 21, 1983 ! 254: ! 255: ! 256: ! 257: ! 258: ! 259: ! 260: ! 261: Arrays and Vectors 9-4 ! 262: ! 263: ! 264: object are filled in (with 15 and 4 respectively) and ! 265: the access function subpart is set to point to the ! 266: appropriate array access function. In this case ! 267: there is a special access function for two dimensional ! 268: value cell arrays called arrac-twoD, and this access ! 269: function is used. The auxiliary subpart is set to ! 270: (t 3 5) which describes the type of array and the ! 271: bounds of the subscripts. Finally this array object is ! 272: placed in the function cell of the symbol foo. Now ! 273: when (_f_o_o _1 _3) is evaluated, the array access function ! 274: is invoked with three arguments: 1, 3 and the array ! 275: object. From the auxiliary field of the array object ! 276: it gets a description of the particular array. It ! 277: then determines which element (_f_o_o _1 _3) refers to and ! 278: uses arrayref to extract that element. Since this is ! 279: an array of value cells, what arrayref returns is a ! 280: value cell whose value is what we want, so we evaluate ! 281: the value cell and return it as the value of ! 282: (_f_o_o _1 _3). ! 283: ! 284: In Maclisp the call (_a_r_r_a_y _f_o_o _f_i_x_n_u_m _2_5) returns ! 285: an array whose data object is a block of 25 memory ! 286: words. When fixnums are stored in this array, the ! 287: actual numbers are stored instead of pointers to the ! 288: numbers as is done in general lisp object arrays. ! 289: This is efficient under Maclisp but inefficient in ! 290: FRANZ LISP since every time a value was referenced ! 291: from an array it had to be copied and a pointer to the ! 292: copy returned to prevent aliasing[]. Thus t, fixnum ! 293: and flonum arrays are all implemented in the same ! 294: manner. This should not affect the compatibility of ! 295: Maclisp and FRANZ LISP. If there is an application ! 296: where a block of fixnums or flonums is required, then ! 297: the exact same effect of fixnum and flonum arrays in ! 298: Maclisp can be achieved by using fixnum-block and ! 299: flonum-block arrays. Such arrays are required if you ! 300: want to pass a large number of arguments to a Fortran ! 301: or C coded function and then get answers back. ! 302: ! 303: The Maclisp compatible array package is just one ! 304: example of how a general array scheme can be imple- ! 305: mented. Another type of array you could implement ! 306: would be hashed arrays. The subscript could be ! 307: ____________________ ! 308: 9 []Aliasing is when two variables are share the same ! 309: storage location. For example if the copying mentioned ! 310: weren't done then after (_s_e_t_q _x (_f_o_o _2)) was done, the value ! 311: of x and (foo 2) would share the same location. Then should ! 312: the value of (foo 2) change, x's value would change as well. ! 313: This is considered dangerous and as a result pointers are ! 314: never returned into the data space of arrays. ! 315: ! 316: ! 317: ! 318: 9 Printed: July 21, 1983 ! 319: ! 320: ! 321: ! 322: ! 323: ! 324: ! 325: ! 326: Arrays and Vectors 9-5 ! 327: ! 328: ! 329: anything, not just a number. The access function ! 330: would hash the subscript and use the result to select ! 331: an array element. With the generality of arrays also ! 332: comes extra cost; if you just want a simple aggregate ! 333: of (less than 128) general lisp objects you would be ! 334: wise to look into using hunks. ! 335: ! 336: ! 337: ! 338: 9.4. vectors Vectors were invented to fix two ! 339: shortcommings with hunks. They can be longer than 128 ! 340: elements. They also have a tag associated with them, ! 341: which is intended to say, for example, "Think of me as ! 342: an _B_l_o_b_i_t." Thus a vector is an arbitrary sized hunk ! 343: with a property list. ! 344: ! 345: Continuing the example, the lisp kernel may not ! 346: know how to print out or evaluate _b_l_o_b_i_t_s, but this is ! 347: information which will be common to all _b_l_o_b_i_t_s. On ! 348: the other hand, for each individual blobits there are ! 349: particulars which are likely to change, (height, ! 350: weight, eye-color). This is the part that would pre- ! 351: viously have been stored in the individual entries in ! 352: the hunk, and are stored in the data slots of the vec- ! 353: tor. Once again we summarize the structure of a vec- ! 354: tor in tabular form: ! 355: ! 356: ! 357: 8 ________________________________________________ ! 358: Subpart name Get value Set value Type ! 359: ! 360: 8 ________________________________________________________________________________________________ ! 361: datum[_i] vref vset lispval ! 362: 8 ________________________________________________ ! 363: property vprop vsetprop lispval ! 364: vputprop ! 365: 8 ________________________________________________ ! 366: size vsize - fixnum ! 367: 8 ________________________________________________ ! 368: 7 |7|7|7|7|7|7|7| ! 369: ! 370: ! 371: ! 372: ! 373: ! 374: ! 375: |7|7|7|7|7|7|7| ! 376: ! 377: ! 378: ! 379: ! 380: ! 381: ! 382: |7|7|7|7|7|7|7| ! 383: ! 384: ! 385: ! 386: ! 387: ! 388: ! 389: |7|7|7|7|7|7|7| ! 390: ! 391: ! 392: ! 393: ! 394: ! 395: ! 396: |7|7|7|7|7|7|7| ! 397: ! 398: ! 399: ! 400: ! 401: ! 402: ! 403: ! 404: ! 405: Vectors are created specifying size and optional fill ! 406: value using the function (_n_e_w-_v_e_c_t_o_r 'x_size ['g_fill ! 407: ['g_prop]]), or by initial values: (_v_e_c_t_o_r ['g_val ! 408: ...]). ! 409: ! 410: ! 411: ! 412: 9.5. anatomy of vectors There are some technical ! 413: details about vectors, that the user should know: ! 414: ! 415: ! 416: ! 417: ! 418: ! 419: ! 420: ! 421: ! 422: 9 Printed: July 21, 1983 ! 423: ! 424: ! 425: ! 426: ! 427: ! 428: ! 429: ! 430: Arrays and Vectors 9-6 ! 431: ! 432: ! 433: 9.5.1. size The user is not free to alter this. It ! 434: is noted when the vector is created, and is used by ! 435: the garbage collector. The garbage collector will ! 436: coallesce two free vectors, which are neighbors in ! 437: the heap. Internally, this is kept as the number ! 438: of bytes of data. Thus, a vector created by (_v_e_c_- ! 439: _t_o_r 'foo), has a size of 4. ! 440: ! 441: ! 442: ! 443: 9.5.2. property Currently, we expect the property ! 444: to be either a symbol, or a list whose first entry ! 445: is a symbol. The symbols fclosure and structure- ! 446: value-argument are magic, and their effect is ! 447: described in Chapter 8. If the property is a ! 448: (non-null) symbol, the vector will be printed out ! 449: as <symbol>[<size>]. Another case is if the pro- ! 450: perty is actually a (disembodied) property-list, ! 451: which contains a value for the indicator print. ! 452: The value is taken to be a Lisp function, which the ! 453: printer will invoke with two arguments: the vector ! 454: and the current output port. Otherwise, the vector ! 455: will be printed as vector[<size>]. We have vague ! 456: (as yet unimplemented) ideas about similar mechan- ! 457: isms for evaluation properties. Users are cau- ! 458: tioned against putting anything other than nil in ! 459: the property entry of a vector. ! 460: ! 461: ! 462: ! 463: 9.5.3. internal order In memory, vectors start with ! 464: a longword containing the size (which is immediate ! 465: data within the vector). The next cell contains a ! 466: pointer to the property. Any remaining cells (if ! 467: any) are for data. Vectors are handled differently ! 468: from any other object in FRANZ LISP, in that a ! 469: pointer to a vector is pointer to the first data ! 470: cell, i.e. a pointer to the _t_h_i_r_d longword of the ! 471: structure. This was done for efficiency in com- ! 472: piled code and for uniformity in referencing ! 473: immediate-vectors (described below). The user ! 474: should never return a pointer to any other part of ! 475: a vector, as this may cause the garbage collector ! 476: to follow an invalid pointer. ! 477: ! 478: ! 479: ! 480: 9.6. immediate-vectors Immediate-vectors are similar ! 481: to vectors. They differ, in that binary data are ! 482: stored in space directly within the vector. Thus the ! 483: garbage collector will preserve the vector itself (if ! 484: used), and will only traverse the property cell. The ! 485: data may be referenced as longwords, shortwords, or ! 486: ! 487: ! 488: Printed: July 21, 1983 ! 489: ! 490: ! 491: ! 492: ! 493: ! 494: ! 495: ! 496: Arrays and Vectors 9-7 ! 497: ! 498: ! 499: even bytes. Shorts and bytes are returned sign- ! 500: extended. The compiler open-codes such references, ! 501: and will avoid boxing the resulting integer data, ! 502: where possible. Thus, immediate vectors may be used ! 503: for efficiently processing character data. They are ! 504: also useful in storing results from functions written ! 505: in other languages. ! 506: ! 507: ! 508: 8 __________________________________________________ ! 509: Subpart name Get value Set value Type ! 510: ! 511: 8 ____________________________________________________________________________________________________ ! 512: datum[_i] vrefi-byte vseti-byte fixnum ! 513: vrefi-word vseti-word fixnum ! 514: vrefi-long vseti-long fixnum ! 515: 8 __________________________________________________ ! 516: property vprop vsetprop lispval ! 517: vputprop ! 518: 8 __________________________________________________ ! 519: size vsize - fixnum ! 520: vsize-byte fixnum ! 521: vsize-word fixnum ! 522: 8 __________________________________________________ ! 523: 7 |7|7|7|7|7|7|7|7|7|7|7| ! 524: ! 525: ! 526: ! 527: ! 528: ! 529: ! 530: ! 531: ! 532: ! 533: ! 534: |7|7|7|7|7|7|7|7|7|7|7| ! 535: ! 536: ! 537: ! 538: ! 539: ! 540: ! 541: ! 542: ! 543: ! 544: ! 545: |7|7|7|7|7|7|7|7|7|7|7| ! 546: ! 547: ! 548: ! 549: ! 550: ! 551: ! 552: ! 553: ! 554: ! 555: ! 556: |7|7|7|7|7|7|7|7|7|7|7| ! 557: ! 558: ! 559: ! 560: ! 561: ! 562: ! 563: ! 564: ! 565: ! 566: ! 567: |7|7|7|7|7|7|7|7|7|7|7| ! 568: ! 569: ! 570: ! 571: ! 572: ! 573: ! 574: ! 575: ! 576: ! 577: ! 578: ! 579: ! 580: To create immediate vectors specifying size and fill ! 581: data, you can use the functions _n_e_w-_v_e_c_t_o_r_i-_b_y_t_e, ! 582: _n_e_w-_v_e_c_t_o_r_i-_w_o_r_d, or _n_e_w-_v_e_c_t_o_r_i-_l_o_n_g. You can also ! 583: use the functions _v_e_c_t_o_r_i-_b_y_t_e, _v_e_c_t_o_r_i-_w_o_r_d, or ! 584: _v_e_c_t_o_r_i-_l_o_n_g. All of these functions are described in ! 585: chapter 2. ! 586: ! 587: ! 588: ! 589: ! 590: ! 591: ! 592: ! 593: ! 594: ! 595: ! 596: ! 597: ! 598: ! 599: ! 600: ! 601: ! 602: ! 603: ! 604: ! 605: ! 606: ! 607: ! 608: ! 609: ! 610: ! 611: ! 612: 9 Printed: July 21, 1983 ! 613: ! 614: ! 615:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.