Fuzion Logo
flang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

marray.fz


# This file is part of the Fuzion language implementation.
#
# The Fuzion language implementation is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, version 3 of the License.
#
# The Fuzion language implementation 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 General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License along with The
# Fuzion language implementation.  If not, see <https://www.gnu.org/licenses/>.


# -----------------------------------------------------------------------
#
#  Tokiwa Software GmbH, Germany
#
#  Source code of Fuzion standard library feature marray
#
#  Author: Fridtjof Siebert (siebert@tokiwa.software)
#
# -----------------------------------------------------------------------

# marray -- one-dimensional mutable array
#
# NYI: marray should be rewritten using effects.
#
module:public marray
  (
   # type of elements stored in this array
   redef T type,

   # length of the marray
   public length i32,

   # contents of the marray
   module data fuzion.sys.internal_array T,

   _ unit
   ) : Sequence T

  pre
    safety: (length ≥ 0) && (length ≤ data.length)

is


  # a sequence of all valid indices to access this array. Useful e.g., for
  # `for`-loops:
  #
  #   for i in arr.indices do
  #     say arr[i]
  #
  public indices => 0..length-1


  # is this sequence known to be finite?  For infinite sequences, features like
  # count diverge.
  #
  public redef finite => true


  # get element at given index i
  #
  public redef index [ ] (i i32) T
    pre
      safety: 0 ≤ i < length
  is
    data[i]

  # set element at given index i to given value o
  #
  public set [ ] (i i32, o T) unit
    pre
      safety: 0 ≤ i < length
  # post   NYI: no '==' for Any yet
  #   marray.this[i] = o
  is
    data[i] := o


  # create a new marray by adding a new element o at the end of this marray
  #
  public add (o T) marray T
    post
      debug: result.length = length + 1
      # debug: result[length] = o  -- there is no 'infix =' defined for T
  is
    d := if (data.length > length) data
      else
        new_data := fuzion.sys.internal_array_init T (max 8 data.length*2)
        for i in indices do
          new_data[i] := data[i]
        new_data
    d[length] := o
    marray T length+1 d unit


  # infix operator synonym for add
  #
  public infix + (o T) => add o


  # create immutable array from this
  #
  public redef as_array =>
    array T length (i -> marray.this[i])


  # create a list from this marray
  #
  public redef as_list =>
    # since marray is mutable,
    # we first copy the elements
    # to an immutable array.
    as_array.as_list


  # map the array to a new array applying function f to all elements
  #
  public map(B type, f T -> B) array B is
    array B marray.this.length (i -> f marray.this[i])


  # fold the elements of this array using the given monoid.
  #
  # e.g., to sum the elements of an array of i32, use a.fold i32.sum
  #
  public redef fold (m Monoid T) => fold 0 m.e m


  # fold the elements of this array using the given monoid and initial value
  #
  # Used to fold an array tail-recursively
  #
  public fold (i i32, s T, m Monoid T) T
    pre
      debug: 0 ≤ i ≤ length
  is
    if i = length
      s
    else
      fold i+1 (m.op s marray.this[i]) m


  # marray -- initialize one-dimensional mutable array
  #
  public type.new
   (# length of the marray to create
    length i32,

    # initial value for elements
    init T

   ) marray T

  is
    data := fuzion.sys.internal_array_init T length

    for x in data.indices do
      data[x] := init

    marray T length data unit


  # initialize an empty mutable array of type T
  #
  public type.new marray T is
    marray T 0 (fuzion.sys.internal_array_init T 0) unit



# marray -- initialize one-dimensional mutable array
#
public marray(T type, length i32, init T) marray T is
  (marray T).type.new length init