1  package frost.collections
  2  
  3  uses frost.unsafe.Pointer
  4  
  5  ====================================================================================================
  6  An immutable version of [Array].
  7  ====================================================================================================
  8  class ImmutableArray<T:Immutable> : Immutable, ListView<T> {
  9      @private
 10      class ImmutableArrayIterator<T:Immutable> : Iterator<T> {
 11          var array:ImmutableArray<T>
 12  
 13          var index := 0
 14  
 15          init(array:ImmutableArray<T>) {
 16              self.array := array
 17          }
 18  
 19          @override
 20          function get_done():Bit {
 21              return index = array.count
 22          }
 23  
 24          @override
 25          function next():T {
 26              index += 1
 27              return array[index - 1]
 28          }
 29      }
 30  
 31      @private
 32      def _count:Int
 33  
 34      @private
 35      def dummy:Int -- for binary compatibility with Array
 36  
 37      @private
 38      def data:Pointer<T?>
 39  
 40      ================================================================================================
 41      Creates an empty `ImmutableArray`.    
 42      ================================================================================================
 43      init() {
 44          self._count := 0
 45          data := Pointer<T?>.alloc(0)
 46      }
 47  
 48      ================================================================================================
 49      Creates an `ImmutableArray` containing all of the elements of `data`. If you are creating an
 50      `ImmutableArray` from an `Array`, consider using the [Array.finish] method instead.
 51      ================================================================================================
 52      init(data:ListView<T>) {
 53          self._count := data.count
 54          self.data := Pointer<T?>.alloc(_count)
 55          for i in 0 .. count {
 56              self.data[i] := data[i]
 57          }
 58      }
 59  
 60      @private
 61      init(data:Pointer<T>, count:Int) {
 62          self.data := data->Pointer<T?>
 63          self._count := count
 64      }
 65  
 66      ================================================================================================
 67      Invalidates an `Array` and returns its contents as an `ImmutableArray`. This is generally
 68      preferable to creating a new instance of `ImmutableArray` from this array, as `finish()` does
 69      not copy the array's contents. Interacting in any way with an `Array` after calling this method
 70      on it will cause precondition violations (or, if safety checks are disabled, undefined
 71      behavior).
 72      ================================================================================================
 73      @class
 74      @unsafeAccess
 75      method from(a:Array<T>):ImmutableArray<T> {
 76          -- FIXME this transformation is only safe at -S0
 77          a.data := a.data.realloc(a.capacity, a._count)
 78          a.$class := ImmutableArray<T>().$class -- FIXME need a better way to get a class Pointer
 79          a.capacity := -1
 80          return a->Object->ImmutableArray<T>
 81      }
 82  
 83      @override
 84      method cleanup() {
 85          for i in 0 .. count {
 86              data[i] := null
 87          }
 88          data.destroy()
 89      }
 90  
 91      @override
 92      function [](index:Int):T {
 93          assert index >= 0 & index < count
 94          return< count
 95          return data[index]->T
 96      }
 97  
 98      @override
 99      function get_count():Int {
100          return _count
101      }
102  
103      @override
104      function get_iterator():Iterator<T> {
105          return ImmutableArrayIterator<T>(self)
106      }
107  
108      @override
109      function get_toString():String {
110          def result := MutableString()
111          result.append("[")
112          var separator := ""
113          for v in self {
114              result.append(separator)
115              separator := ", "
116              -- FIXME cast shouldn't be necessary
117              if v->Object? !== null {
118                  result.append(v)
119              }
120              else {
121                  result.append("<null>")
122              }
123          }
124          result.append("]")
125          return result.finish()
126      }
127  }
128