From 95e3080cc7bd7625d1ffdfe94493ee4b4ecd5634 Mon Sep 17 00:00:00 2001 From: pTalanov Date: Tue, 5 Jun 2012 19:22:29 +0400 Subject: [PATCH] Manually assemble kotlinLib.js from ecma version independent and dependent parts and it to dist --- build.xml | 6 +- .../testFiles/kotlinFullLib_ecma3.js | 1136 +++++++++++++++++ 2 files changed, 1139 insertions(+), 3 deletions(-) create mode 100644 js/js.translator/testFiles/kotlinFullLib_ecma3.js diff --git a/build.xml b/build.xml index 8e935efa548..74725194b7c 100644 --- a/build.xml +++ b/build.xml @@ -1,9 +1,9 @@ - + - + @@ -141,7 +141,7 @@ - + diff --git a/js/js.translator/testFiles/kotlinFullLib_ecma3.js b/js/js.translator/testFiles/kotlinFullLib_ecma3.js new file mode 100644 index 00000000000..181b2be678d --- /dev/null +++ b/js/js.translator/testFiles/kotlinFullLib_ecma3.js @@ -0,0 +1,1136 @@ +/* Prototype JavaScript framework, version 1.6.1 + * (c) 2005-2009 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * + *--------------------------------------------------------------------------*/ +var Kotlin = {}; + +(function () { + "use strict"; + var emptyFunction = function () { + }; + + function $A(iterable) { + if (!iterable) return []; + if ('toArray' in Object(iterable)) return iterable.toArray(); + var length = iterable.length || 0, results = new Array(length); + while (length--) results[length] = iterable[length]; + return results; + } + + (function () { + function extend(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; + } + + function keys(object) { + var results = []; + for (var property in object) { + if (object.hasOwnProperty(property)) { + results.push(property); + } + } + return results; + } + + function values(object) { + var results = []; + for (var property in object) { + results.push(object[property]); + } + return results; + } + + extend(Object, { + extend: extend, + keys: Object.keys || keys, + values: values + }); + })(); + + Object.extend(Function.prototype, (function () { + var slice = Array.prototype.slice; + + function update(array, args) { + var arrayLength = array.length, length = args.length; + while (length--) array[arrayLength + length] = args[length]; + return array; + } + + function merge(array, args) { + array = slice.call(array, 0); + return update(array, args); + } + + function argumentNames() { + var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] + .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') + .replace(/\s+/g, '').split(','); + return names.length == 1 && !names[0] ? [] : names; + } + + function bind(context) { + if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; + var __method = this, args = slice.call(arguments, 1); + return function () { + var a = merge(args, arguments); + return __method.apply(context, a); + }; + } + + function bindAsEventListener(context) { + var __method = this, args = slice.call(arguments, 1); + return function (event) { + var a = update([event || window.event], args); + return __method.apply(context, a); + }; + } + + function wrap(wrapper) { + var __method = this; + return function () { + var a = update([__method.bind(this)], arguments); + return wrapper.apply(this, a); + }; + } + + return { + argumentNames: argumentNames, + bind: bind, + bindAsEventListener: bindAsEventListener, + wrap: wrap + }; + })()); + + Kotlin.isType = function (object, klass) { + if (object === null) { + return false; + } + + var current = object.get_class(); + while (current !== klass) { + if (current === null) { + return false; + } + current = current.superclass; + } + return true; + }; + + Kotlin.createTrait = (function () { + function add(object, source) { + var properties = Object.keys(source); + for (var i = 0, length = properties.length; i < length; i++) { + var property = properties[i]; + object[property] = source[property]; + } + return this; + } + + return function () { + var result = {}; + for (var i = 0, length = arguments.length; i < length; i++) { + add(result, arguments[i]); + } + return result; + } + })(); + + Kotlin.createNamespace = function () { + return Kotlin.createTrait.apply(null, arguments); + }; + + Kotlin.createClass = (function () { + var METHODS = {addMethods: addMethods}; + + function subclass() { + } + + function create() { + var parent = null, properties = $A(arguments); + if (typeof (properties[0]) == "function") { + parent = properties.shift(); + } + + function klass() { + this.initializing = klass; + if (this.initialize) { + this.initialize.apply(this, arguments); + } + } + + Object.extend(klass, METHODS); + klass.superclass = parent; + klass.subclasses = []; + + if (parent) { + subclass.prototype = parent.prototype; + klass.prototype = new subclass(); + parent.subclasses.push(klass); + } + + klass.addMethods( + { + get_class: function () { + return klass; + } + }); + + if (parent !== null) { + klass.addMethods( + { + super_init: function () { + this.initializing = this.initializing.superclass; + this.initializing.prototype.initialize.apply(this, arguments); + } + }); + } + + for (var i = 0, length = properties.length; i < length; i++) { + klass.addMethods(properties[i]); + } + + if (!klass.prototype.initialize) { + klass.prototype.initialize = emptyFunction; + } + + klass.prototype.constructor = klass; + return klass; + } + + function addMethods(source) { + var ancestor = this.superclass && this.superclass.prototype, + properties = Object.keys(source); + + + for (var i = 0, length = properties.length; i < length; i++) { + var property = properties[i], value = source[property]; + if (ancestor && (typeof (value) == "function") && + value.argumentNames()[0] == "$super") { + var method = value; + value = (function (m) { + return function () { + return ancestor[m].apply(this, arguments); + }; + })(property).wrap(method); + + } + this.prototype[property] = value; + } + + return this; + } + + return create; + })(); + + Kotlin.$createClass = Kotlin.createClass; + + Kotlin.$new = function (f) { + var o = {'__proto__': f.prototype}; + return function () { + f.apply(o, arguments); + return o; + }; + }; + + Kotlin.createObject = function () { + var singletonClass = Kotlin.createClass.apply(null, arguments); + return new singletonClass(); + }; +})(); + +/** + * Copyright 2010 Tim Down. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +(function () { + "use strict"; + + Kotlin.equals = function (obj1, obj2) { + if (typeof obj1 == "object") { + if (obj1.equals !== undefined) { + return obj1.equals(obj2); + } + } + return (obj1 === obj2); + }; + + Kotlin.defs = {}; + Kotlin.Exceptions = {}; + Kotlin.Exception = Kotlin.$createClass(); + Kotlin.RuntimeException = Kotlin.$createClass(Kotlin.Exception); + Kotlin.Exceptions.IndexOutOfBounds = Kotlin.$createClass(Kotlin.Exception); + Kotlin.Exceptions.NullPointerException = Kotlin.$createClass(Kotlin.Exception); + Kotlin.Exceptions.NoSuchElementException = Kotlin.$createClass(Kotlin.Exception); + Kotlin.Exceptions.IllegalArgumentException = Kotlin.$createClass(Kotlin.Exception); + Kotlin.Exceptions.IllegalStateException = Kotlin.$createClass(Kotlin.Exception); + Kotlin.Exceptions.IndexOutOfBoundsException = Kotlin.$createClass(Kotlin.Exception); + Kotlin.Exceptions.UnsupportedOperationException = Kotlin.$createClass(Kotlin.Exception); + + Kotlin.throwNPE = function() { + 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; + } + }); + + Kotlin.ArrayList = Kotlin.$createClass({ + 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; + }, + size:function () { + return this.$size; + }, + iterator:function () { + return Kotlin.$new(Kotlin.ArrayIterator)(this); + }, + isEmpty:function () { + return (this.$size === 0); + }, + add:function (element) { + this.array[this.$size++] = element; + }, + 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) { + 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; + } + }); + + + Kotlin.parseInt = function (str) { + return parseInt(str, 10); + } + ; + + Kotlin.safeParseInt = function(str) { + var r = parseInt(str, 10); + return isNaN(r) ? null : r; + }; + + Kotlin.safeParseDouble = function(str) { + var r = parseFloat(str, 10); + return isNaN(r) ? null : r; + }; + + Kotlin.System = function () { + var output = ""; + + var print = function (obj) { + if (obj !== undefined) { + if (obj === null || typeof obj !== "object") { + output += obj; + } + else { + output += obj.toString(); + } + } + }; + var println = function (obj) { + this.print(obj); + output += "\n"; + }; + + return { + out:function () { + return { + print:print, + println:println + }; + }, + output:function () { + return output; + }, + flush:function () { + output = ""; + } + }; + }(); + + Kotlin.println = function (s) { + Kotlin.System.out().println(s); + }; + + Kotlin.print = function (s) { + 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) { + this.$start = start; + this.$count = count; + this.$reversed = reversed; + this.$i = this.get_start(); + }, get_start:function () { + return this.$start; + }, get_count:function () { + return this.$count; + }, set_count:function (tmp$0) { + this.$count = tmp$0; + }, get_reversed:function () { + return this.$reversed; + }, get_i:function () { + return this.$i; + }, set_i:function (tmp$0) { + this.$i = tmp$0; + }, next:function () { + this.set_count(this.get_count() - 1); + if (this.get_reversed()) { + this.set_i(this.get_i() - 1); + return this.get_i() + 1; + } + else { + this.set_i(this.get_i() + 1); + return this.get_i() - 1; + } + }, + get_hasNext: function () { + return this.get_count() > 0; + } + }); + + 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()); + } + }); + + Kotlin.Comparator = Kotlin.$createClass( + { + initialize: function () { + }, + compare: function (el1, el2) { + throw Kotlin.$new(Kotlin.AbstractFunctionInvocationError)(); + } + } + ); + + Kotlin.comparator = function (f) { + var result = Kotlin.$new(Kotlin.Comparator)(); + result.compare = f; + return result; + }; + + Kotlin.collectionsMax = function (col, comp) { + var it = col.iterator(); + if (col.isEmpty()) { + //TODO: which exception? + throw Kotlin.Exception(); + } + var max = it.next(); + while (it.get_hasNext()) { + var el = it.next(); + if (comp.compare(max, el) < 0) { + max = el; + } + } + return max; + }; + + Kotlin.StringBuilder = Kotlin.$createClass( + { + initialize:function () { + this.string = ""; + }, + append:function (obj) { + this.string = this.string + obj.toString(); + }, + toString:function () { + return this.string; + } + } + ); + + Kotlin.splitString = function (str, regex) { + return str.split(regex); + }; + + Kotlin.nullArray = function (size) { + var res = []; + var i = size; + while (i > 0) { + res[--i] = null; + } + return res; + }; + + Kotlin.arrayFromFun = function (size, initFun) { + var res = []; + var i = size; + while (i > 0) { + res[--i] = initFun(i); + } + return res; + }; + + Kotlin.arrayIndices = function (arr) { + 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.toString = function (obj) { + return obj.toString(); + }; + + Kotlin.jsonFromTuples = function (pairArr) { + var i = pairArr.length; + var res = {}; + while (i > 0) { + --i; + res[pairArr[i][0]] = pairArr[i][1]; + } + return res; + }; + + //TODO: use intrinsic + Kotlin.jsonSet = function (obj, attrName, value) { + obj[attrName] = value; + }; + + Kotlin.jsonGet = function (obj, attrName) { + return obj[attrName]; + }; + + + Kotlin.jsonAddProperties = function (obj1, obj2) { + for (var p in obj2) { + if (obj2.hasOwnProperty(p)) { + obj1[p] = obj2[p]; + } + } + return obj1; + }; + + //TODO: use intrinsic + Kotlin.sure = function (obj) { + return obj; + }; + + (function () { + var FUNCTION = "function"; + + var arrayRemoveAt = (typeof Array.prototype.splice == FUNCTION) ? + function (arr, idx) { + arr.splice(idx, 1); + } : + + function (arr, idx) { + var itemsAfterDeleted, i, len; + if (idx === arr.length - 1) { + arr.length = idx; + } + else { + itemsAfterDeleted = arr.slice(idx + 1); + arr.length = idx; + for (i = 0, len = itemsAfterDeleted.length; i < len; ++i) { + arr[idx + i] = itemsAfterDeleted[i]; + } + } + }; + + function hashObject(obj) { + var hashCode; + if (typeof obj == "string") { + return obj; + } else if (typeof obj.hashCode == FUNCTION) { + // Check the hashCode method really has returned a string + hashCode = obj.hashCode(); + return (typeof hashCode == "string") ? hashCode : hashObject(hashCode); + } else if (typeof obj.toString == FUNCTION) { + return obj.toString(); + } + else { + try { + return String(obj); + } catch (ex) { + // For host objects (such as ActiveObjects in IE) that have no toString() method and throw an error when + // passed to String() + return Object.prototype.toString.call(obj); + } + } + } + + function equals_fixedValueHasEquals(fixedValue, variableValue) { + return fixedValue.equals(variableValue); + } + + function equals_fixedValueNoEquals(fixedValue, variableValue) { + return (typeof variableValue.equals == FUNCTION) ? + variableValue.equals(fixedValue) : (fixedValue === variableValue); + } + + function createKeyValCheck(kvStr) { + return function (kv) { + if (kv === null) { + throw new Error("null is not a valid " + kvStr); + } else if (typeof kv == "undefined") { + throw new Error(kvStr + " must not be undefined"); + } + }; + } + + var checkKey = createKeyValCheck("key"), checkValue = createKeyValCheck("value"); + + /*----------------------------------------------------------------------------------------------------------------*/ + + function Bucket(hash, firstKey, firstValue, equalityFunction) { + this[0] = hash; + this.entries = []; + this.addEntry(firstKey, firstValue); + + if (equalityFunction !== null) { + this.getEqualityFunction = function () { + return equalityFunction; + }; + } + } + + var EXISTENCE = 0, ENTRY = 1, ENTRY_INDEX_AND_VALUE = 2; + + function createBucketSearcher(mode) { + return function (key) { + var i = this.entries.length, entry, equals = this.getEqualityFunction(key); + while (i--) { + entry = this.entries[i]; + if (equals(key, entry[0])) { + switch (mode) { + case EXISTENCE: + return true; + case ENTRY: + return entry; + case ENTRY_INDEX_AND_VALUE: + return [ i, entry[1] ]; + } + } + } + return false; + }; + } + + function createBucketLister(entryProperty) { + return function (aggregatedArr) { + var startIndex = aggregatedArr.length; + for (var i = 0, len = this.entries.length; i < len; ++i) { + aggregatedArr[startIndex + i] = this.entries[i][entryProperty]; + } + }; + } + + Bucket.prototype = { + getEqualityFunction:function (searchValue) { + return (typeof searchValue.equals == FUNCTION) ? equals_fixedValueHasEquals : equals_fixedValueNoEquals; + }, + + getEntryForKey:createBucketSearcher(ENTRY), + + getEntryAndIndexForKey:createBucketSearcher(ENTRY_INDEX_AND_VALUE), + + removeEntryForKey:function (key) { + var result = this.getEntryAndIndexForKey(key); + if (result) { + arrayRemoveAt(this.entries, result[0]); + return result[1]; + } + return null; + }, + + addEntry:function (key, value) { + this.entries[this.entries.length] = [key, value]; + }, + + keys:createBucketLister(0), + + values:createBucketLister(1), + + getEntries:function (entries) { + var startIndex = entries.length; + for (var i = 0, len = this.entries.length; i < len; ++i) { + // Clone the entry stored in the bucket before adding to array + entries[startIndex + i] = this.entries[i].slice(0); + } + }, + + containsKey:createBucketSearcher(EXISTENCE), + + containsValue:function (value) { + var i = this.entries.length; + while (i--) { + if (value === this.entries[i][1]) { + return true; + } + } + return false; + } + }; + + /*----------------------------------------------------------------------------------------------------------------*/ + + // Supporting functions for searching hashtable buckets + + function searchBuckets(buckets, hash) { + var i = buckets.length, bucket; + while (i--) { + bucket = buckets[i]; + if (hash === bucket[0]) { + return i; + } + } + return null; + } + + function getBucketForHash(bucketsByHash, hash) { + var bucket = bucketsByHash[hash]; + + // Check that this is a genuine bucket and not something inherited from the bucketsByHash's prototype + return ( bucket && (bucket instanceof Bucket) ) ? bucket : null; + } + + /*----------------------------------------------------------------------------------------------------------------*/ + + var Hashtable = function (hashingFunctionParam, equalityFunctionParam) { + var that = this; + var buckets = []; + var bucketsByHash = {}; + + var hashingFunction = (typeof hashingFunctionParam == FUNCTION) ? hashingFunctionParam : hashObject; + var equalityFunction = (typeof equalityFunctionParam == FUNCTION) ? equalityFunctionParam : null; + + this.put = function (key, value) { + checkKey(key); + checkValue(value); + var hash = hashingFunction(key), bucket, bucketEntry, oldValue = null; + + // Check if a bucket exists for the bucket key + bucket = getBucketForHash(bucketsByHash, hash); + if (bucket) { + // Check this bucket to see if it already contains this key + bucketEntry = bucket.getEntryForKey(key); + if (bucketEntry) { + // This bucket entry is the current mapping of key to value, so replace old value and we're done. + oldValue = bucketEntry[1]; + bucketEntry[1] = value; + } + else { + // The bucket does not contain an entry for this key, so add one + bucket.addEntry(key, value); + } + } + else { + // No bucket exists for the key, so create one and put our key/value mapping in + bucket = new Bucket(hash, key, value, equalityFunction); + buckets[buckets.length] = bucket; + bucketsByHash[hash] = bucket; + } + return oldValue; + }; + + this.get = function (key) { + checkKey(key); + + var hash = hashingFunction(key); + + // Check if a bucket exists for the bucket key + var bucket = getBucketForHash(bucketsByHash, hash); + if (bucket) { + // Check this bucket to see if it contains this key + var bucketEntry = bucket.getEntryForKey(key); + if (bucketEntry) { + // This bucket entry is the current mapping of key to value, so return the value. + return bucketEntry[1]; + } + } + return null; + }; + + this.containsKey = function (key) { + checkKey(key); + var bucketKey = hashingFunction(key); + + // Check if a bucket exists for the bucket key + var bucket = getBucketForHash(bucketsByHash, bucketKey); + + return bucket ? bucket.containsKey(key) : false; + }; + + this.containsValue = function (value) { + checkValue(value); + var i = buckets.length; + while (i--) { + if (buckets[i].containsValue(value)) { + return true; + } + } + return false; + }; + + this.clear = function () { + buckets.length = 0; + bucketsByHash = {}; + }; + + this.isEmpty = function () { + return !buckets.length; + }; + + var createBucketAggregator = function (bucketFuncName) { + return function () { + var aggregated = [], i = buckets.length; + while (i--) { + buckets[i][bucketFuncName](aggregated); + } + return aggregated; + }; + }; + + this._keys = createBucketAggregator("keys"); + this._values = createBucketAggregator("values"); + this._entries = createBucketAggregator("getEntries"); + + this.values = function() { + var values = this._values(); + var i = values.length + var result = Kotlin.$new(Kotlin.ArrayList)(); + while (--i) { + result.add(values[i]); + } + return result; + }; + + this.remove = function (key) { + checkKey(key); + + var hash = hashingFunction(key), bucketIndex, oldValue = null; + + // Check if a bucket exists for the bucket key + var bucket = getBucketForHash(bucketsByHash, hash); + + if (bucket) { + // Remove entry from this bucket for this key + oldValue = bucket.removeEntryForKey(key); + if (oldValue !== null) { + // Entry was removed, so check if bucket is empty + if (!bucket.entries.length) { + // Bucket is empty, so remove it from the bucket collections + bucketIndex = searchBuckets(buckets, hash); + arrayRemoveAt(buckets, bucketIndex); + delete bucketsByHash[hash]; + } + } + } + return oldValue; + }; + + this.size = function () { + var total = 0, i = buckets.length; + while (i--) { + total += buckets[i].entries.length; + } + return total; + }; + + this.each = function (callback) { + var entries = that.entries(), i = entries.length, entry; + while (i--) { + entry = entries[i]; + callback(entry[0], entry[1]); + } + }; + + + this.putAll = function (hashtable, conflictCallback) { + var entries = hashtable.entries(); + var entry, key, value, thisValue, i = entries.length; + var hasConflictCallback = (typeof conflictCallback == FUNCTION); + while (i--) { + entry = entries[i]; + key = entry[0]; + value = entry[1]; + + // Check for a conflict. The default behaviour is to overwrite the value for an existing key + if (hasConflictCallback && (thisValue = that.get(key))) { + value = conflictCallback(key, thisValue, value); + } + that.put(key, value); + } + }; + + this.clone = function () { + var clone = new Hashtable(hashingFunctionParam, equalityFunctionParam); + clone.putAll(that); + return clone; + }; + + this.keySet = function () { + var res = Kotlin.$new(Kotlin.HashSet)(); + var keys = this._keys(); + var i = keys.length; + while (i--) { + res.add(keys[i]); + } + return res; + }; + }; + + Kotlin.HashTable = Hashtable; + })(); + + Kotlin.HashMap = Kotlin.$createClass( + { + initialize:function () { + Kotlin.HashTable.call(this); + } + } + ); + + + (function () { + function HashSet(hashingFunction, equalityFunction) { + var hashTable = new Kotlin.HashTable(hashingFunction, equalityFunction); + + this.add = function (o) { + hashTable.put(o, true); + }; + + this.addAll = function (arr) { + var i = arr.length; + while (i--) { + hashTable.put(arr[i], true); + } + }; + + this.values = function () { + return hashTable._keys(); + }; + + this.iterator = function () { + return Kotlin.arrayIterator(this.values()); + }; + + this.remove = function (o) { + return hashTable.remove(o) ? o : null; + }; + + this.contains = function (o) { + return hashTable.containsKey(o); + }; + + this.clear = function () { + hashTable.clear(); + }; + + this.size = function () { + return hashTable.size(); + }; + + this.isEmpty = function () { + return hashTable.isEmpty(); + }; + + this.clone = function () { + var h = new HashSet(hashingFunction, equalityFunction); + h.addAll(hashTable.keys()); + return h; + }; + + this.intersection = function (hashSet) { + var intersection = new HashSet(hashingFunction, equalityFunction); + var values = hashSet.values(), i = values.length, val; + while (i--) { + val = values[i]; + if (hashTable.containsKey(val)) { + intersection.add(val); + } + } + return intersection; + }; + + this.union = function (hashSet) { + var union = this.clone(); + var values = hashSet.values(), i = values.length, val; + while (i--) { + val = values[i]; + if (!hashTable.containsKey(val)) { + union.add(val); + } + } + return union; + }; + + this.isSubsetOf = function (hashSet) { + var values = hashTable.keys(), i = values.length; + while (i--) { + if (!hashSet.contains(values[i])) { + return false; + } + } + return true; + }; + } + + Kotlin.HashSet = Kotlin.$createClass({initialize: function () { + HashSet.call(this); + }}); + }()); +})();