{Begin Chapter Arrays}
{Title Arrays}
{Text

{index *PRIMARY* Arrays}

An array in Interlisp is an object representing a one-dimensional vector of objects.  Arrays are generally created by the function {fn ARRAY}.


{FnDef {Name ARRAY} {Args SIZE TYPE INIT ORIG {anonarg}}
{Text
Creates and returns a new array capable of containing {arg SIZE} objects of type {arg TYPE}.  If {arg TYPE} is {lisp NIL}, the array can contain any arbitrary Lisp datum.  In general, {arg TYPE} may be any of the various field specifications which are legal in {lisp DATATYPE} declarations (see {PageRef (Record Type) DATATYPE}): {lisp POINTER}, {lisp FIXP}, {lisp FLOATP}, {lisp (BITS {arg N})}, etc.  The implementation will, if necessary, choose an "enclosing" type if the given one is not supported; for example, an array of {lisp (BITS 3)} may be represented by an array of {lisp (BITS 8)}.

{arg INIT} is the initial value in each element of the new array.  If not specified, the array elements will be initialized with 0 (for number arrays) or {lisp NIL} (all other types).

Arrays can have either 0-origin or 1-origin indexing, as specified by the {arg ORIG} argument; if {arg ORIG} is not specified, the default is 1. 

Note:  Arrays of type {lisp FLOATP} are stored unboxed.  This increases the space and time efficiency of {lisp FLOATP} arrays.  Users who want to use boxed floating point numbers should use an array of type {lisp POINTER} instead of {lisp FLOATP}.
}}


{index *PRIMARY* ARRAYP Fn}
{FnDef {FnName ARRAYP} {FnArgs X}
{Text
Returns {arg X} if {arg X} is an array,{index arrays} {lisp NIL} otherwise.

Note:  In some implementations of Interlisp (but not Interlisp-D), {fn ARRAYP} may also return {arg X} if it is of type {lisp CCODEP} or {lisp HARRAYP}.
}}



{FnDef {FnName ELT} {FnArgs ARRAY N}
{Text
Returns the {arg N}th element of the array {arg ARRAY}.

Generates the error {lisp ARG NOT ARRAY}{index ARG NOT ARRAY Error} if {arg ARRAY} is not an array.  Generates the error {lisp ILLEGAL ARG}{index ILLEGAL ARG Error} if {arg N} is out of bounds.
}}


{FnDef {FnName SETA} {FnArgs ARRAY N V}
{Text
Sets the {arg N}th element of the array {arg ARRAY} to {arg VAL}, and returns {arg VAL}.

Generates the error {lisp ARG NOT ARRAY}{index ARG NOT ARRAY Error} if {arg ARRAY} is not an array.  Generates the error {lisp ILLEGAL ARG}{index ILLEGAL ARG Error} if {arg N} is out of bounds.  Can generate the error {lisp NON-NUMERIC ARG}{index NON-NUMERIC ARG Error} if {arg ARRAY} is an array whose {fn ARRAYTYP} is {lisp FIXP} or {lisp FLOATP} and {arg VAL} is non-numeric.
}}


{FnDef {FnName ARRAYTYP} {FnArgs ARRAY}
{Text
Returns the type of the elements in the array {arg ARRAY}, a value corresponding to the second argument to {fn ARRAY}.

Note:  If {fn ARRAY} coerced the array type as described above, {fn ARRAYTYP} will return the {it new} type.  For example, {lisp (ARRAYTYP (ARRAY 10 '(BITS 3)))} will return {lisp BYTE} in Interlisp-D, and {lisp FIXP} in Interlisp-10.
}}


{FnDef {FnName ARRAYSIZE} {FnArgs ARRAY}
{Text
Returns the size of array {arg ARRAY}. Generates the error, {lisp ARG NOT ARRAY},{index ARG NOT ARRAY Error} if {arg ARRAY} is not an array.
}}


{FnDef {FnName ARRAYORIG} {FnArgs ARRAY}
{Text
Returns the origin of array {arg ARRAY}, which may be 0 or 1.  Generates an error, {lisp ARG NOT ARRAY}, if {arg ARRAY} is not an array.{index ARG NOT ARRAY Error}
}}


{FnDef {FnName COPYARRAY} {FnArgs ARRAY}
{Text
Returns a new array of the same size and type as {arg ARRAY}, and with the same contents as {arg ARRAY}.  Generates an {lisp ARG NOT ARRAY}{index ARG NOT ARRAY Error} error, if {arg ARRAY} is not an array.
}}



{Begin Note}
Back compatibility note:  In Interlisp-10, where hash arrays are a type of array, COPYARRAY will copy hash arrays, but it is better to use REHASH.   ---lmm
Documentation should not say ANYTHING about applying COPYARRAY or any other functions in this section to non-arrays.  If it works, fine --- but don't commit yourself to one implementation of hash arrays  ---mjs
{End Note}

{Begin Comment Interlisp-10 specific}
I removed the following section on Interlisp-10 arrays. They are covered adequately in the above (edited) discussion on ARRAYS in general. ---lmm

This is what it used to say:

Interlisp-10 and Interlisp-Vax have a more primitive array facility than the other implementations of Interlisp.  In Interlisp-10, arrays are partitioned into four sections: a header, a section containing unboxed numbers, a section containing list cells (each with a {fn CAR} and {fn CDR}), and a section containing relocation information. The last three sections can each be of arbitrary length (including 0); the header is two words long and contains the length of the other sections.  The unboxed number region of an array is used to store 36 bit quantities that are not Interlisp pointers, and therefore are not to be chased during garbage collections, e.g. machine instructions.  The relocation informaion is used when the array contains the definition of a compiled function, and specifies which locations in the {it unboxed} region of the array must be changed if the array is moved during a garbage collection.


{fn ARRAY} returns an "array pointer" to the beginning of the array, but it is also possible to create a pointer into the middle of an array.  {fn ARRAYP} will accept a pointer into the middle of an array, but  {fn ELT}, {fn SETA}, {fn ELTD}, and {fn SETD} generate an error, if {arg A} is not an array pointer to the beginning of an array.


Array-pointers print as {lisp #{arg NNNN}}, where {arg NNNN} is the octal representation of the pointer.  Note that {lisp #{arg NNNN}} will be read as a literal atom, and not an array pointer.  

The following functions are used to manipulate Interlisp-10 arrays:

	
{FnDef {FnName ARRAY} {FnArgs N P V}
{Text
Allocates a block of {arg N}+2 words, of which the first two are header information.  The next {arg P} ({LE} {arg N}) words contain unboxed numbers, and are initialized to unboxed 0.  The last {arg N}-{arg P} ({GE} 0) words are list cells; both {fn CAR} and {fn CDR} are available for storing information, and each is initialized to {arg V}.  If {arg P} is {lisp NIL}, 0 is used (i.e., an array containing all Interlisp pointers).
{fn ARRAY} returns an "array pointer" to the array.

If sufficient space is not available for the array, a garbage collection of array space is initiated.  If this is unsuccessful in obtaining sufficient space, an error is generated, {lisp ARRAYS FULL}.
}}


{FnDef {FnName ELT} {FnArgs A N}
{Text
Returns the {arg N}th element of the array {arg A}.  {lisp (ELT {arg A} 1)} is the first element of the array (actually corresponds to the 3rd cell because of the 2 word header).

If {arg N} corresponds to the unboxed number region of {arg A}, {fn ELT} returns the full 36 bit word as a boxed integer.  If {arg N} corresponds to the list cell region of {arg A}, {fn ELT} returns the {fn CAR} of the corresponding element.
}}


{FnDef {FnName SETA} {FnArgs A N V}
{Text
Sets the {arg N}th element of the array {arg A} to {arg V}.
If {arg N} corresponds to the unboxed number region of {arg A}, {arg V} must be a number, and is unboxed and stored as a full 36 bit word into the {arg N}th element of {arg A}.  If {arg N} corresponds to the list cell region of {arg A}, {arg V} replaces the {fn CAR} of the {arg N}th element.  {fn SETA} returns {arg V}.
}}


{FnDef {FnName ELTD} {FnArgs A N}
{Text
Same as {fn ELT} for the unboxed number region of {arg A}, but returns the {fn CDR} of the {arg N}th element, if {arg N} corresponds to the list cell region of {arg A}.
}}


{FnDef {FnName SETD} {FnArgs A N V}
{Text
Same as {fn SETA} for the unboxed number region of {arg A}, but sets the {fn CDR} half of the {arg N}th element, if {arg N} corresponds to the list cell
region of {arg A}.  {fn SETD} returns {arg V}.
}}




{FnDef {FnName ARRAYTYP} {FnArgs A}
{Text
Returns the number of unboxed number words of array {arg A}.  This value corresponds to the second argument to {fn ARRAY}.
}}


{FnDef {FnName ARRAYP} {FnArgs X}
{Text
Returns {arg X} if {arg X} is an array pointer, otherwise {lisp NIL}.  No check is made to ensure that {arg X} actually addresses the {it beginning} of an array.
}}


{FnDef {FnName ARRAYBEG} {FnArgs A}
{Text
If {arg A} is a pointer into the middle of an array, returns the pointer to its beginning.  Otherwise returns {lisp NIL}.

{note will it return NIL if A is already a pointer to the beginning of the array??}
}}

{FnDef {FnName ARRAYORIG} {FnArgs A}
{Text
Returns 1.  A dummy function provided for compatibility with other Interlisp arrays.
}}

{End Comment Interlisp-10 Specific}




}{End Chapter Arrays}