(********************************************************************) (* *) (* fixarray.s7i Support for arrays with a fixed size *) (* Copyright (C) 2024 Thomas Mertes *) (* *) (* This file is part of the Seed7 Runtime Library. *) (* *) (* The Seed7 Runtime Library is free software; you can *) (* redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) (* Foundation; either version 2.1 of the License, or (at your *) (* option) any later version. *) (* *) (* The Seed7 Runtime Library is distributed in the hope that it *) (* will be useful, but WITHOUT ANY WARRANTY; without even the *) (* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR *) (* PURPOSE. See the GNU Lesser General Public License for more *) (* details. *) (* *) (* You should have received a copy of the GNU Lesser General *) (* Public License along with this program; if not, write to the *) (* Free Software Foundation, Inc., 51 Franklin Street, *) (* Fifth Floor, Boston, MA 02110-1301, USA. *) (* *) (********************************************************************) (** * Abstract data type, describing fixed size arrays with [[integer]] index. * A fixed size array type defines the minimum and maximum allowed indices. * All arrays declared with this type have the same length and the same * minimum and maximum indices. All abstract fixed size array types are * incompatible to each other. A type declaration is needed to use the * same fixed size array type at several places. E.g.: * const type: dataBlockType is array [1 .. 64] integer; * afterwards ''dataBlockType'' can be used in declarations. E.g.: * var dataBlockType: aDataBlock is dataBlockType.value; * @param minIdx Minimum index of the array type. * @param maxIdx Maximum index of the array type. * @param baseType Type of the array elements. *) const func type: array [ (in integer: minIdx) .. (in integer: maxIdx) ] (in type: baseType) is func result var type: arrayType is void; begin global arrayType := newtype; IN_PARAM_IS_REFERENCE(arrayType); const proc: (ref arrayType: dest) ::= (in arrayType: source) is action "ARR_CREATE"; const proc: destroy (ref arrayType: aValue) is action "ARR_DESTR"; const proc: (inout arrayType: dest) := (in arrayType: source) is action "ARR_CPY"; const func arrayType: SET_MIN_IDX (paren1, in integer: start, paren2, in arrayType: arr) is action "ARR_ARRLIT2"; const func arrayType: TIMES (in integer: factor, times, in baseType: element, attr arrayType) is action "ARR_TIMES"; const arrayType: (attr arrayType) . value is SET_MIN_IDX(paren1, minIdx, paren2, TIMES(succ(maxIdx - minIdx), times, baseType.value, arrayType)); (** * Generate an ''arrayType'' array filled with ''elements''. * @return a fixed size array filled with ''elements''. * @exception MEMORY_ERROR Not enough memory to represent the result. *) const func arrayType: (attr arrayType) times (in baseType: element) is return SET_MIN_IDX(paren1, minIdx, paren2, TIMES(succ(maxIdx - minIdx), times, element, arrayType)); (** * Length of all arrays declared with ''arrayType''. * All arrays declared with ''arrayType'' have this length. * @return the length of the array. *) const integer: length (attr arrayType) is succ(maxIdx - minIdx); (** * Minimum index of all arrays declared with ''arrayType''. * All arrays declared with ''arrayType'' have this minimum index. * @return the length of the array. *) const integer: minIdx (attr arrayType) is minIdx; (** * Maximum index of all arrays declared with ''arrayType''. * All arrays declared with ''arrayType'' have this maximum index. * @return the length of the array. *) const integer: maxIdx (attr arrayType) is maxIdx; (** * Length of the array ''arr''. * The length of a fixed size array does not depend on the value. * @return the length of the array. *) const integer: length (in arrayType: arr) is succ(maxIdx - minIdx); (** * Minimum index of array ''arr''. * The minimum index of a fixed size array does not depend on the value. * @return the minimum index of the array. *) const integer: minIdx (in arrayType: arr) is minIdx; (** * Maximum index of array ''arr''. * The maximum index of a fixed size array does not depend on the value. * @return the maximum index of the array. *) const integer: maxIdx (in arrayType: arr) is maxIdx; (** * Access one element from the fixed size array ''arr''. * @return the element with the specified ''index'' from ''arr''. * @exception INDEX_ERROR If ''index'' is less than [[#minIdx(attr_arrayType)|minIdx]](arrayType) or * greater than [[#maxIdx(attr_arrayType)|maxIdx]](arrayType) *) const func baseType: (in arrayType: arr) [ (in integer: index) ] is action "ARR_IDX"; const varfunc baseType: (inout arrayType: arr) [ (in integer: index) ] is action "ARR_IDX"; (** * For-loop where ''forVar'' loops over the elements of the array ''arr''. *) const proc: for (inout baseType: forVar) range (in arrayType: arr) do (in proc: statements) end for is func local var integer: number is 0; begin for number range minIdx to maxIdx do forVar := arr[number]; statements; end for; end func; (** * For-loop where ''keyVar'' loops over the indices of the array ''arr''. *) const proc: for key (inout integer: keyVar) range (in arrayType: arr) do (in proc: statements) end for is func begin for keyVar range minIdx to maxIdx do statements; end for; end func; (** * For-loop where ''forVar'' and ''keyVar'' loop over the array ''arr''. * The variable ''forVar'' loops over the elements of ''arr'' * and ''keyVar'' loops over the indices of ''arr''. *) const proc: for (inout baseType: forVar) key (inout integer: keyVar) range (in arrayType: arr) do (in proc: statements) end for is func begin for keyVar range minIdx to maxIdx do forVar := arr[keyVar]; statements; end for; end func; (** * For-loop where ''forVar'' loops over the elements of the array ''arr''. * Additionally a ''condition'' is checked before the statements in * the loop body are executed. *) const proc: for (inout baseType: forVar) range (in arrayType: arr) until (ref func boolean: condition) do (in proc: statements) end for is func local var integer: index is 0; begin index := minIdx; if index <= maxIdx then forVar := arr[index]; while index <= maxIdx and not condition do statements; incr(index); if index <= maxIdx then forVar := arr[index]; end if; end while; end if; end func; const proc: for (inout baseType: forVar) range (in arrayType: arr) until (ref boolean: condition) do (in proc: statements) end for is func local var integer: index is 0; begin index := minIdx; if index <= maxIdx then forVar := arr[index]; while index <= maxIdx and not condition do statements; incr(index); if index <= maxIdx then forVar := arr[index]; end if; end while; end if; end func; (** * For-loop where ''keyVar'' loops over the indices of the array ''arr''. * Additionally a ''condition'' is checked before the statements in * the loop body are executed. *) const proc: for key (inout integer: keyVar) range (in arrayType: arr) until (ref func boolean: condition) do (in proc: statements) end for is func begin for keyVar range minIdx to maxIdx until condition do statements; end for; end func; const proc: for key (inout integer: keyVar) range (in arrayType: arr) until (ref boolean: condition) do (in proc: statements) end for is func begin for keyVar range minIdx to maxIdx until condition do statements; end for; end func; (** * For-loop where ''forVar'' and ''keyVar'' loop over the array ''arr''. * The variable ''forVar'' loops over the elements of ''arr'' * and ''keyVar'' loops over the indices of ''arr''. * Additionally a ''condition'' is checked before the statements in * the loop body are executed. *) const proc: for (inout baseType: forVar) key (inout integer: keyVar) range (in arrayType: arr) until (ref func boolean: condition) do (in proc: statements) end for is func begin keyVar := minIdx; if keyVar <= maxIdx then forVar := arr[keyVar]; while keyVar <= maxIdx and not condition do statements; incr(keyVar); if keyVar <= maxIdx then forVar := arr[keyVar]; end if; end while; end if; end func; const proc: for (inout baseType: forVar) key (inout integer: keyVar) range (in arrayType: arr) until (ref boolean: condition) do (in proc: statements) end for is func begin keyVar := minIdx; if keyVar <= maxIdx then forVar := arr[keyVar]; while keyVar <= maxIdx and not condition do statements; incr(keyVar); if keyVar <= maxIdx then forVar := arr[keyVar]; end if; end while; end if; end func; end global; end func; (** * Abstract data type for fixed size arrays with minimum index of 1. * A fixed size array type defines the minimum and maximum allowed indices. * All arrays declared with this type have the same length and the same * minimum and maximum indices. All abstract fixed size array types are * incompatible to each other. A type declaration is needed to use the * same fixed size array type at several places. E.g.: * const type: dataBlockType is array [64] integer; * afterwards ''dataBlockType'' can be used in declarations. E.g.: * var dataBlockType: aDataBlock is dataBlockType.value; * @param maxIdx Maximum index of the array type. * @param baseType Type of the array elements. *) const func type: array [ (in integer: maxIdx) ] (in type: baseType) is return array[1 .. maxIdx] baseType;