ArrayList improvements:

1) remove must compare object using Kotlin.equals (the same as in contains)
2) use ArrayIterator instead of ListIterator (perfomance)
3) remove duplicated code (refactor)
4) toArray
5) fix "add((index, item)" — correct translation to JavaScript "addAt"
This commit is contained in:
develar
2012-06-28 11:13:48 +04:00
parent 07ae3afc95
commit 77320e07f2
5 changed files with 291 additions and 376 deletions
+56 -113
View File
@@ -55,125 +55,77 @@ val Collections = object {
list[i2] = tmp
}
}
}
library
public open class ArrayList<E>() : java.util.List<E> {
public override fun size() : Int = js.noImpl
public override fun isEmpty() : Boolean = js.noImpl
public override fun contains(o : Any?) : Boolean = js.noImpl
public override fun iterator() : Iterator<E> = js.noImpl
// public override fun indexOf(o : Any?) : Int = js.noImpl
// public override fun lastIndexOf(o : Any?) : Int = js.noImpl
// public override fun toArray() : Array<Any?> = js.noImpl
// public override fun toArray<T>(a : Array<out T>) : Array<T> = js.noImpl
public override fun get(index : Int) : E = js.noImpl
public override fun set(index : Int, element : E) : E = js.noImpl
public override fun add(e : E) : Boolean = js.noImpl
public override fun add(index : Int, element : E) : Unit = js.noImpl
library("removeByIndex")
public override fun remove(index : Int) : E = js.noImpl
public override fun remove(o : Any?) : Boolean = js.noImpl
public override fun clear() : Unit = js.noImpl
public override fun addAll(c : java.util.Collection<out E>) : Boolean = js.noImpl
// public override fun addAll(index : Int, c : java.util.Collection<out E>) : Boolean = js.noImpl
}
library
public trait Collection<E> : java.lang.Iterable<E> {
open fun size() : Int
open fun isEmpty() : Boolean
open fun contains(o : Any?) : Boolean
override fun iterator() : java.util.Iterator<E>
// open fun toArray() : Array<Any?>
// open fun toArray<T>(a : Array<out T>) : Array<T>
open fun add(e : E) : Boolean
open fun remove(o : Any?) : Boolean
public trait Collection<E>: Iterable<E> {
open fun size(): Int
open fun isEmpty(): Boolean
open fun contains(o: Any?): Boolean
override fun iterator(): Iterator<E>
fun toArray(): Array<E>
// open fun toArray<T>(a : Array<out T>) : Array<T>
open fun add(e: E): Boolean
open fun remove(o: Any?): Boolean
//open fun containsAll(c : java.util.Collection<*>) : Boolean
open fun addAll(c : java.util.Collection<out E>) : Boolean
open fun addAll(c: Collection<out E>): Boolean
//open fun removeAll(c : java.util.Collection<*>) : Boolean
//open fun retainAll(c : java.util.Collection<*>) : Boolean
open fun clear() : Unit
open fun clear(): Unit
}
library
public abstract open class AbstractCollection<E>() : Collection<E> {
public abstract class AbstractCollection<E>() : Collection<E> {
override fun toArray(): Array<E> = js.noImpl
override fun isEmpty(): Boolean = js.noImpl
override fun contains(o: Any?): Boolean = js.noImpl
override fun iterator(): Iterator<E> = js.noImpl
override fun add(e: E): Boolean = js.noImpl
override fun remove(o: Any?): Boolean = js.noImpl
override fun addAll(c: Collection<out E>): Boolean = js.noImpl
override fun clear(): Unit = js.noImpl
override fun size(): Int = js.noImpl
}
library
public abstract open class AbstractList<E>() : AbstractCollection<E>(), List<E> {
public override fun isEmpty() : Boolean = js.noImpl
public override fun contains(o : Any?) : Boolean = js.noImpl
public override fun iterator() : Iterator<E> = js.noImpl
// public override fun indexOf(o : Any?) : Int = js.noImpl
// public override fun lastIndexOf(o : Any?) : Int = js.noImpl
// public override fun toArray() : Array<Any?> = js.noImpl
// public override fun toArray<T>(a : Array<out T>) : Array<T> = js.noImpl
public override fun set(index : Int, element : E) : E = js.noImpl
public override fun add(e : E) : Boolean = js.noImpl
public override fun add(index : Int, element : E) : Unit = js.noImpl
library("removeByIndex")
public override fun remove(index : Int) : E = js.noImpl
public override fun remove(o : Any?) : Boolean = js.noImpl
public override fun clear() : Unit = js.noImpl
public override fun addAll(c : java.util.Collection<out E>) : Boolean = js.noImpl
// public override fun addAll(index : Int, c : java.util.Collection<out E>) : Boolean = js.noImpl
public trait List<E>: Collection<E> {
fun get(index: Int): E
fun set(index: Int, element: E): E
fun add(index: Int, element: E): Unit
fun remove(index: Int): E
fun indexOf(o: E?): Int
}
library
public trait List<E> : Collection<E> {
override fun size() : Int
override fun isEmpty() : Boolean
override fun contains(o : Any?) : Boolean
override fun iterator() : java.util.Iterator<E>
// override fun toArray() : Array<Any?>
// Simulate Java's array covariance
// override fun toArray<T>(a : Array<out T>) : Array<T>
override fun add(e : E) : Boolean
override fun remove(o : Any?) : Boolean
// override fun containsAll(c : java.util.Collection<*>) : Boolean
override fun addAll(c : java.util.Collection<out E>) : Boolean
// open fun addAll(index : Int, c : java.util.Collection<out E>) : Boolean
// override fun removeAll(c : java.util.Collection<*>) : Boolean
// override fun retainAll(c : java.util.Collection<*>) : Boolean
override fun clear() : Unit
open fun get(index : Int) : E
open fun set(index : Int, element : E) : E
open fun add(index : Int, element : E) : Unit
open fun remove(index : Int) : E
// open fun indexOf(o : Any?) : Int
// open fun lastIndexOf(o : Any?) : Int
public abstract class AbstractList<E>(): AbstractCollection<E>(), List<E> {
override fun get(index: Int): E = js.noImpl
override fun set(index: Int, element: E): E = js.noImpl
library("addAt")
override fun add(index: Int, element: E): Unit = js.noImpl
library("removeAt")
override fun remove(index: Int): E = js.noImpl
override fun indexOf(o: E?): Int = js.noImpl
}
library
public open class ArrayList<E>() : AbstractList<E>() {
}
library
public trait Set<E> : Collection<E> {
override fun size() : Int
override fun isEmpty() : Boolean
override fun contains(o : Any?) : Boolean
override fun iterator() : java.util.Iterator<E>
// override fun toArray() : Array<Any?>
// override fun toArray<T>(a : Array<out T>) : Array<T>
override fun add(e : E) : Boolean
override fun remove(o : Any?) : Boolean
//override fun containsAll(c : java.util.Collection<*>) : Boolean
override fun addAll(c : java.util.Collection<out E>) : Boolean
//override fun retainAll(c : java.util.Collection<*>) : Boolean
//override fun removeAll(c : java.util.Collection<*>) : Boolean
override fun clear() : Unit
}
library
public open class HashSet<E>() : java.util.Set<E> {
public override fun iterator() : java.util.Iterator<E> = js.noImpl
public override fun size() : Int = js.noImpl
public override fun isEmpty() : Boolean = js.noImpl
public override fun contains(o : Any?) : Boolean = js.noImpl
public override fun add(e : E) : Boolean = js.noImpl
public override fun remove(o : Any?) : Boolean = js.noImpl
public override fun clear() : Unit = js.noImpl
override fun addAll(c : java.util.Collection<out E>) : Boolean = js.noImpl
public open class HashSet<E>(): AbstractCollection<E>(), java.util.Set<E> {
}
library
@@ -220,22 +172,13 @@ public open class HashMap<K, V>() : java.util.Map<K, V> {
}
library
public open class LinkedList<E>() : List<E> {
public override fun iterator() : java.util.Iterator<E> = js.noImpl
public override fun isEmpty() : Boolean = js.noImpl
public override fun contains(o : Any?) : Boolean = js.noImpl
public override fun size() : Int = js.noImpl
public override fun add(e : E) : Boolean = js.noImpl
public override fun remove(o : Any?) : Boolean = js.noImpl
public override fun addAll(c : java.util.Collection<out E>) : Boolean = js.noImpl
public override fun clear() : Unit = js.noImpl
public override fun get(index : Int) : E = js.noImpl
public override fun set(index : Int, element : E) : E = js.noImpl
public override fun add(index : Int, element : E) : Unit = js.noImpl
public override fun remove(index : Int) : E = js.noImpl
public fun poll() : E? = js.noImpl
public fun peek() : E? = js.noImpl
public fun offer(e : E) : Boolean = js.noImpl
public open class LinkedList<E>(): AbstractList<E>() {
public override fun get(index: Int): E = js.noImpl
public override fun set(index: Int, element: E): E = js.noImpl
public override fun add(index: Int, element: E): Unit = js.noImpl
public fun poll(): E? = js.noImpl
public fun peek(): E? = js.noImpl
public fun offer(e: E): Boolean = js.noImpl
}
library
@@ -51,6 +51,10 @@ public final class ArrayListTest extends JavaClassesTest {
fooBoxTest();
}
public void testToArray() throws Exception {
fooBoxTest();
}
public void testIndexOOB() throws Exception {
try {
fooBoxTest();
@@ -0,0 +1,13 @@
package foo
import java.util.ArrayList
fun box() : Boolean {
var i = 0
val list = ArrayList<Int>()
while (i++ < 3) {
list.add(i)
}
val array = list.toArray()
return array[0] == 1 && array[1] == 2 && array[2] == 3
}
+155 -187
View File
@@ -28,7 +28,7 @@ var kotlin = {set:function (receiver, key, value) {
return obj1.equals(obj2);
}
}
return (obj1 === obj2);
return obj1 === obj2;
};
Kotlin.modules = {};
@@ -48,117 +48,122 @@ var kotlin = {set:function (receiver, key, value) {
throw Kotlin.$new(Kotlin.Exceptions.NullPointerException)();
};
Kotlin.AbstractList = Kotlin.$createClass({
set:function (index, value) {
throw Kotlin.$new(Kotlin.Exceptions.UnsupportedOperationException)();
},
iterator:function () {
return Kotlin.$new(Kotlin.ArrayIterator)(this);
},
isEmpty:function () {
return (this.size() === 0);
},
add:function (element) {
throw Kotlin.$new(Kotlin.Exceptions.UnsupportedOperationException)();
},
addAll:function (collection) {
var it = collection.iterator();
while (it.get_hasNext()) {
this.add(it.next());
}
},
remove:function(value) {
for (var i = 0; i < this.$size; ++i) {
if (this.array[i] == value) {
this.removeByIndex(i);
return;
}
}
},
removeByIndex:function (index) {
throw Kotlin.$new(Kotlin.Exceptions.UnsupportedOperationException)();
},
clear:function () {
throw Kotlin.$new(Kotlin.Exceptions.UnsupportedOperationException)();
},
contains:function (obj) {
for (var i = 0; i < this.$size; ++i) {
if (Kotlin.equals(this.array[i], obj)) {
return true;
}
}
return false;
}
});
function throwAbstractFunctionInvocationError() {
throw new TypeError("Function is abstract");
}
Kotlin.ArrayList = Kotlin.$createClass({
initialize:function () {
this.array = [];
this.$size = 0;
Kotlin.Iterator = Kotlin.$createClass({
initialize: function () {
},
get:function (index) {
if ((index < 0) || (index >= this.$size)) {
throw Kotlin.Exceptions.IndexOutOfBounds;
}
return (this.array)[index];
next: throwAbstractFunctionInvocationError,
get_hasNext: throwAbstractFunctionInvocationError
});
var ArrayIterator = Kotlin.$createClass(Kotlin.Iterator, {
initialize: function (array) {
this.array = array;
this.size = array.length;
this.index = 0;
},
set:function (index, value) {
if ((index < 0) || (index >= this.$size)) {
throw Kotlin.Exceptions.IndexOutOfBounds;
}
(this.array)[index] = value;
next: function () {
return this.array[this.index++];
},
size:function () {
return this.$size;
get_hasNext: function () {
return this.index < this.size;
}
});
var ListIterator = Kotlin.$createClass(ArrayIterator, {
initialize: function (list) {
this.list = list;
this.size = list.size();
this.index = 0;
},
iterator:function () {
return Kotlin.$new(Kotlin.ArrayIterator)(this);
next: function () {
return this.list.get(this.index++);
},
isEmpty:function () {
return (this.$size === 0);
get_hasNext: function () {
return this.index < this.size;
}
});
Kotlin.AbstractList = Kotlin.$createClass({
iterator: function () {
return Kotlin.$new(ListIterator)(this);
},
add:function (element) {
this.array[this.$size++] = element;
isEmpty: function () {
return this.size() == 0;
},
addAll:function (collection) {
addAll: function (collection) {
var it = collection.iterator();
while (it.get_hasNext()) {
this.add(it.next());
}
},
remove:function(value) {
for (var i = 0; i < this.$size; ++i) {
if (this.array[i] == value) {
this.removeByIndex(i);
return;
}
remove: function (o) {
var index = this.indexOf(o);
if (index != -1) {
this.removeAt(index);
}
},
removeByIndex:function (index) {
for (var i = index; i < this.$size - 1; ++i) {
this.array[i] = this.array[i + 1];
}
this.$size--;
},
clear:function () {
this.array = [];
this.$size = 0;
},
contains:function (obj) {
for (var i = 0; i < this.$size; ++i) {
if (Kotlin.equals(this.array[i], obj)) {
return true;
}
}
return false;
contains: function (o) {
return this.indexOf(o) != -1;
}
});
Kotlin.ArrayList = Kotlin.$createClass(Kotlin.AbstractList, {
initialize: function () {
this.array = [];
this.$size = 0;
},
get: function (index) {
if (index < 0 || index >= this.$size) {
throw Kotlin.Exceptions.IndexOutOfBounds;
}
return this.array[index];
},
set: function (index, value) {
if (index < 0 || index >= this.$size) {
throw Kotlin.Exceptions.IndexOutOfBounds;
}
this.array[index] = value;
},
toArray: function () {
return this.array.slice(0, this.$size);
},
size: function () {
return this.$size;
},
iterator: function () {
return Kotlin.arrayIterator(this.array);
},
add: function (element) {
this.array[this.$size++] = element;
},
addAt: function (index, element) {
this.array.splice(index, 0, element);
},
removeAt: function (index) {
this.array.splice(index, 1);
this.$size--;
},
clear: function () {
this.array.length = 0;
this.$size = 0;
},
indexOf: function (o) {
for (var i = 0, n = this.$size; i < n; ++i) {
if (Kotlin.equals(this.array[i], o)) {
return i;
}
}
return -1;
}
});
Kotlin.parseInt = function (str) {
return parseInt(str, 10);
}
;
};
Kotlin.safeParseInt = function(str) {
var r = parseInt(str, 10);
@@ -212,51 +217,32 @@ var kotlin = {set:function (receiver, key, value) {
Kotlin.System.out().print(s);
};
Kotlin.AbstractFunctionInvocationError = Kotlin.$createClass();
Kotlin.Iterator = Kotlin.$createClass({
initialize:function () {
},
next:function () {
throw Kotlin.$new(Kotlin.AbstractFunctionInvocationError)();
},
get_hasNext:function () {
throw Kotlin.$new(Kotlin.AbstractFunctionInvocationError)();
}
});
Kotlin.ArrayIterator = Kotlin.$createClass(Kotlin.Iterator, {
initialize: function (array) {
this.array = array;
this.index = 0;
},
next: function () {
return this.array.get(this.index++);
},
get_hasNext: function () {
return this.array.size() > this.index;
}
});
Kotlin.RangeIterator = Kotlin.$createClass(Kotlin.Iterator, {
initialize:function (start, count, reversed) {
initialize: function (start, count, reversed) {
this.$start = start;
this.$count = count;
this.$reversed = reversed;
this.$i = this.get_start();
}, get_start:function () {
},
get_start: function () {
return this.$start;
}, get_count:function () {
},
get_count: function () {
return this.$count;
}, set_count:function (tmp$0) {
},
set_count: function (tmp$0) {
this.$count = tmp$0;
}, get_reversed:function () {
},
get_reversed: function () {
return this.$reversed;
}, get_i:function () {
},
get_i: function () {
return this.$i;
}, set_i:function (tmp$0) {
},
set_i: function (tmp$0) {
this.$i = tmp$0;
}, next:function () {
},
next: function () {
this.set_count(this.get_count() - 1);
if (this.get_reversed()) {
this.set_i(this.get_i() - 1);
@@ -272,46 +258,48 @@ var kotlin = {set:function (receiver, key, value) {
}
});
Kotlin.NumberRange = Kotlin.$createClass({initialize:function (start, size, reversed) {
this.$start = start;
this.$size = size;
this.$reversed = reversed;
}, get_start:function () {
return this.$start;
}, get_size:function () {
return this.$size;
}, get_reversed:function () {
return this.$reversed;
}, get_end:function () {
return this.get_reversed() ? this.get_start() - this.get_size() + 1 : this.get_start() + this.get_size() - 1;
}, contains:function (number) {
if (this.get_reversed()) {
return number <= this.get_start() && number > this.get_start() - this.get_size();
Kotlin.NumberRange = Kotlin.$createClass({
initialize: function (start, size, reversed) {
this.$start = start;
this.$size = size;
this.$reversed = reversed;
},
get_start: function () {
return this.$start;
},
get_size: function () {
return this.$size;
},
get_reversed: function () {
return this.$reversed;
},
get_end: function () {
return this.get_reversed() ? this.get_start() - this.get_size() + 1 : this.get_start() + this.get_size() - 1;
},
contains: function (number) {
if (this.get_reversed()) {
return number <= this.get_start() && number > this.get_start() - this.get_size();
}
else {
return number >= this.get_start() && number < this.get_start() + this.get_size();
}
},
iterator: function () {
return Kotlin.$new(Kotlin.RangeIterator)(this.get_start(), this.get_size(), this.get_reversed());
}
else {
return number >= this.get_start() && number < this.get_start() + this.get_size();
}
}, iterator:function () {
return Kotlin.$new(Kotlin.RangeIterator)(this.get_start(), this.get_size(), this.get_reversed());
}
});
Kotlin.Comparator = Kotlin.$createClass(
{
initialize: function () {
},
compare: function (el1, el2) {
throw Kotlin.$new(Kotlin.AbstractFunctionInvocationError)();
}
}
);
Kotlin.Comparator = Kotlin.$createClass({
initialize: function () {
},
compare: throwAbstractFunctionInvocationError
});
var ComparatorImpl = Kotlin.$createClass(Kotlin.Comparator, {
initialize: function (comparator) {
this.compare = comparator;
}
}
);
initialize: function (comparator) {
this.compare = comparator;
}
});
Kotlin.comparator = function (f) {
return Kotlin.$new(ComparatorImpl)(f);
@@ -373,25 +361,8 @@ var kotlin = {set:function (receiver, key, value) {
return Kotlin.$new(Kotlin.NumberRange)(0, arr.length);
};
var intrinsicArrayIterator = Kotlin.$createClass(
Kotlin.Iterator,
{
initialize: function (arr) {
this.arr = arr;
this.len = arr.length;
this.i = 0;
},
next: function () {
return this.arr[this.i++];
},
get_hasNext: function () {
return this.i < this.len;
}
}
);
Kotlin.arrayIterator = function (arr) {
return Kotlin.$new(intrinsicArrayIterator)(arr);
Kotlin.arrayIterator = function (array) {
return Kotlin.$new(ArrayIterator)(array);
};
Kotlin.toString = function (obj) {
@@ -800,14 +771,11 @@ var kotlin = {set:function (receiver, key, value) {
Kotlin.HashTable = Hashtable;
})();
Kotlin.HashMap = Kotlin.$createClass(
{
initialize:function () {
Kotlin.HashTable.call(this);
}
}
);
Kotlin.HashMap = Kotlin.$createClass({
initialize: function () {
Kotlin.HashTable.call(this);
}
});
(function () {
function HashSet(hashingFunction, equalityFunction) {
+63 -76
View File
@@ -20,88 +20,75 @@ var Kotlin = {};
return false;
};
// todo compatibility for opera https://raw.github.com/gist/1000718/es5compat-gs.js
// as separated function to reduce scope
function createConstructor(proto, initializer) {
return function () {
var o = Object.create(proto);
if (initializer != null) {
initializer.apply(o, arguments);
}
Object.seal(o);
return o;
};
}
function computeProto(bases, properties) {
var proto = null;
for (var i = 0, n = bases.length; i < n; i++) {
var base = bases[i];
var baseProto = base.proto;
if (baseProto == null || base.properties == null) {
continue;
}
if (!proto) {
proto = Object.create(baseProto, properties || undefined);
continue;
}
Object.defineProperties(proto, base.properties);
// todo test A -> B, C(->D) *properties from D is not yet added to proto*
}
return proto;
}
// proto must be created for class even if it is not needed (requires for is operator)
Kotlin.createClass = (function () {
function create(bases, initializer, properties) {
var proto;
var baseInitializer = null;
var isTrait = initializer == null;
if (!bases) {
proto = !properties && isTrait ? null : Object.create(null, properties || undefined);
Kotlin.createClass = function (bases, initializer, properties) {
var proto;
var baseInitializer = null;
var isTrait = initializer == null;
if (!bases) {
proto = !properties && isTrait ? null : Object.create(null, properties || undefined);
}
else if (!Array.isArray(bases)) {
baseInitializer = bases.initializer;
proto = !properties && isTrait ? bases.proto : Object.create(bases.proto, properties || undefined);
}
else {
proto = computeProto(bases, properties);
// first is superclass, other are traits
baseInitializer = bases[0].initializer;
// all bases are traits without properties
if (proto == null && !isTrait) {
proto = Object.create(null, properties || undefined);
}
else if (!Array.isArray(bases)) {
baseInitializer = bases.initializer;
proto = !properties && isTrait ? bases.proto : Object.create(bases.proto, properties || undefined);
}
else {
proto = computeProto(bases, properties);
// first is superclass, other are traits
baseInitializer = bases[0].initializer;
// all bases are traits without properties
if (proto == null && !isTrait) {
proto = Object.create(null, properties || undefined);
}
}
var constructor = createConstructor(proto, initializer);
Object.defineProperty(constructor, "proto", {value: proto});
Object.defineProperty(constructor, "properties", {value: properties || null});
// null for trait
if (!isTrait) {
Object.defineProperty(constructor, "initializer", {value: initializer});
Object.defineProperty(initializer, "baseInitializer", {value: baseInitializer});
Object.seal(initializer);
}
Object.seal(constructor);
return constructor;
}
// as separate function to reduce scope
function createConstructor(proto, initializer) {
return function () {
var o = Object.create(proto);
if (initializer != null) {
initializer.apply(o, arguments);
}
var constructor = createConstructor(proto, initializer);
Object.defineProperty(constructor, "proto", {value: proto});
Object.defineProperty(constructor, "properties", {value: properties || null});
// null for trait
if (!isTrait) {
Object.defineProperty(constructor, "initializer", {value: initializer});
Object.seal(o);
return o;
};
Object.defineProperty(initializer, "baseInitializer", {value: baseInitializer});
Object.freeze(initializer);
}
function computeProto(bases, properties) {
var proto = null;
for (var i = 0, n = bases.length; i < n; i++) {
var base = bases[i];
var baseProto = base.proto;
if (baseProto == null || base.properties == null) {
continue;
}
if (!proto) {
proto = Object.create(baseProto, properties || undefined);
continue;
}
// chrome bug related to getOwnPropertyDescriptor (sometimes returns undefined), so, we keep properties
//var names = Object.getOwnPropertyNames(baseProto);
//for (var j = 0, k = names.length; j < k; j++) {
// var descriptor = Object.getOwnPropertyDescriptor(baseProto, names[i]);
// Object.defineProperty(proto, names[i], descriptor);
//}
Object.defineProperties(proto, base.properties);
// todo test A -> B, C(->D) *properties from D is not yet added to proto*
}
return proto;
}
return create;
})();
Object.freeze(constructor);
return constructor;
};
Kotlin.createObject = function (initializer, properties) {
var o = Object.create(null, properties || undefined);
@@ -128,7 +115,7 @@ var Kotlin = {};
};
Kotlin.$createClass = function (parent, properties) {
if (typeof (parent) != "function") {
if (parent !== null && typeof (parent) != "function") {
properties = parent;
parent = null;
}