lib/array: suppress a warning to be compatible with the bootstrap
[nit.git] / lib / standard / collection / array.nit
index add6077..3cc0b57 100644 (file)
@@ -13,7 +13,9 @@
 
 # This module introduces the standard array structure.
 # It also implements two other abstract collections : ArrayMap and ArraySet
-module array
+module array is
+       no_warning "useless-type-test" # to avoid warning with nitc while compiling with c_src
+end
 
 import abstract_collection
 
@@ -130,7 +132,20 @@ abstract class AbstractArrayRead[E]
                end
        end
 
-       redef fun iterator: ArrayIterator[E] do return new ArrayIterator[E](self)
+       redef fun iterator: ArrayIterator[E] do
+               var res = _free_iterator
+               if res == null then return new ArrayIterator[E](self)
+               res._index = 0
+               _free_iterator = null
+               return res
+       end
+
+       # An old iterator, free to reuse.
+       # Once an iterator is `finish`, it become reusable.
+       # Since some arrays are iterated a lot, this avoid most of the
+       # continuous allocation/garbage-collection of the needed iterators.
+       private var free_iterator: nullable ArrayIterator[E] = null
+
        redef fun reverse_iterator do return new ArrayReverseIterator[E](self)
 end
 
@@ -242,6 +257,7 @@ end
 # Resizable one dimension array of objects.
 #
 # Arrays have a literal representation.
+#
 #     var a = [12, 32, 8]
 #     # is equivalent with:
 #     var b = new Array[Int]
@@ -251,6 +267,7 @@ end
 #     assert a == b
 class Array[E]
        super AbstractArray[E]
+       super Cloneable
 
        redef fun [](index)
        do
@@ -280,6 +297,32 @@ class Array[E]
                _items[l] = item
        end
 
+       # Slight optimization for arrays
+       redef fun add_all(items)
+       do
+               var l = _length
+               var nl = l + items.length
+               if _capacity < nl then
+                       enlarge nl
+               end
+
+               if items isa Array[E] then
+                       var k = 0
+                       while l < nl do
+                               _items[l] = items._items[k]
+                               l += 1
+                               k += 1
+                       end
+               else
+                       for item in items do
+                               _items[l] = item
+                               l += 1
+                       end
+               end
+
+               _length = nl
+       end
+
        redef fun enlarge(cap)
        do
                var c = _capacity
@@ -347,10 +390,6 @@ class Array[E]
        # The internal storage.
        private var items: nullable NativeArray[E] = null
 
-       # Do not use this method
-       # FIXME: Remove it once modules can intrude non local modules
-       fun intern_items: NativeArray[E] do return _items.as(not null)
-
        # The size of `_items`.
        private var capacity: Int = 0
 
@@ -370,6 +409,29 @@ class Array[E]
                return true
        end
 
+       # Shallow clone of `self`
+       #
+       # ~~~
+       # var a = [1,2,3]
+       # var b = a.clone
+       # assert a == b
+       # a.add 4
+       # assert a != b
+       # b.add 4
+       # assert a == b
+       # ~~~
+       #
+       # Note that the clone is shallow and elements are shared between `self` and the result.
+       #
+       # ~~~
+       # var aa = [a]
+       # var bb = aa.clone
+       # assert aa == bb
+       # aa.first.add 5
+       # assert aa == bb
+       # ~~~
+       redef fun clone do return to_a
+
        # Concatenation of arrays.
        #
        # Returns a new array built by concatenating `self` and `other` together.
@@ -398,11 +460,11 @@ class Array[E]
        #
        # returns a new array built by concatenating `self` `repeat` times.
        #
-       #    var a = [1,2,3]
-       #    assert (a * 0).is_empty
-       #    assert a * 1  ==  [1,2,3]
-       #    assert a * 2  ==  [1,2,3,1,2,3]
-       #    assert (a * 10).length  ==  30
+       #     var a = [1,2,3]
+       #     assert (a * 0).is_empty
+       #     assert a * 1  ==  [1,2,3]
+       #     assert a * 2  ==  [1,2,3,1,2,3]
+       #     assert (a * 10).length  ==  30
        fun *(repeat: Int): Array[E]
        do
                assert repeat >= 0
@@ -430,6 +492,8 @@ private class ArrayIterator[E]
        redef var index = 0
 
        var array: AbstractArrayRead[E]
+
+       redef fun finish do _array._free_iterator = self
 end
 
 private class ArrayReverseIterator[E]
@@ -448,8 +512,9 @@ end
 # Others collections ##########################################################
 
 # A set implemented with an Array.
-class ArraySet[E: Object]
+class ArraySet[E]
        super Set[E]
+       super Cloneable
 
        # The stored elements.
        private var array: Array[E] is noinit
@@ -496,10 +561,41 @@ class ArraySet[E: Object]
        init with_capacity(i: Int) do _array = new Array[E].with_capacity(i)
 
        redef fun new_set do return new ArraySet[E]
+
+       # Shallow clone of `self`
+       #
+       # ~~~
+       # var a = new ArraySet[Int]
+       # a.add 1
+       # a.add 2
+       # var b = a.clone
+       # assert a == b
+       # a.add 3
+       # assert a != b
+       # b.add 3
+       # assert a == b
+       # ~~~
+       #
+       # Note that the clone is shallow and keys and values are shared between `self` and the result.
+       #
+       # ~~~
+       # var aa = new ArraySet[Array[Int]]
+       # aa.add([1,2])
+       # var bb = aa.clone
+       # assert aa == bb
+       # aa.first.add 5
+       # assert aa == bb
+       # ~~~
+       redef fun clone
+       do
+               var res = new ArraySet[E]
+               res.add_all self
+               return res
+       end
 end
 
 # Iterators on sets implemented with arrays.
-private class ArraySetIterator[E: Object]
+private class ArraySetIterator[E]
        super Iterator[E]
 
        redef fun is_ok do return _iter.is_ok
@@ -513,8 +609,9 @@ end
 
 
 # Associative arrays implemented with an array of (key, value) pairs.
-class ArrayMap[K: Object, E]
+class ArrayMap[K, E]
        super CoupleMap[K, E]
+       super Cloneable
 
        # O(n)
        redef fun [](key)
@@ -538,8 +635,8 @@ class ArrayMap[K: Object, E]
                end
        end
 
-       redef var keys: RemovableCollection[K] = new ArrayMapKeys[K, E](self)
-       redef var values: RemovableCollection[E] = new ArrayMapValues[K, E](self)
+       redef var keys: RemovableCollection[K] = new ArrayMapKeys[K, E](self) is lazy
+       redef var values: RemovableCollection[E] = new ArrayMapValues[K, E](self) is lazy
 
        # O(1)
        redef fun length do return _items.length
@@ -593,9 +690,38 @@ class ArrayMap[K: Object, E]
                end
                return -1
        end
+
+       # Shallow clone of `self`
+       #
+       # ~~~
+       # var a = new ArrayMap[String,Int]
+       # a["one"] = 1
+       # a["two"] = 2
+       # var b = a.clone
+       # assert a == b
+       # a["zero"] = 0
+       # assert a != b
+       # ~~~
+       #
+       # Note that the clone is shallow and keys and values are shared between `self` and the result.
+       #
+       # ~~~
+       # var aa = new ArrayMap[String, Array[Int]]
+       # aa["two"] = [1,2]
+       # var bb = aa.clone
+       # assert aa == bb
+       # aa["two"].add 5
+       # assert aa == bb
+       # ~~~
+       redef fun clone
+       do
+               var res = new ArrayMap[K,E]
+               res.recover_with self
+               return res
+       end
 end
 
-private class ArrayMapKeys[K: Object, E]
+private class ArrayMapKeys[K, E]
        super RemovableCollection[K]
        # The original map
        var map: ArrayMap[K, E]
@@ -615,7 +741,7 @@ private class ArrayMapKeys[K: Object, E]
        redef fun remove_all(key) do self.remove(key)
 end
 
-private class ArrayMapValues[K: Object, E]
+private class ArrayMapValues[K, E]
        super RemovableCollection[E]
        # The original map
        var map: ArrayMap[K, E]