{Begin SubSec 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}.

{Begin Note}
used to say about input and output syntax. Arrays print out differently in different implementations. Input syntax is via HPRINT:

|{bracket  Y<size> <type> <orig> elements }

{End Note}


{index *PRIMARY* ARRAY Fn}

{FnDef {Name ARRAY} {Args SIZE TYPE INIT ORIG}
{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 Tag RecordDeclarationDATATYPE}): {lisp POINTER}, {lisp FIXP}, {lisp FLOATP}, {lisp (BITS {arg N})}. 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)} (in Interlisp-D) or {lisp FIXP} (in Interlisp-10).

For backward compatibility with Interlisp-10 arrays, {arg TYPE} can be 0 (meaning to create an array of type {lisp POINTER} or {arg SIZE} (meaning an array of type {lisp FIXP}).

{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).

In Interlisp-D and -VAX, 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. 

Interlisp-10 and -Jericho require that {arg ORIG}=1.
}}


{index *PRIMARY* ELT Fn}

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

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


{index *PRIMARY* SETA Fn}

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

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 A} is an array whose {fn ARRAYTYP} is {lisp FIXP} or {lisp FLOATP} and {arg N} is non-numeric.
}}


{index *PRIMARY* ARRAYTYP Fn}

{FnDef {FnName ARRAYTYP} {FnArgs A}
{Text
Returns 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 A}
{Text
Returns the size of array {arg A}. Generates the error, {lisp ARG NOT ARRAY},{index ARG NOT ARRAY Error} if {arg A} is not an array.
}}


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



{FnDef {FnName COPYARRAY} {FnArgs A}
{Text
Returns a new array of the same size and type as {arg A}, and with the same contents as {arg A}.  Generates an {lisp ARG NOT ARRAY}{index ARG NOT ARRAY Error} error, if {arg A} 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 Note}
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 Note}



{Begin Note}
Date: 4 June 1981 4:35 pm PDT (Thursday)
From: Masinter.PA
Subject: (BBN meeting notes) ARRAYS

Interlisp-D has some extensions to the Interlisp-10 style of arrays. Interlisp-Jericho has imported (or will) Interlisp-D's style of ARRAYs. BBN agreed to implement the extensions in Interlisp-10 in a way which is also backward compatible.

(Note that Interlisp-Jericho has an interesting scheme for implementing DOUBLEPOINTER arrays where the ELTD/SETD portion of the array is stored offline at first reference.)

We are agreed that the specification for ARRAY[n, typ, init, orig] is that "typ" can be any element which is a valid DATATYPE field descriptor; including POINTER, BYTE, (BITS n), FLOATP, FIXP. Implementations are free to "coerce" arguments to "higher" level types, e.g. (BITS n) -> FIXP.

"Mixed" arrays with part pointers and part numbers need not be supported.

Date: 4 Jun 1981 1951-EDT
Sender: GREENFELD at BBND
Subject: Re: (BBN meeting notes) ARRAYS

on the ARRAY function, one point still not agreed is whether to allow ORIGINs other than 1.  While Interlisp-D adds this feature, Interlisp-Jericho explicitly decided not to.

the ELTD/SETD scheme is a simple package that is machine-independent, and is in our LISPUSERS.
{End Note}


}{End subsec Arrays}