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

container/Mutable_Linked_List.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 Mutable_Linked_List
#
# -----------------------------------------------------------------------

# a type for mutable singly linked lists
#
# On call to `Mutable_Linked_List LM T data` creates a minimal list consisting
# of only one single element. To create larger rings, you can either call
# `append` to add single cells, or `concat` to concatenate two lists.
#
private:public Mutable_Linked_List(# mutate effect to be used to create mutable variables
                    LM type : mutate,

                    # type of data stored in this list
                    T type,

                    # the data stored in this element.
                    data T) ref : Linked_List T is


  # mutable references to next. Initalizes to refer to nil to form
  # a list with a single element.
  #
  private n := LM.env.new (option (Mutable_Linked_List LM T)) nil


  # short-hand features to get the mutable references from `n`
  #
  public next option (Linked_List T) =>
    match n.get
      ll Mutable_Linked_List => ll
      nil => nil


  # append an element to the linked list
  #
  public append(data T) =>
    match n.get
      nil => n <- Mutable_Linked_List LM T data
      ll Mutable_Linked_List => ll.append data


  # append an entire list to this linked list
  #
  public concat(other Mutable_Linked_List LM T) =>
    match n.get
      nil => n <- other
      ll Mutable_Linked_List => ll.concat other


  # freeze this list, i.e., turn all references into immutable values
  #
  public freeze =>
    if n.open
      n.close

    match n.get
      ll Mutable_Linked_List => ll.freeze
      nil =>


  # create a mutable linked list from a given sequence
  #
  # this results in a mutable linked list that is not yet frozen, i.e. it
  # can still be modified. however, the list needs to be frozen manually
  # before leaving the mutate environment.
  #
  public type.from_sequence(from Sequence T) container.Mutable_Linked_List LM T
    pre
      !from.is_empty
  =>
    from_sequence from true


  # create a mutable linked list from a given sequence
  #
  # the argument freeze specifies whether the resulting list is frozen. if
  # true, the list is frozen after creation, i.e. it can no longer be changed,
  # but the mutate environment can be left.
  #
  public type.from_sequence(from Sequence T, freeze bool) container.Mutable_Linked_List LM T
    pre
      !from.is_empty
  =>
    from_list := from.as_list
    c := container.Mutable_Linked_List LM T from_list.head.get
    from_list.tail.for_each (x -> c.append x)

    if freeze
      c.freeze

    c