;;;arrays.mhtml: -*- Meta-HTML -*-  DESCRIPTIVE TEXT.
;;;
;;; Copyright (c) 1999 Brian J. Fox
;;; Author: Brian J. Fox (bfox@ai.mit.edu) Mon Jan 11 12:41:24 1999.

;;; <array-size>, <array-member>, <array-append>, and <array-add-unique>
;;; are now all written as primitives.

<defun array-union array1 array2>
  ;;; DOC_SECTION (ARRAYS)
  ;;; Return the union of the two arrays represented by the variables
  ;;; <var array1> and <var array2>.
  ;;; For example:
  ;;; <complete-example>
  ;;; <set-var a1[0]=0 a1[1]=1 a1[2]=2 a2[0]=2 a2[1]=3 a2[2]=4>
  ;;; <array-union a1 a2>
  ;;; </complete-example>
  <parser::canonicalize-var array1>
  <parser::canonicalize-var array2>
  <foreach element <get-var-once array1>>
    <array-add-unique <get-var-once element> results>
  </foreach>
  <foreach element <get-var-once array2>>
    <array-add-unique <get-var-once element> results>
  </foreach>
  <get-var-once results[]>
</defun>

<defun array-intersection array1 array2>
  ;;; DOC_SECTION (ARRAYS)
  ;;; Return the intersection of the two arrays represented by the variables
  ;;; <var array1> and <var array2>.
  ;;; For example:
  ;;; <complete-example>
  ;;; <set-var a1[0]=0 a1[1]=1 a1[2]=2 a2[0]=2 a2[1]=3 a2[2]=4>
  ;;; <array-intersection a1 a2>
  ;;; </complete-example>
  <parser::canonicalize-var array1>
  <parser::canonicalize-var array2>
  <foreach element <get-var-once array1>>
    <if <array-member <get-var-once element> <get-var-once array2>>
	<array-add-unique <get-var-once element> results>>
  </foreach>
  <get-var-once results[]>
</defun>

<defun array-section arrayvar &optional beg end>
  ;;; DOC_SECTION (ARRAYS)
  ;;; Return the section of the array in <var arrayvar> which starts at
  ;;; index offset <var beg> and continues until index offset <var end>.
  ;;;
  ;;; <var beg> defaults to zero (i.e., the beginning of the array), and
  ;;; <var end> defaults to the size of the array (see also
  ;;; <funref arrays array-size>).
  ;;;
  ;;; If <var beg> is greater than <var end>, the elements of the array
  ;;; are returned in reverse order, starting from the <var end>th element.
  <parser::canonicalize-var arrayvar>
  <defvar beg 0>
  <defvar end <array-size <get-var-once arrayvar>>>
  <if <gt end beg>
      <concat
       <increment end>
       <if <gt end <array-size <get-var-once arrayvar>>>
	   <set-var end = <array-size <get-var-once arrayvar>>>>>>
  <foreach elt <get-var-once arrayvar>
	   start=<get-var-once beg> end=<get-var-once end>>
    <array-append <get-var-once elt> results>
  </foreach>
  <get-var-once results[]>
</defun>

<defsubst array-delete-index index arrayvar whitespace=delete>
  ;;; DOC_SECTION (ARRAYS)
  ;;; Delete the element of <var arrayvar> indicated by <var index>.
  ;;; The remainder of the array after <var index> is shifted back by one,
  ;;; so that the array ends up with one less element than it had before.
  <array-shift -1 <get-var arrayvar> start=<get-var index>>
</defsubst>

<defun comma-separated arrayvar whitespace=delete>
  ;;; DOC_SECTION (ARRAYS)
  ;;; Produce a human readable string of the elements in the array
  ;;; variable <var arrayvar> separated by commas where appropriate,
  ;;; and with the word "and" after the penultimate item.
  ;;;
  <parser::canonicalize-var arrayvar>
  <with i=0 size=<array-size <get-var-once arrayvar>>>
    <while <lt i size>>
      <concat
       <get-var <get-var-once arrayvar>[i]>
       <if <eq i <sub size 2>> ", and "
	 <if <lt i <sub size 2>> ", ">>>
      <increment i>
    </while>
  </with>
</defun>
