diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 0ed2d1c2a22..85f139460c7 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -12,14 +12,30 @@ - + + + + + + + - - - - - - + + + + + + + + + + + + + + + + @@ -119,106 +135,94 @@ - + - - + + - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - - - - - - - - - - - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -228,24 +232,6 @@ - - - - - - - - - - - - - - - - - - @@ -285,12 +271,32 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -311,10 +317,10 @@ - + - + @@ -345,22 +351,22 @@ @@ -634,6 +640,32 @@ - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + @@ -1252,11 +1264,11 @@ - - - - - + + + + + localhost @@ -1344,7 +1356,7 @@ - + @@ -1392,7 +1404,7 @@ @@ -1439,128 +1451,114 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + diff --git a/jslib/src/core/annotations.kt b/jslib/src/core/annotations.kt new file mode 100644 index 00000000000..8d7c69cb06d --- /dev/null +++ b/jslib/src/core/annotations.kt @@ -0,0 +1,7 @@ +package js.annotations; + +annotation class NativeClass() {} +annotation class NativeFun(name : String) + +annotation class LibraryClass() {} +annotation class LibraryFun(name : String) {} \ No newline at end of file diff --git a/jslib/src/core/core.kt b/jslib/src/core/core.kt index b45d2aa786a..0b75d5eb4b7 100644 --- a/jslib/src/core/core.kt +++ b/jslib/src/core/core.kt @@ -1,10 +1,17 @@ package js; +import js.annotations.LibraryFun +import js.annotations.LibraryClass + +LibraryFun("println") fun println() +LibraryFun("println") fun println(s : Any?) +LibraryFun("print") fun print(s : Any?) - +LibraryFun("parseInt") fun parseInt(s : String) : Int - +LibraryClass open class Exception() +LibraryClass class NumberFormatException() : Exception() diff --git a/jslib/src/core/javautil.kt b/jslib/src/core/javautil.kt index 288446b236c..2acaad22beb 100644 --- a/jslib/src/core/javautil.kt +++ b/jslib/src/core/javautil.kt @@ -1,23 +1,35 @@ package java.util -import java.lang; -import js.annotations.LibraryClass +import js.annotations.*; + +//LibraryClass +//public trait Comparator { +// fun compare(obj1 : T, obj2 : T) : Int; +//} +// +//LibraryFun("comparator") +//public fun comparator(f : (T, T) -> Int) : Comparator {} +// +//LibraryFun("max") +//public fun max(col : Collection, comp : Comparator) {} + LibraryClass -public trait Iterator { - fun hasNext() : Boolean - fun next() : T +public open class Iterator() { + open fun next() : T {} + open fun hasNext() : Boolean {} } LibraryClass -public open class ArrayList() : java.util.List, java.util.AbstractList() { +public open class ArrayList() : java.util.List { override public fun size() : Int {} override public fun isEmpty() : Boolean {} override public fun contains(o : Any?) : Boolean {} - override public fun indexOf(o : Any?) : Int {} - override public fun lastIndexOf(o : Any?) : Int {} - override public fun toArray() : Array {} - override public fun toArray(a : Array) : Array {} + override public fun iterator() : Iterator {} + // override public fun indexOf(o : Any?) : Int {} + // override public fun lastIndexOf(o : Any?) : Int {} + // override public fun toArray() : Array {} + // override public fun toArray(a : Array) : Array {} override public fun get(index : Int) : E {} override public fun set(index : Int, element : E) : E {} override public fun add(e : E) : Boolean {} @@ -26,7 +38,7 @@ public open class ArrayList() : java.util.List, java.util.AbstractL override public fun remove(o : Any?) : Boolean {} override public fun clear() : Unit {} override public fun addAll(c : java.util.Collection) : Boolean {} - override public fun addAll(index : Int, c : java.util.Collection) : Boolean {} + // override public fun addAll(index : Int, c : java.util.Collection) : Boolean {} } LibraryClass @@ -34,15 +46,15 @@ public trait Collection : java.lang.Iterable { open fun size() : Int open fun isEmpty() : Boolean open fun contains(o : Any?) : Boolean - override fun iterator() : Iterator - open fun toArray() : Array - open fun toArray(a : Array) : Array + override fun iterator() : java.util.Iterator + // open fun toArray() : Array + // open fun toArray(a : Array) : Array open fun add(e : E) : Boolean open fun remove(o : Any?) : Boolean - open fun containsAll(c : java.util.Collection<*>) : Boolean + //open fun containsAll(c : java.util.Collection<*>) : Boolean open fun addAll(c : java.util.Collection) : Boolean - open fun removeAll(c : java.util.Collection<*>) : Boolean - open fun retainAll(c : java.util.Collection<*>) : Boolean + //open fun removeAll(c : java.util.Collection<*>) : Boolean + //open fun retainAll(c : java.util.Collection<*>) : Boolean open fun clear() : Unit } @@ -51,56 +63,24 @@ public trait List : java.util.Collection { override fun size() : Int override fun isEmpty() : Boolean override fun contains(o : Any?) : Boolean - override fun iterator() : Iterator - override fun toArray() : Array + override fun iterator() : java.util.Iterator + // override fun toArray() : Array // Simulate Java's array covariance - override fun toArray(a : Array) : Array + // override fun toArray(a : Array) : Array override fun add(e : E) : Boolean override fun remove(o : Any?) : Boolean - override fun containsAll(c : java.util.Collection<*>) : Boolean + // override fun containsAll(c : java.util.Collection<*>) : Boolean override fun addAll(c : java.util.Collection) : Boolean - open fun addAll(index : Int, c : java.util.Collection) : Boolean - override fun removeAll(c : java.util.Collection<*>) : Boolean - override fun retainAll(c : java.util.Collection<*>) : Boolean + // open fun addAll(index : Int, c : java.util.Collection) : 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 -} - -LibraryClass -abstract public class AbstractCollection protected () : java.util.Collection { - abstract override public fun iterator() : java.util.Iterator - abstract override public fun size() : Int - override public fun isEmpty() : Boolean {} - override public fun contains(o : Any?) : Boolean {} - override public fun toArray() : Array {} - override public fun toArray(a : Array) : Array {} - override public fun add(e : E) : Boolean {} - override public fun remove(o : Any?) : Boolean {} - override public fun containsAll(c : java.util.Collection<*>) : Boolean {} - override public fun addAll(c : java.util.Collection) : Boolean {} - override public fun removeAll(c : java.util.Collection<*>) : Boolean {} - override public fun retainAll(c : java.util.Collection<*>) : Boolean {} - override public fun clear() : Unit {} -} - -LibraryClass -abstract public open class AbstractList protected () : java.util.AbstractCollection(), java.util.List { - override public fun add(e : E) : Boolean {} - abstract override public fun get(index : Int) : E - override public fun set(index : Int, element : E) : E {} - override public fun add(index : Int, element : E) : Unit {} - override public fun remove(index : Int) : E {} - override public fun indexOf(o : Any?) : Int {} - override public fun lastIndexOf(o : Any?) : Int {} - override public fun clear() : Unit {} - override public fun addAll(index : Int, c : java.util.Collection) : Boolean {} - override public fun iterator() : Iterator {} - open protected fun removeRange(fromIndex : Int, toIndex : Int) : Unit {} + // open fun indexOf(o : Any?) : Int + // open fun lastIndexOf(o : Any?) : Int } LibraryClass @@ -108,38 +88,28 @@ public trait Set : java.util.Collection { override fun size() : Int override fun isEmpty() : Boolean override fun contains(o : Any?) : Boolean - override fun iterator() : Iterator - override fun toArray() : Array - override fun toArray(a : Array) : Array + override fun iterator() : java.util.Iterator + // override fun toArray() : Array + // override fun toArray(a : Array) : Array override fun add(e : E) : Boolean override fun remove(o : Any?) : Boolean - override fun containsAll(c : java.util.Collection<*>) : Boolean + //override fun containsAll(c : java.util.Collection<*>) : Boolean override fun addAll(c : java.util.Collection) : Boolean - override fun retainAll(c : java.util.Collection<*>) : Boolean - override fun removeAll(c : java.util.Collection<*>) : Boolean + //override fun retainAll(c : java.util.Collection<*>) : Boolean + //override fun removeAll(c : java.util.Collection<*>) : Boolean override fun clear() : Unit } -LibraryClass -abstract public class AbstractSet protected () : java.util.AbstractCollection(), java.util.Set { - override public fun removeAll(c : java.util.Collection<*>) : Boolean {} -} - LibraryClass public open class HashSet() : java.util.Set { - override public fun iterator() : Iterator {} + override public fun iterator() : java.util.Iterator {} override public fun size() : Int {} override public fun isEmpty() : Boolean {} override public fun contains(o : Any?) : Boolean {} override public fun add(e : E) : Boolean {} override public fun remove(o : Any?) : Boolean {} - override fun toArray() : Array {} - override fun toArray(a : Array) : Array {} - override fun containsAll(c : java.util.Collection<*>) : Boolean {} - override fun addAll(c : java.util.Collection) : Boolean {} - override fun retainAll(c : java.util.Collection<*>) : Boolean {} - override fun removeAll(c : java.util.Collection<*>) : Boolean {} - override fun clear() : Unit {} + override public fun clear() : Unit {} + override fun addAll(c : java.util.Collection) : Boolean } LibraryClass @@ -148,7 +118,7 @@ public trait Map { open fun isEmpty() : Boolean open fun containsKey(key : Any?) : Boolean open fun containsValue(value : Any?) : Boolean - open fun get(key : Any?) : V + open fun get(key : Any?) : V? open fun put(key : K, value : V) : V? open fun remove(key : Any?) : V? open fun putAll(m : java.util.Map) : Unit @@ -157,28 +127,13 @@ public trait Map { open fun values() : java.util.Collection } -LibraryClass -abstract public open class AbstractMap protected () : java.util.Map { - override public fun size() : Int {} - override public fun isEmpty() : Boolean {} - override public fun containsValue(value : Any?) : Boolean {} - override public fun containsKey(key : Any?) : Boolean {} - override public fun get(key : Any?) : V {} - override public fun put(key : K, value : V) : V? {} - override public fun remove(key : Any?) : V? {} - override public fun putAll(m : java.util.Map) : Unit {} - override public fun clear() : Unit {} - override public fun keySet() : java.util.Set {} - override public fun values() : java.util.Collection {} -} - LibraryClass public open class HashMap() : java.util.Map { override public fun size() : Int {} override public fun isEmpty() : Boolean {} override public fun get(key : Any?) : V {} override public fun containsKey(key : Any?) : Boolean {} - override public fun put(key : K, value : V) : V? {} + override public fun put(key : K, value : V) : V {} override public fun putAll(m : java.util.Map) : Unit {} override public fun remove(key : Any?) : V? {} override public fun clear() : Unit {} @@ -192,3 +147,4 @@ public class StringBuilder() { public fun append(obj : Any) : StringBuilder public fun toString() : String } + diff --git a/jslib/src/core/json.kt b/jslib/src/core/json.kt new file mode 100644 index 00000000000..b427d861516 --- /dev/null +++ b/jslib/src/core/json.kt @@ -0,0 +1,11 @@ +package js + +import java.util.*; + +class Json() { + fun set(paramName : String, value : Any?) {} + fun get(paramName : String) : Any? = null +} + +fun Map.toJson() : Json = Json() +fun json(vararg pairs : Tuple2) = Json() diff --git a/jslib/src/jquery/common.kt b/jslib/src/jquery/common.kt index 07913e69e55..271c4835d6c 100644 --- a/jslib/src/jquery/common.kt +++ b/jslib/src/jquery/common.kt @@ -2,17 +2,21 @@ package jquery; import js.annotations.*; -fun JQuery.toString() = "" - NativeClass class JQuery() { fun addClass(className : String) : JQuery = this; fun addClass(f : DomElement.(Int, String)->String) = this; - fun attr(attrName : String) = "" - fun attr(attrName : String, value : String) = this + + fun attr(attrName : String) = ""; + fun attr(attrName : String, value : String) = this; + + fun html() : String = ""; + fun html(s : String) = this; + fun html(f : DomElement.(Int, String)->String) = this; + + fun hasClass(className : String) = true fun removeClass(className : String) = this - fun html() : String = "" fun height() = 0 fun width() = 0 fun click() = this; diff --git a/jslib/src/raphael/raphael.kt b/jslib/src/raphael/raphael.kt new file mode 100644 index 00000000000..2050097e701 --- /dev/null +++ b/jslib/src/raphael/raphael.kt @@ -0,0 +1,34 @@ +package raphael + +import js.annotations.*; +import js.*; + +NativeClass +class Element() { + + fun attr(name : String, value : String) : Element = this + fun attr(nameToValue : Json) : Element = this + + fun mouseover(handler : () -> Unit) = this + + fun getTotalLength() : Double = 0.0 + //fun mouse +} + +NativeClass +class Paper() { + fun path(pathString : String) : Element = Element(); + fun path() : Element = Element(); + + fun ellipse(x : Int, y : Int, rx : Int, ry : Int) : Element = Element(); +} + +NativeFun("Raphael") +fun Raphael(elementId : String, width : Int, height : Int) : Paper = Paper(); +NativeFun("Raphael") +fun Raphael(elementId : String, width : Int, height : Int, initFun : Paper.() -> Unit) : Unit {} + +NativeClass +val Raphael = object { + fun getColor() : String = "" +} diff --git a/translator/src/org/jetbrains/k2js/config/Config.java b/translator/src/org/jetbrains/k2js/config/Config.java index 394e6e91ca5..845b6d0dd4c 100644 --- a/translator/src/org/jetbrains/k2js/config/Config.java +++ b/translator/src/org/jetbrains/k2js/config/Config.java @@ -28,7 +28,9 @@ public abstract class Config { PATH_TO_JS_LIB_SRC + "\\jquery\\common.kt", PATH_TO_JS_LIB_SRC + "\\core\\javautil.kt", PATH_TO_JS_LIB_SRC + "\\core\\javalang.kt", - PATH_TO_JS_LIB_SRC + "\\core\\core.kt" + PATH_TO_JS_LIB_SRC + "\\core\\core.kt", + PATH_TO_JS_LIB_SRC + "\\raphael\\raphael.kt", + PATH_TO_JS_LIB_SRC + "\\core\\json.kt" ); diff --git a/translator/test/org/jetbrains/k2js/test/KotlinLibTest.java b/translator/test/org/jetbrains/k2js/test/KotlinLibTest.java index b31554eba27..2497bd5d1b4 100644 --- a/translator/test/org/jetbrains/k2js/test/KotlinLibTest.java +++ b/translator/test/org/jetbrains/k2js/test/KotlinLibTest.java @@ -2,7 +2,6 @@ package org.jetbrains.k2js.test; import org.junit.Test; import org.mozilla.javascript.Context; -import org.mozilla.javascript.Function; import org.mozilla.javascript.Scriptable; import java.util.Arrays; @@ -38,29 +37,6 @@ public class KotlinLibTest extends TranslationTest { //TODO: refactor - @Test - public void classObjectHasCreateMethod() throws Exception { - final Map> propertyToType - = new HashMap>(); - propertyToType.put("create", Function.class); - runPropertyTypeCheck("Class", propertyToType); - } - - @Test - public void namespaceObjectHasCreateMethod() throws Exception { - final Map> propertyToType - = new HashMap>(); - propertyToType.put("create", Function.class); - runPropertyTypeCheck("Namespace", propertyToType); - } - - @Test - public void traitObjectHasCreateMethod() throws Exception { - final Map> propertyToType - = new HashMap>(); - propertyToType.put("create", Function.class); - runPropertyTypeCheck("Trait", propertyToType); - } @Test public void createdTraitIsJSObject() throws Exception { diff --git a/translator/test/org/jetbrains/k2js/test/StdlibTest.java b/translator/test/org/jetbrains/k2js/test/StdlibTest.java index 096be4fbffd..18deb7d29ce 100644 --- a/translator/test/org/jetbrains/k2js/test/StdlibTest.java +++ b/translator/test/org/jetbrains/k2js/test/StdlibTest.java @@ -1,7 +1,5 @@ package org.jetbrains.k2js.test; -import org.junit.Test; - /** * @author Pavel Talanov */ @@ -13,9 +11,9 @@ public final class StdlibTest extends TranslationTest { return MAIN; } - //TODO: test! - @Test - public void filter() throws Exception { - // testFooBoxIsTrue("Filter.kt"); - } + //TODO: cant do due to big java dependencies +// @Test +// public void filter() throws Exception { +// testFooBoxIsTrue("Filter.kt"); +// } } diff --git a/translator/test/org/jetbrains/k2js/test/WebDemoExamples2Test.java b/translator/test/org/jetbrains/k2js/test/WebDemoExamples2Test.java index f569816bbe9..c4b46d4dce3 100644 --- a/translator/test/org/jetbrains/k2js/test/WebDemoExamples2Test.java +++ b/translator/test/org/jetbrains/k2js/test/WebDemoExamples2Test.java @@ -20,7 +20,7 @@ public final class WebDemoExamples2Test extends TranslationTest { testWithMain("bottles", ""); } - //TODO: a couple of classes not supported + //TODO: a couple of classes not supported and objects // @Test // public void life() throws Exception { // testWithMain("life", "", "2"); @@ -31,4 +31,10 @@ public final class WebDemoExamples2Test extends TranslationTest { testWithMain("builder", ""); testWithMain("builder", "1", "over9000"); } + + //TODO: comparator dependencies +// @Test +// public void maze() throws Exception { +// testWithMain("maze", ""); +// } } diff --git a/translator/testFiles/java/arrayList/cases/max.kt b/translator/testFiles/java/arrayList/cases/max.kt new file mode 100644 index 00000000000..50098e82059 --- /dev/null +++ b/translator/testFiles/java/arrayList/cases/max.kt @@ -0,0 +1,8 @@ +package foo + +import java.util.Collection; +import java.util.Comparator. + +fun max(col :Collection, ) { + +} \ No newline at end of file diff --git a/translator/testFiles/kotlinLib/cases/isAncestorType.js b/translator/testFiles/kotlinLib/cases/isAncestorType.js index 29fea2ff1b1..6473de60fce 100644 --- a/translator/testFiles/kotlinLib/cases/isAncestorType.js +++ b/translator/testFiles/kotlinLib/cases/isAncestorType.js @@ -1,7 +1,7 @@ -var A = Class.create(); -var B = Class.create(A); +var A = Kotlin.Class.create(); +var B = Kotlin.Class.create(A); var b = new B; test = function() { - return (isType(b, A) && isType(b, B)); + return (Kotlin.isType(b, A) && Kotlin.isType(b, B)); } \ No newline at end of file diff --git a/translator/testFiles/kotlinLib/cases/isComplexTest.js b/translator/testFiles/kotlinLib/cases/isComplexTest.js index c935e77afc0..9af77ce6b2c 100644 --- a/translator/testFiles/kotlinLib/cases/isComplexTest.js +++ b/translator/testFiles/kotlinLib/cases/isComplexTest.js @@ -1,22 +1,22 @@ -var A = Class.create(); -var B = Class.create(A); +var A = Kotlin.Class.create(); +var B = Kotlin.Class.create(A); var b = new B; -var C = Class.create(B); +var C = Kotlin.Class.create(B); var c = new C; -var E = Class.create(A) +var E = Kotlin.Class.create(A) var e = new E; test1 = function() { b2 = b - return (isType(b, A) && isType(b, B)); + return (Kotlin.isType(b, A) && Kotlin.isType(b, B)); } test2 = function() { - return (isType(c, C) && isType(c, B) && isType(c, A) && (!isType(c, E))); + return (Kotlin.isType(c, C) && Kotlin.isType(c, B) && Kotlin.isType(c, A) && (!Kotlin.isType(c, E))); } test3 = function() { - return isType(e, E) && !isType(e, B) && !isType(e, C) && isType(e, A) + return Kotlin.isType(e, E) && !Kotlin.isType(e, B) && !Kotlin.isType(e, C) && Kotlin.isType(e, A) } test = function() { diff --git a/translator/testFiles/kotlinLib/cases/isNotOtherType.js b/translator/testFiles/kotlinLib/cases/isNotOtherType.js index 624f1584c89..f9abb7f314f 100644 --- a/translator/testFiles/kotlinLib/cases/isNotOtherType.js +++ b/translator/testFiles/kotlinLib/cases/isNotOtherType.js @@ -1,6 +1,6 @@ -var A = Class.create(); -var B = Class.create(A); -var C = Class.create(); +var A = Kotlin.Class.create(); +var B = Kotlin.Class.create(A); +var C = Kotlin.Class.create(); var c = new C; test = function() { diff --git a/translator/testFiles/kotlinLib/cases/isSameType.js b/translator/testFiles/kotlinLib/cases/isSameType.js index bb8dfb4e7db..cd5529d401f 100644 --- a/translator/testFiles/kotlinLib/cases/isSameType.js +++ b/translator/testFiles/kotlinLib/cases/isSameType.js @@ -1,6 +1,6 @@ -var A = Class.create(); +var A = Kotlin.Class.create(); var a = new A; test = function() { - return isType(a, A); + return Kotlin.isType(a, A); } \ No newline at end of file diff --git a/translator/testFiles/kotlinLib/cases/namespace.js b/translator/testFiles/kotlinLib/cases/namespace.js index 4e028424b2f..5601936ffb1 100644 --- a/translator/testFiles/kotlinLib/cases/namespace.js +++ b/translator/testFiles/kotlinLib/cases/namespace.js @@ -1,4 +1,4 @@ -foo = Namespace.create({initialize:function(){ +foo = Kotlin.Namespace.create({initialize:function(){ } , box:function(){ return !false; diff --git a/translator/testFiles/kotlinLib/cases/namespaceWithClasses.js b/translator/testFiles/kotlinLib/cases/namespaceWithClasses.js index 4d85b782583..d2ca875bcef 100644 --- a/translator/testFiles/kotlinLib/cases/namespaceWithClasses.js +++ b/translator/testFiles/kotlinLib/cases/namespaceWithClasses.js @@ -1,6 +1,6 @@ { classes = function(){ - var A = Class.create({initialize:function(){ + var A = Kotlin.Class.create({initialize:function(){ this.$order = ''; { this.set_order(this.get_order() + 'A'); @@ -13,14 +13,14 @@ return this.$order; } }); - var B = Class.create(A, {initialize:function(){ + var B = Kotlin.Class.create(A, {initialize:function(){ this.super_init(); { this.set_order(this.get_order() + 'B'); } } }); - var C = Class.create(B, {initialize:function(){ + var C = Kotlin.Class.create(B, {initialize:function(){ this.super_init(); { this.set_order(this.get_order() + 'C'); @@ -30,7 +30,7 @@ return {A:A, B:B, C:C}; } (); - foo = Namespace.create(classes, {initialize:function(){ + foo = Kotlin.Namespace.create(classes, {initialize:function(){ } , box:function(){ return (new foo.C).get_order() === 'ABC' && (new foo.B).get_order() === 'AB' && (new foo.A).get_order() === 'A'; @@ -38,8 +38,6 @@ }); } - - function test() { return foo.box() } diff --git a/translator/testFiles/kotlinLib/cases/trait.js b/translator/testFiles/kotlinLib/cases/trait.js index f1efec21a20..3eb670980dd 100644 --- a/translator/testFiles/kotlinLib/cases/trait.js +++ b/translator/testFiles/kotlinLib/cases/trait.js @@ -1,10 +1,10 @@ foo = {}; (function(foo){ - foo.Test = Trait.create({addFoo:function(s){ + foo.Test = Kotlin.Trait.create({addFoo:function(s){ return s + 'FOO'; } }); - foo.ExtendedTest = Trait.create(foo.Test, {hooray:function(){ + foo.ExtendedTest = Kotlin.Trait.create(foo.Test, {hooray:function(){ return 'hooray'; } }); diff --git a/translator/testFiles/kotlin_lib.js b/translator/testFiles/kotlin_lib.js index cc4d2188044..7f8b4e3ba28 100644 --- a/translator/testFiles/kotlin_lib.js +++ b/translator/testFiles/kotlin_lib.js @@ -1,1035 +1,1050 @@ -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 $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 keys(object) { - if (Type(object) !== OBJECT_TYPE) { - throw new TypeError(); + + function extend(destination, source) { + for (var property in source) + destination[property] = source[property]; + return destination; } - var results = []; - for (var property in object) { - if (object.hasOwnProperty(property)) { - results.push(property); + + + function keys(object) { + if (Type(object) !== OBJECT_TYPE) { + throw new TypeError(); + } + 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); } } - 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 - } -})()); - -var isType = function (object, klass) { - current = object.get_class(); - while (current !== klass) { - if (current === null) { - return false; - } - current = current.superclass; - } - return true; -} - -var emptyFunction = function () { -} - -var Class = (function () { - - function subclass() { - } - - ; - function create() { - var parent = null, properties = $A(arguments); - if (typeof (properties[0]) == "function") - parent = properties.shift(); - - function klass() { - this.initializing = klass; - this.initialize.apply(this, arguments); + 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); + } } - Object.extend(klass, Class.Methods); - klass.superclass = parent; - klass.subclasses = []; - - if (parent) { - subclass.prototype = parent.prototype; - klass.prototype = new subclass; - parent.subclasses.push(klass); + function wrap(wrapper) { + var __method = this; + return function () { + var a = update([__method.bind(this)], arguments); + return wrapper.apply(this, a); + } } - klass.addMethods( - { - get_class:function () { - return klass; - } - }); + return { + argumentNames:argumentNames, + bind:bind, + bindAsEventListener:bindAsEventListener, + wrap:wrap + } + })()); + + var isType = function (object, klass) { + current = object.get_class(); + while (current !== klass) { + if (current === null) { + return false; + } + current = current.superclass; + } + return true; + } + + var emptyFunction = function () { + } + + var Class = (function () { + + function subclass() { + } + + ; + function create() { + var parent = null, properties = $A(arguments); + if (typeof (properties[0]) == "function") + parent = properties.shift(); + + function klass() { + this.initializing = klass; + this.initialize.apply(this, arguments); + } + + Object.extend(klass, Class.Methods); + klass.superclass = parent; + klass.subclasses = []; + + if (parent) { + subclass.prototype = parent.prototype; + klass.prototype = new subclass; + parent.subclasses.push(klass); + } - if (parent != null) { klass.addMethods( { - super_init:function () { - this.initializing = this.initializing.superclass; - this.initializing.prototype.initialize.apply(this, arguments) + 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; } - for (var i = 0, length = properties.length; i < length; i++) - klass.addMethods(properties[i]); + function addMethods(source) { + var ancestor = this.superclass && this.superclass.prototype, + properties = Object.keys(source); - if (!klass.prototype.initialize) - klass.prototype.initialize = emptyFunction; - klass.prototype.constructor = klass; - return klass; - } + 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); - function addMethods(source) { - var ancestor = this.superclass && this.superclass.prototype, + } + this.prototype[property] = value; + } + + return this; + } + + return { + create:create, + Methods:{ + addMethods:addMethods + } + }; + })(); + + var Trait = (function () { + + function add(object, source) { 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); - + for (var i = 0, length = properties.length; i < length; i++) { + var property = properties[i]; + var value = source[property]; + object[property] = value; } - this.prototype[property] = value; + return this; } - return this; - } + function create() { - return { - create:create, - Methods:{ - addMethods:addMethods + result = {} + for (var i = 0, length = arguments.length; i < length; i++) { + add(result, arguments[i]); + } + return result; } + + return { + create:create + }; + })(); + + + var Namespace = (function () { + + function create() { + return Trait.create.apply(Trait, arguments); + } + + return { + create:create + }; + })(); + + Kotlin = {} + Kotlin.Class = Class; + Kotlin.Namespace = Namespace; + Kotlin.Trait = Trait; + Kotlin.isType = isType; + + Kotlin.equals = function (obj1, obj2) { + if (typeof obj1 == "object") { + if (obj1.equals != undefined) { + return obj1.equals(obj2); + } + } + return (obj1 === obj2); }; -})(); -var Trait = (function () { - - function add(object, source) { - properties = Object.keys(source); - for (var i = 0, length = properties.length; i < length; i++) { - var property = properties[i]; - var value = source[property]; - object[property] = value; + Kotlin.Exceptions = {} + Kotlin.Exception = Kotlin.Class.create(); + Kotlin.Exceptions.IndexOutOfBounds = {} + Kotlin.array = function (len) { + return new Kotlin.Array(len, function () { + return null + }); + } + Kotlin.Array = Class.create({ + initialize:function (len, f) { + this.array = []; + var i = 0; + while (i < len) { + this.array.push(f(i)); + ++i; + } + }, + get:function (index) { + if ((index < 0) || (index >= this.array.length)) { + throw Kotlin.Exceptions.IndexOutOfBounds; + } + return (this.array)[index]; + }, + set:function (index, value) { + if ((index < 0) || (index >= this.array.length)) { + throw Kotlin.Exceptions.IndexOutOfBounds; + } + (this.array)[index] = value; + }, + size:function () { + return this.array.length; + }, + //TODO: remove duplicated methods + get_size:function () { + return this.array.length; + }, + iterator:function () { + return new Kotlin.ArrayIterator(this); + }, + get_indices:function () { + return new Kotlin.NumberRange(0, this.size(), false); } - return this; - } - - function create() { - - result = {} - for (var i = 0, length = arguments.length; i < length; i++) { - add(result, arguments[i]); - } - return result; - } - - return { - create:create - }; -})(); - - -var Namespace = (function () { - - function create() { - return Trait.create.apply(Trait, arguments); - } - - return { - create:create - }; -})(); - -Kotlin = {} -Kotlin.Class = Class; -Kotlin.Namespace = Namespace; -Kotlin.Trait = Trait; -Kotlin.isType = isType; - -Kotlin.equals = function (obj1, obj2) { - if (typeof obj1 == "object") { - if (obj1.equals != undefined) { - return obj1.equals(obj2); - } - } - return (obj1 === obj2); -}; - -Kotlin.Exceptions = {} -Kotlin.Exception = Kotlin.Class.create(); -Kotlin.Exceptions.IndexOutOfBounds = {} -Kotlin.array = function (len) { - return new Kotlin.Array(len, function () { - return null }); -} -Kotlin.Array = Class.create({ - initialize:function (len, f) { - this.array = []; - var i = 0; - while (i < len) { - this.array.push(f(i)); - ++i; - } - }, - get:function (index) { - if ((index < 0) || (index >= this.array.length)) { - throw Kotlin.Exceptions.IndexOutOfBounds; - } - return (this.array)[index]; - }, - set:function (index, value) { - if ((index < 0) || (index >= this.array.length)) { - throw Kotlin.Exceptions.IndexOutOfBounds; - } - (this.array)[index] = value; - }, - size:function () { - return this.array.length; - }, - //TODO: remove duplicated methods - get_size:function () { - return this.array.length; - }, - iterator:function () { - return new Kotlin.ArrayIterator(this); - }, - get_indices:function () { - return new Kotlin.NumberRange(0, this.size(), false); - } -}); -Kotlin.ArrayList = Class.create({ - 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 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.hasNext()) { - this.add(it.next()); - } - }, - remove: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.ArrayIterator = Class.create({ - initialize:function (array) { - this.array = array; - this.index = 0; - }, - next:function () { - return this.array.get(this.index++); - }, - hasNext:function () { - return (this.array.size() > this.index); - } -}); - -Kotlin.parseInt = - function (str) { - return parseInt(str); - } -; - -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 - }; + Kotlin.ArrayList = Class.create({ + initialize:function () { + this.array = []; + this.$size = 0; }, - output:function () { - return output; + get:function (index) { + if ((index < 0) || (index >= this.$size)) { + throw Kotlin.Exceptions.IndexOutOfBounds; + } + return (this.array)[index]; }, - flush:function () { - output = ""; + 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 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.hasNext()) { + this.add(it.next()); + } + }, + remove: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.println = function (s) { - Kotlin.System.out().println(s); -} -Kotlin.print = function (s) { - Kotlin.System.out().print(s); -} + Kotlin.ArrayIterator = Class.create({ + initialize:function (array) { + this.array = array; + this.index = 0; + }, + next:function () { + return this.array.get(this.index++); + }, + hasNext:function () { + return (this.array.size() > this.index); + } + }); -Kotlin.AbstractFunctionInvokationError = Class.create(); + Kotlin.parseInt = + function (str) { + return parseInt(str); + } + ; -Kotlin.Iterator = Class.create({ - initialize:function () { - }, - next:function () { - throw new Kotlin.AbstractFunctionInvokationError(); - }, - hasNext:function () { - throw new Kotlin.AbstractFunctionInvokationError(); + 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.ArrayIterator = Class.create(Kotlin.Iterator, { - initialize:function (array) { - this.array = array; - this.index = 0; - }, - next:function () { - return this.array.get(this.index++); - }, - hasNext:function () { - return (this.array.size() > this.index); - }, - get_hasNext:function () { - return this.hasNext(); + Kotlin.print = function (s) { + Kotlin.System.out().print(s); } -}); -Kotlin.RangeIterator = Kotlin.Class.create(Kotlin.Iterator, { - initialize:function (start, count, reversed) { + Kotlin.AbstractFunctionInvokationError = Class.create(); + + Kotlin.Iterator = Class.create({ + initialize:function () { + }, + next:function () { + throw new Kotlin.AbstractFunctionInvokationError(); + }, + hasNext:function () { + throw new Kotlin.AbstractFunctionInvokationError(); + } + }); + + Kotlin.ArrayIterator = Class.create(Kotlin.Iterator, { + initialize:function (array) { + this.array = array; + this.index = 0; + }, + next:function () { + return this.array.get(this.index++); + }, + hasNext:function () { + return (this.array.size() > this.index); + }, + get_hasNext:function () { + return this.hasNext(); + } + }); + + Kotlin.RangeIterator = Kotlin.Class.create(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; + } + }, hasNext:function () { + return this.get_count() > 0; + }, get_hasNext:function () { + return this.hasNext(); + } + }); + + Kotlin.NumberRange = Kotlin.Class.create({initialize:function (start, size, reversed) { this.$start = start; - this.$count = count; + this.$size = size; 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_size:function () { + return this.$size; }, 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); + }, 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()) { - this.set_i(this.get_i() - 1); - return this.get_i() + 1; + return number <= this.get_start() && number > this.get_start() - this.get_size(); } else { - this.set_i(this.get_i() + 1); - return this.get_i() - 1; + return number >= this.get_start() && number < this.get_start() + this.get_size(); } - }, hasNext:function () { - return this.get_count() > 0; - }, get_hasNext:function () { - return this.hasNext(); + }, iterator:function () { + return new Kotlin.RangeIterator(this.get_start(), this.get_size(), this.get_reversed()); } -}); + }); -Kotlin.NumberRange = Kotlin.Class.create({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 new Kotlin.RangeIterator(this.get_start(), this.get_size(), this.get_reversed()); -} -}); - - -/** - * 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. - */ - -/** - * jshashtable - * - * jshashtable is a JavaScript implementation of a hash table. It creates a single constructor function called Hashtable - * in the global scope. - * - * Author: Tim Down - * Version: 2.1 - * Build date: 21 March 2010 - * Website: http://www.timdown.co.uk/jshashtable - */ - -(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); + Kotlin.Comparator = Kotlin.Class.create( + { + initialize:function() { + }, + compare:function() { + throw new Kotlin.AbstractFunctionInvokationError(); } } - } + ); - 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.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 = 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.Class.create( - { - initialize:function () { - Kotlin.HashTable.call(this); - } - } -); - -Kotlin.StringBuilder = Kotlin.Class.create( - { - initialize:function () { - this.string = ""; - }, - append:function (obj) { - this.string = this.string + obj.toString(); - }, - toString:function () { - return this.string; - } - } -); - -Kotlin.toString = function (obj) { - return obj.toString(); -}; - -/** - * 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. - */ - -/** - * HashSet - * - * This is a JavaScript implementation of HashSet, similar in concept to those found in Java or C#'s standard libraries. - * It is distributed as part of jshashtable and depends on jshashtable.js. It creates a single constructor function - * called HashSet in the global scope. - * - * Author: Tim Down - * Version: 2.1 - * Build date: 27 March 2010 - * Website: http://www.timdown.co.uk/jshashtable/ - */ -(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 () { - var list = new Kotlin.ArrayList(); - var values = this.values(); - var i = values.length; - while (i--) { - list.add(values[i]); - } - return list.iterator(); - }; - - 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.Class.create( + Kotlin.StringBuilder = Kotlin.Class.create( { initialize:function () { - HashSet.call(this); + this.string = ""; + }, + append:function (obj) { + this.string = this.string + obj.toString(); + }, + toString:function () { + return this.string; } } - ) -}()); + ); + + Kotlin.toString = function (obj) { + return obj.toString(); + }; + + + /** + * 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. + */ + + /** + * jshashtable + * + * jshashtable is a JavaScript implementation of a hash table. It creates a single constructor function called Hashtable + * in the global scope. + * + * Author: Tim Down + * Version: 2.1 + * Build date: 21 March 2010 + * Website: http://www.timdown.co.uk/jshashtable + */ + + (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.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 = 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.Class.create( + { + initialize:function () { + Kotlin.HashTable.call(this); + } + } + ); + + + /** + * 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. + */ + + /** + * HashSet + * + * This is a JavaScript implementation of HashSet, similar in concept to those found in Java or C#'s standard libraries. + * It is distributed as part of jshashtable and depends on jshashtable.js. It creates a single constructor function + * called HashSet in the global scope. + * + * Author: Tim Down + * Version: 2.1 + * Build date: 27 March 2010 + * Website: http://www.timdown.co.uk/jshashtable/ + */ + (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 () { + var list = new Kotlin.ArrayList(); + var values = this.values(); + var i = values.length; + while (i--) { + list.add(values[i]); + } + return list.iterator(); + }; + + 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.Class.create( + { + initialize:function () { + HashSet.call(this); + } + } + ) + }()); + +})(); diff --git a/translator/testFiles/stdlib/cases/Filter.kt b/translator/testFiles/stdlib/cases/Filter.kt index 6c8350fd560..321be2ecb69 100644 --- a/translator/testFiles/stdlib/cases/Filter.kt +++ b/translator/testFiles/stdlib/cases/Filter.kt @@ -1,19 +1,17 @@ -package foo +package std -import js.* import java.util.* - -class NoSuchElementException() : Exception() {} +import java.lang.Iterable /* Filters given iterator */ -inline fun Iterator.filter(f: (T)-> Boolean) : Iterator = FilterIterator(this, f) +inline fun java.util.Iterator.filter(f: (T)-> Boolean) : java.util.Iterator = FilterIterator(this, f) /* Adds filtered elements in to given container */ -inline fun > Iterable.filterTo(var container: U, filter: (T)->Boolean) : U { +inline fun > java.lang.Iterable.filterTo(var container: U, filter: (T)->Boolean) : U { for(element in this) { if(filter(element)) container.add(element) @@ -25,37 +23,38 @@ inline fun > Iterable.filterTo(var container: U, filte Create iterator filtering given java.lang.Iterable */ /* -inline fun Iterable.filter(f: (T)->Boolean) : Iterator = (iterator() as Iterator).filter(f) +inline fun java.lang.Iterable.filter(f: (T)->Boolean) : java.util.Iterator = (iterator() as java.util.Iterator).filter(f) */ -private class FilterIterator(val original: Iterator, val filter: (T)-> Boolean) : Iterator { +private class FilterIterator(val original: java.util.Iterator, val filter: (T)-> Boolean) : java.util.Iterator { var state = 0 var nextElement: T? = null - override val hasNext: Boolean - get() { - if (state == 1) { - return true; - } - if (state == 2) { - return false; - } - while(original.hasNext) { - val candidate = original.next() - if((filter)(candidate)) { - nextElement = candidate - state = 1; - return true; - } - } - state = 2; - return false; - } + override fun hasNext(): Boolean = + when(state) { + 1 -> true // checked and next present + 2 -> false // checked and next not present + else -> { + while(original.hasNext()) { + val candidate = original.next() + if((filter)(candidate)) { + nextElement = candidate + state = 1 + true + } + } + state = 2 + false + } + } - override fun next(): T { + override fun next(): T = + if(state != 1) + throw java.util.NoSuchElementException() + else { val res = nextElement as T nextElement = null state = 0 - return res + res } } diff --git a/translator/testFiles/webDemoExamples2/cases/maze.kt b/translator/testFiles/webDemoExamples2/cases/maze.kt new file mode 100644 index 00000000000..f6dbb9eed3e --- /dev/null +++ b/translator/testFiles/webDemoExamples2/cases/maze.kt @@ -0,0 +1,238 @@ +/** + * Let's Walk Through a Maze. + * + * Imagine there is a maze whose walls are the big 'O' letters. + * Now, I stand where a big 'I' stands and some cool prize lies + * somewhere marked with a '$' sign. Like this: + * + * OOOOOOOOOOOOOOOOO + * O O + * O$ O O + * OOOOO O + * O O + * O OOOOOOOOOOOOOO + * O O I O + * O O + * OOOOOOOOOOOOOOOOO + * + * I want to get the prize, and this program helps me do so as soon + * as I possibly can by finding a shortest path through the maze. + */ +package maze + +import java.util.Collections.* +import java.util.* + +/** + * This function looks for a path from max.start to maze.end through + * free space (a path does not go through walls). One can move only + * straightly up, down, left or right, no diagonal moves allowed. + */ +fun findPath(maze : Maze) : List<#(Int, Int)>? { + val previous = HashMap<#(Int, Int), #(Int, Int)> + + val queue = LinkedList<#(Int, Int)> + val visited = HashSet<#(Int, Int)> + + queue.offer(maze.start) + visited.add(maze.start) + while (!queue.isEmpty()) { + val cell = queue.poll() + if (cell == maze.end) break + + for (newCell in maze.neighbors(cell._1, cell._2)) { + if (newCell in visited) continue + previous[newCell] = cell + queue.offer(newCell) + visited.add(cell) + } + } + + if (previous[maze.end] == null) return null + + val path = ArrayList<#(Int, Int)>() + var current = previous[maze.end] + while (current != maze.start) { + path.add(0, current) + current = previous[current] + } + return path +} + +/** + * Find neighbors of the (i, j) cell that are not walls + */ +fun Maze.neighbors(i : Int, j : Int) : List<#(Int, Int)> { + val result = ArrayList<#(Int, Int)> + addIfFree(i - 1, j, result) + addIfFree(i, j - 1, result) + addIfFree(i + 1, j, result) + addIfFree(i, j + 1, result) + return result +} + +fun Maze.addIfFree(i : Int, j : Int, result : List<#(Int, Int)>) { + if (i !in 0..height-1) return + if (j !in 0..width-1) return + if (walls[i][j]) return + + result.add(#(i, j)) +} + +/** + * A data class that represents a maze + */ +class Maze( + // Number or columns + val width : Int, + // Number of rows + val height : Int, + // true for a wall, false for free space + val walls : Array>, + // The starting point (must not be a wall) + val start : #(Int, Int), + // The target point (must not be a wall) + val end : #(Int, Int) +) { +} + +/** A few maze examples here */ +fun main(args : Array) { + printMaze("I $") + printMaze("I O $") + printMaze(""" + O $ + O + O + O + O I + """) + printMaze(""" + OOOOOOOOOOO + O $ O + OOOOOOO OOO + O O + OOOOO OOOOO + O O + O OOOOOOOOO + O OO + OOOOOO IO + """) + printMaze(""" + OOOOOOOOOOOOOOOOO + O O + O$ O O + OOOOO O + O O + O OOOOOOOOOOOOOO + O O I O + O O + OOOOOOOOOOOOOOOOO + """) +} + +// UTILITIES + +fun printMaze(str : String) { + val maze = makeMaze(str) + + println("Maze:") + val path = findPath(maze) + for (i in 0..maze.height - 1) { + for (j in 0..maze.width - 1) { + val cell = #(i, j) + print( + if (maze.walls[i][j]) "O" + else if (cell == maze.start) "I" + else if (cell == maze.end) "$" + else if (path != null && path.contains(cell)) "~" + else " " + ) + } + println("") + } + println("Result: " + if (path == null) "No path" else "Path found") + println("") +} + +/** + * A maze is encoded in the string s: the big 'O' letters are walls. + * I stand where a big 'I' stands and the prize is marked with + * a '$' sign. + * + * Example: + * + * OOOOOOOOOOOOOOOOO + * O O + * O$ O O + * OOOOO O + * O O + * O OOOOOOOOOOOOOO + * O O I O + * O O + * OOOOOOOOOOOOOOOOO + */ +fun makeMaze(s : String) : Maze { + val lines = s.split("\n").sure() + val w = max(lines.toList(), comparator {o1, o2 -> + val l1 : Int = o1?.size ?: 0 + val l2 = o2?.size ?: 0 + l1 - l2 + }).sure() + val data = Array>(lines.size) {Array(w.size) {false}} + + var start : #(Int, Int)? = null + var end : #(Int, Int)? = null + + for (line in lines.indices) { + for (x in lines[line].indices) { + val c = lines[line].sure()[x] + data[line][x] = c == 'O' + when (c) { + 'I' -> start = #(line, x) + '$' -> end = #(line, x) + else -> {} + } + } + } + + if (start == null) { + throw IllegalArgumentException("No starting point in the maze (should be indicated with 'I')") + } + + if (end == null) { + throw IllegalArgumentException("No goal point in the maze (should be indicated with a '$' sign)") + } + + return Maze(w.size, lines.size, data, start.sure(), end.sure()) +} + +// An excerpt from the Standard Library +val String?.indices : IntRange get() = IntRange(0, this.sure().size) + +val String.size : Int + get() = length + +fun Map.set(k : K, v : V) { put(k, v) } + +fun comparator (f : (T, T) -> Int) : Comparator = object : Comparator { + override fun compare(o1 : T, o2 : T) : Int = f(o1, o2) +} + +fun String.split(s : String) = (this as java.lang.String).split(s) + +fun println(message : Any?) { + System.out?.println(message) +} + +fun print(message : Any?) { + System.out?.print(message) +} + +fun > Array.to(result: C) : C { + for (elem in this) + result.add(elem) + return result +} + +fun Array.toList() : List = this.to(ArrayList()) diff --git a/translator/testFiles/webDemoExamples2/expected/maze.out b/translator/testFiles/webDemoExamples2/expected/maze.out new file mode 100644 index 00000000000..537f1c5c465 --- /dev/null +++ b/translator/testFiles/webDemoExamples2/expected/maze.out @@ -0,0 +1,45 @@ +Maze: +I~~$ +Result: Path found + +Maze: +I O $ +Result: No path + +Maze: + +O $ +O ~ +O ~ +O ~ +O ~~~~~~~~~I + +Result: Path found + +Maze: + +OOOOOOOOOOO +O $~~~~~ O +OOOOOOO~OOO +O ~~~ O +OOOOO~OOOOO +O~~~~~ O +O~OOOOOOOOO +O~~~~~~ OO +OOOOOO~~~IO + +Result: Path found + +Maze: + +OOOOOOOOOOOOOOOOO +O ~~~ O +O$~~O~ O +OOOOO~ O +O ~~~~ O +O ~OOOOOOOOOOOOOO +O ~ O I O +O ~~~~~~~~~~~~~ O +OOOOOOOOOOOOOOOOO + +Result: Path found