diff --git a/build.xml b/build.xml index 75607fd8f67..0bddfa35f98 100644 --- a/build.xml +++ b/build.xml @@ -368,20 +368,9 @@ - - - - - - - - - - - @@ -412,6 +401,15 @@ + + + diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java index 9a6362e2d64..899a799ab5f 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java @@ -39,7 +39,6 @@ import org.jetbrains.kotlin.js.translate.intrinsic.Intrinsics; import org.jetbrains.kotlin.js.translate.utils.JsAstUtils; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqNameUnsafe; -import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.DescriptorUtils; @@ -145,15 +144,12 @@ public final class StaticContext { @NotNull private final Set classes = new HashSet(); - @NotNull - private final ExportedPackage rootPackage = new ExportedPackage(""); - - @NotNull - private final JsObjectLiteral exportObject = rootPackage.objectLiteral; - @NotNull private final Set exportedDeclarations = new HashSet(); + @NotNull + private final Map localPackageNames = new HashMap(); + //TODO: too many parameters in constructor private StaticContext( @NotNull JsProgram program, @@ -665,11 +661,7 @@ public final class StaticContext { exportedDeclarations.add(descriptor); if (container instanceof PackageFragmentDescriptor) { - PackageFragmentDescriptor packageDescriptor = (PackageFragmentDescriptor) container; - ExportedPackage exportedPackage = rootPackage; - for (Name packageName : packageDescriptor.getFqName().pathSegments()) { - exportedPackage = exportedPackage.getSubpackage(packageName.asString()); - } + JsExpression packageRef = getLocalPackageReference(((PackageFragmentDescriptor) container).getFqName()); JsExpression initializerExpr = DeclarationExporter.exportDeclaration(this, descriptor, exportStatements); if (initializerExpr != null) { @@ -679,8 +671,7 @@ public final class StaticContext { MetadataProperties.setStaticRef(propertyName, initializerExpr); } } - JsPropertyInitializer initializer = new JsPropertyInitializer(propertyName.makeRef(), initializerExpr); - exportedPackage.objectLiteral.getPropertyInitializers().add(initializer); + exportStatements.add(JsAstUtils.assignment(new JsNameRef(propertyName, packageRef), initializerExpr).makeStmt()); } } else { @@ -689,6 +680,24 @@ public final class StaticContext { } } + private JsExpression getLocalPackageReference(FqName packageName) { + if (packageName.isRoot()) { + return rootFunction.getScope().declareName(Namer.getRootPackageName()).makeRef(); + } + JsName name = localPackageNames.get(packageName); + if (name == null) { + name = rootFunction.getScope().declareFreshName("package$" + packageName.shortName().asString()); + localPackageNames.put(packageName, name); + + JsExpression parentRef = getLocalPackageReference(packageName.parent()); + JsExpression selfRef = new JsNameRef(packageName.shortName().asString(), parentRef); + JsExpression rhs = JsAstUtils.or(selfRef, JsAstUtils.assignment(selfRef.deepCopy(), new JsObjectLiteral(false))); + + exportStatements.add(JsAstUtils.newVar(name, rhs)); + } + return name.makeRef(); + } + @NotNull public NameSuggestion getNameSuggestion() { return nameSuggestion; @@ -704,11 +713,7 @@ public final class StaticContext { rootFunction.getBody().getStatements().addAll(importStatements); addClassPrototypes(); rootFunction.getBody().getStatements().addAll(declarationStatements); - - JsName rootPackageName = rootFunction.getScope().declareName(Namer.getRootPackageName()); - rootFunction.getBody().getStatements().add(JsAstUtils.newVar(rootPackageName, exportObject)); rootFunction.getBody().getStatements().addAll(exportStatements); - rootFunction.getBody().getStatements().addAll(topLevelStatements); } @@ -753,25 +758,4 @@ public final class StaticContext { } return false; } - - private static class ExportedPackage { - @NotNull final String name; - @NotNull final Map subpackages = new HashMap(); - @NotNull final JsObjectLiteral objectLiteral = new JsObjectLiteral(true); - - public ExportedPackage(@NotNull String name) { - this.name = name; - } - - @NotNull - public ExportedPackage getSubpackage(@NotNull String name) { - ExportedPackage subpackage = subpackages.get(name); - if (subpackage == null) { - subpackage = new ExportedPackage(name); - subpackages.put(name, subpackage); - objectLiteral.getPropertyInitializers().add(new JsPropertyInitializer(new JsNameRef(name), subpackage.objectLiteral)); - } - return subpackage; - } - } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/ModuleWrapperTranslation.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/ModuleWrapperTranslation.kt index 728fd0eefa3..8021320192e 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/ModuleWrapperTranslation.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/ModuleWrapperTranslation.kt @@ -55,7 +55,7 @@ object ModuleWrapperTranslation { val amdBody = JsBlock(wrapAmd(moduleId, factoryName.makeRef(), importedModules, program)) val commonJsBody = JsBlock(wrapCommonJs(factoryName.makeRef(), importedModules, program)) - val plainInvocation = makePlainInvocation(factoryName.makeRef(), importedModules, program) + val plainInvocation = makePlainInvocation(moduleId, factoryName.makeRef(), importedModules, program) val lhs: JsExpression = if (Namer.requiresEscaping(moduleId)) { JsArrayAccess(rootName.makeRef(), program.getStringLiteral(moduleId)) @@ -79,7 +79,7 @@ object ModuleWrapperTranslation { val defineName = scope.declareName("define") val invocationArgs = listOf( program.getStringLiteral(moduleId), - JsArrayLiteral(importedModules.map { program.getStringLiteral(it) }), + JsArrayLiteral(listOf(program.getStringLiteral("exports")) + importedModules.map { program.getStringLiteral(it) }), function ) @@ -93,16 +93,15 @@ object ModuleWrapperTranslation { val requireName = scope.declareName("require") val invocationArgs = importedModules.map { JsInvocation(requireName.makeRef(), program.getStringLiteral(it)) } - val invocation = JsInvocation(function, invocationArgs) - val assignment = JsAstUtils.assignment(JsNameRef("exports", moduleName.makeRef()), invocation) - return listOf(assignment.makeStmt()) + val invocation = JsInvocation(function, listOf(JsNameRef("exports", moduleName.makeRef())) + invocationArgs) + return listOf(invocation.makeStmt()) } private fun wrapPlain( moduleId: String, function: JsExpression, importedModules: List, program: JsProgram ): List { - val invocation = makePlainInvocation(function, importedModules, program) + val invocation = makePlainInvocation(moduleId, function, importedModules, program) val statement = if (Namer.requiresEscaping(moduleId)) { JsAstUtils.assignment(makePlainModuleRef(moduleId, program), invocation).makeStmt() @@ -114,9 +113,18 @@ object ModuleWrapperTranslation { return listOf(statement) } - private fun makePlainInvocation(function: JsExpression, importedModules: List, program: JsProgram): JsInvocation { + private fun makePlainInvocation( + moduleId: String, + function: JsExpression, + importedModules: List, + program: JsProgram + ): JsInvocation { val invocationArgs = importedModules.map { makePlainModuleRef(it, program) } - return JsInvocation(function, invocationArgs) + val moduleRef = makePlainModuleRef(moduleId, program) + val testModuleDefined = JsAstUtils.typeOfIs(moduleRef, program.getStringLiteral("undefined")) + val selfArg = JsConditional(testModuleDefined, JsObjectLiteral(false), moduleRef.deepCopy()) + + return JsInvocation(function, listOf(selfArg) + invocationArgs) } private fun makePlainModuleRef(moduleId: String, program: JsProgram): JsExpression { diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java index 59492220816..61aa54d5714 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/general/Translation.java @@ -269,6 +269,9 @@ public final class Translation { mayBeGenerateTests(files, config, rootBlock, context); + JsName rootPackageName = program.getRootScope().declareName(Namer.getRootPackageName()); + rootFunction.getParameters().add(new JsParameter((rootPackageName))); + // Invoke function passing modules as arguments // This should help minifier tool to recognize references to these modules as local variables and make them shorter. List importedModuleList = new ArrayList(); @@ -288,7 +291,7 @@ public final class Translation { } } - statements.add(new JsReturn(program.getRootScope().declareName(Namer.getRootPackageName()).makeRef())); + statements.add(new JsReturn(rootPackageName.makeRef())); JsBlock block = program.getGlobalBlock(); block.getStatements().addAll(wrapIfNecessary(config.getModuleId(), rootFunction, importedModuleList, program, diff --git a/js/js.translator/testData/closure-wrapper.txt b/js/js.translator/testData/closure-wrapper.txt index ec90b7bb9cb..e5156814ebe 100644 --- a/js/js.translator/testData/closure-wrapper.txt +++ b/js/js.translator/testData/closure-wrapper.txt @@ -8,11 +8,8 @@ } }(this, function () { var Kotlin = {}; - function require() { - return Kotlin; - } - var module = {}; + %output% - Kotlin.modules.kotlin = Kotlin; + return Kotlin; })); \ No newline at end of file diff --git a/js/js.translator/testData/kotlin_lib.js b/js/js.translator/testData/kotlin_lib.js index 3d510ec49ff..11db08cc249 100644 --- a/js/js.translator/testData/kotlin_lib.js +++ b/js/js.translator/testData/kotlin_lib.js @@ -14,90 +14,87 @@ * limitations under the License. */ -(function (Kotlin) { - "use strict"; +// Shims for String +if (typeof String.prototype.startsWith === "undefined") { + String.prototype.startsWith = function(searchString, position) { + position = position || 0; + return this.lastIndexOf(searchString, position) === position; + }; +} +if (typeof String.prototype.endsWith === "undefined") { + String.prototype.endsWith = function(searchString, position) { + var subjectString = this.toString(); + if (position === undefined || position > subjectString.length) { + position = subjectString.length; + } + position -= searchString.length; + var lastIndex = subjectString.indexOf(searchString, position); + return lastIndex !== -1 && lastIndex === position; + }; +} - // Shims for String - if (typeof String.prototype.startsWith === "undefined") { - String.prototype.startsWith = function(searchString, position) { - position = position || 0; - return this.lastIndexOf(searchString, position) === position; - }; - } - if (typeof String.prototype.endsWith === "undefined") { - String.prototype.endsWith = function(searchString, position) { - var subjectString = this.toString(); - if (position === undefined || position > subjectString.length) { - position = subjectString.length; - } - position -= searchString.length; - var lastIndex = subjectString.indexOf(searchString, position); - return lastIndex !== -1 && lastIndex === position; - }; +String.prototype.contains = function (s) { + return this.indexOf(s) !== -1; +}; + +// Kotlin stdlib + +Kotlin.equals = function (obj1, obj2) { + if (obj1 == null) { + return obj2 == null; } - String.prototype.contains = function (s) { - return this.indexOf(s) !== -1; - }; + if (obj2 == null) { + return false; + } - // Kotlin stdlib + if (typeof obj1 == "object" && typeof obj1.equals_za3rmp$ === "function") { + return obj1.equals_za3rmp$(obj2); + } - Kotlin.equals = function (obj1, obj2) { - if (obj1 == null) { - return obj2 == null; - } + return obj1 === obj2; +}; - if (obj2 == null) { - return false; - } +Kotlin.hashCode = function (obj) { + if (obj == null) { + return 0; + } + if ("function" == typeof obj.hashCode) { + return obj.hashCode(); + } + var objType = typeof obj; + if ("object" == objType || "function" == objType) { + return getObjectHashCode(obj); + } else if ("number" == objType) { + // TODO: a more elaborate code is needed for floating point values. + return obj | 0; + } if ("boolean" == objType) { + return Number(obj) + } - if (typeof obj1 == "object" && typeof obj1.equals_za3rmp$ === "function") { - return obj1.equals_za3rmp$(obj2); - } + var str = String(obj); + return getStringHashCode(str); +}; - return obj1 === obj2; - }; +Kotlin.toString = function (o) { + if (o == null) { + return "null"; + } + else if (Array.isArray(o)) { + return "[...]"; + } + else { + return o.toString(); + } +}; - Kotlin.hashCode = function (obj) { - if (obj == null) { - return 0; - } - if ("function" == typeof obj.hashCode) { - return obj.hashCode(); - } - var objType = typeof obj; - if ("object" == objType || "function" == objType) { - return getObjectHashCode(obj); - } else if ("number" == objType) { - // TODO: a more elaborate code is needed for floating point values. - return obj | 0; - } if ("boolean" == objType) { - return Number(obj) - } +Kotlin.arrayToString = function (a) { + return "[" + a.map(Kotlin.toString).join(", ") + "]"; +}; - var str = String(obj); - return getStringHashCode(str); - }; - - Kotlin.toString = function (o) { - if (o == null) { - return "null"; - } - else if (Array.isArray(o)) { - return "[...]"; - } - else { - return o.toString(); - } - }; - - Kotlin.arrayToString = function (a) { - return "[" + a.map(Kotlin.toString).join(", ") + "]"; - }; - - Kotlin.arrayDeepToString = function (a, visited) { - visited = visited || [a]; - return "[" + a.map(function(e) { +Kotlin.arrayDeepToString = function (a, visited) { + visited = visited || [a]; + return "[" + a.map(function(e) { if (Array.isArray(e) && visited.indexOf(e) < 0) { visited.push(e); var result = Kotlin.arrayDeepToString(e, visited); @@ -108,396 +105,395 @@ return Kotlin.toString(e); } }).join(", ") + "]"; - }; +}; - Kotlin.compareTo = function (a, b) { - var typeA = typeof a; - var typeB = typeof a; - if (Kotlin.isChar(a) && typeB == "number") { - return Kotlin.primitiveCompareTo(a.charCodeAt(0), b); - } - if (typeA == "number" && Kotlin.isChar(b)) { - return Kotlin.primitiveCompareTo(a, b.charCodeAt(0)); - } - if (typeA == "number" || typeA == "string") { - return a < b ? -1 : a > b ? 1 : 0; - } - return a.compareTo_za3rmp$(b); - }; - - Kotlin.primitiveCompareTo = function (a, b) { +Kotlin.compareTo = function (a, b) { + var typeA = typeof a; + var typeB = typeof a; + if (Kotlin.isChar(a) && typeB == "number") { + return Kotlin.primitiveCompareTo(a.charCodeAt(0), b); + } + if (typeA == "number" && Kotlin.isChar(b)) { + return Kotlin.primitiveCompareTo(a, b.charCodeAt(0)); + } + if (typeA == "number" || typeA == "string") { return a < b ? -1 : a > b ? 1 : 0; - }; + } + return a.compareTo_za3rmp$(b); +}; - Kotlin.isNumber = function (a) { - return typeof a == "number" || a instanceof Kotlin.Long; - }; +Kotlin.primitiveCompareTo = function (a, b) { + return a < b ? -1 : a > b ? 1 : 0; +}; - Kotlin.isChar = function (value) { - return (typeof value) == "string" && value.length == 1; - }; +Kotlin.isNumber = function (a) { + return typeof a == "number" || a instanceof Kotlin.Long; +}; - Kotlin.isComparable = function (value) { - var type = typeof value; +Kotlin.isChar = function (value) { + return (typeof value) == "string" && value.length == 1; +}; - return type === "string" || - type === "boolean" || - Kotlin.isNumber(value) || - Kotlin.isType(value, Kotlin.kotlin.Comparable); - }; - - Kotlin.isCharSequence = function (value) { - return typeof value === "string" || Kotlin.isType(value, Kotlin.kotlin.CharSequence); - }; +Kotlin.isComparable = function (value) { + var type = typeof value; - Kotlin.charInc = function (value) { - return String.fromCharCode(value.charCodeAt(0)+1); - }; + return type === "string" || + type === "boolean" || + Kotlin.isNumber(value) || + Kotlin.isType(value, Kotlin.kotlin.Comparable); +}; - Kotlin.charDec = function (value) { - return String.fromCharCode(value.charCodeAt(0)-1); - }; +Kotlin.isCharSequence = function (value) { + return typeof value === "string" || Kotlin.isType(value, Kotlin.kotlin.CharSequence); +}; - Kotlin.toShort = function (a) { - return (a & 0xFFFF) << 16 >> 16; - }; +Kotlin.charInc = function (value) { + return String.fromCharCode(value.charCodeAt(0)+1); +}; - Kotlin.toByte = function (a) { - return (a & 0xFF) << 24 >> 24; - }; +Kotlin.charDec = function (value) { + return String.fromCharCode(value.charCodeAt(0)-1); +}; - Kotlin.toChar = function (a) { - return String.fromCharCode((((a | 0) % 65536) & 0xFFFF) << 16 >>> 16); - }; +Kotlin.toShort = function (a) { + return (a & 0xFFFF) << 16 >> 16; +}; - Kotlin.numberToLong = function (a) { - return a instanceof Kotlin.Long ? a : Kotlin.Long.fromNumber(a); - }; +Kotlin.toByte = function (a) { + return (a & 0xFF) << 24 >> 24; +}; - Kotlin.numberToInt = function (a) { - return a instanceof Kotlin.Long ? a.toInt() : (a | 0); - }; +Kotlin.toChar = function (a) { + return String.fromCharCode((((a | 0) % 65536) & 0xFFFF) << 16 >>> 16); +}; - Kotlin.numberToShort = function (a) { - return Kotlin.toShort(Kotlin.numberToInt(a)); - }; +Kotlin.numberToLong = function (a) { + return a instanceof Kotlin.Long ? a : Kotlin.Long.fromNumber(a); +}; - Kotlin.numberToByte = function (a) { - return Kotlin.toByte(Kotlin.numberToInt(a)); - }; +Kotlin.numberToInt = function (a) { + return a instanceof Kotlin.Long ? a.toInt() : (a | 0); +}; - Kotlin.numberToDouble = function (a) { - return +a; - }; +Kotlin.numberToShort = function (a) { + return Kotlin.toShort(Kotlin.numberToInt(a)); +}; - Kotlin.numberToChar = function (a) { - return Kotlin.toChar(Kotlin.numberToInt(a)); - }; +Kotlin.numberToByte = function (a) { + return Kotlin.toByte(Kotlin.numberToInt(a)); +}; - Kotlin.intUpto = function (from, to) { - return new Kotlin.kotlin.ranges.IntRange(from, to); - }; +Kotlin.numberToDouble = function (a) { + return +a; +}; - Kotlin.intDownto = function (from, to) { - return new Kotlin.kotlin.ranges.IntProgression(from, to, -1); - }; +Kotlin.numberToChar = function (a) { + return Kotlin.toChar(Kotlin.numberToInt(a)); +}; - Kotlin.Throwable = Error; +Kotlin.intUpto = function (from, to) { + return new Kotlin.kotlin.ranges.IntRange(from, to); +}; - Kotlin.throwNPE = function (message) { - throw new Kotlin.kotlin.NullPointerException(message); - }; +Kotlin.intDownto = function (from, to) { + return new Kotlin.kotlin.ranges.IntProgression(from, to, -1); +}; - Kotlin.throwCCE = function () { - throw new Kotlin.kotlin.ClassCastException("Illegal cast"); - }; +Kotlin.Throwable = Error; - /** @const */ - var POW_2_32 = 4294967296; - // TODO: consider switching to Symbol type once we are on ES6. - /** @const */ - var OBJECT_HASH_CODE_PROPERTY_NAME = "kotlinHashCodeValue$"; +Kotlin.throwNPE = function (message) { + throw new Kotlin.kotlin.NullPointerException(message); +}; - function getObjectHashCode(obj) { - if (!(OBJECT_HASH_CODE_PROPERTY_NAME in obj)) { - var hash = (Math.random() * POW_2_32) | 0; // Make 32-bit singed integer. - Object.defineProperty(obj, OBJECT_HASH_CODE_PROPERTY_NAME, { value: hash, enumerable: false }); - } - return obj[OBJECT_HASH_CODE_PROPERTY_NAME]; +Kotlin.throwCCE = function () { + throw new Kotlin.kotlin.ClassCastException("Illegal cast"); +}; + +/** @const */ +var POW_2_32 = 4294967296; +// TODO: consider switching to Symbol type once we are on ES6. +/** @const */ +var OBJECT_HASH_CODE_PROPERTY_NAME = "kotlinHashCodeValue$"; + +function getObjectHashCode(obj) { + if (!(OBJECT_HASH_CODE_PROPERTY_NAME in obj)) { + var hash = (Math.random() * POW_2_32) | 0; // Make 32-bit singed integer. + Object.defineProperty(obj, OBJECT_HASH_CODE_PROPERTY_NAME, { value: hash, enumerable: false }); + } + return obj[OBJECT_HASH_CODE_PROPERTY_NAME]; +} + +function getStringHashCode(str) { + var hash = 0; + for (var i = 0; i < str.length; i++) { + var code = str.charCodeAt(i); + hash = (hash * 31 + code) | 0; // Keep it 32-bit. + } + return hash; +} + +Kotlin.PropertyMetadata = Kotlin.createClassNow(null, + function (name) { + this.name = name; + } +); + +Kotlin.safeParseInt = function (str) { + var r = parseInt(str, 10); + return isNaN(r) ? null : r; +}; + +Kotlin.safeParseDouble = function (str) { + var r = parseFloat(str); + return isNaN(r) ? null : r; +}; + +Kotlin.arrayEquals = function (a, b) { + if (a === b) { + return true; + } + if (!Array.isArray(b) || a.length !== b.length) { + return false; } - function getStringHashCode(str) { - var hash = 0; - for (var i = 0; i < str.length; i++) { - var code = str.charCodeAt(i); - hash = (hash * 31 + code) | 0; // Keep it 32-bit. + for (var i = 0, n = a.length; i < n; i++) { + if (!Kotlin.equals(a[i], b[i])) { + return false; } - return hash; + } + return true; +}; + +Kotlin.arrayDeepEquals = function (a, b) { + if (a === b) { + return true; + } + if (!Array.isArray(b) || a.length !== b.length) { + return false; } - Kotlin.PropertyMetadata = Kotlin.createClassNow(null, - function (name) { - this.name = name; - } - ); - - Kotlin.safeParseInt = function (str) { - var r = parseInt(str, 10); - return isNaN(r) ? null : r; - }; - - Kotlin.safeParseDouble = function (str) { - var r = parseFloat(str); - return isNaN(r) ? null : r; - }; - - Kotlin.arrayEquals = function (a, b) { - if (a === b) { - return true; - } - if (!Array.isArray(b) || a.length !== b.length) { - return false; - } - - for (var i = 0, n = a.length; i < n; i++) { - if (!Kotlin.equals(a[i], b[i])) { + for (var i = 0, n = a.length; i < n; i++) { + if (Array.isArray(a[i])) { + if (!Kotlin.arrayDeepEquals(a[i], b[i])) { return false; } - } - return true; - }; - - Kotlin.arrayDeepEquals = function (a, b) { - if (a === b) { - return true; - } - if (!Array.isArray(b) || a.length !== b.length) { + } else if (!Kotlin.equals(a[i], b[i])) { return false; } + } + return true; +}; - for (var i = 0, n = a.length; i < n; i++) { - if (Array.isArray(a[i])) { - if (!Kotlin.arrayDeepEquals(a[i], b[i])) { - return false; - } - } else if (!Kotlin.equals(a[i], b[i])) { - return false; +Kotlin.arrayHashCode = function (arr) { + var result = 1; + for (var i = 0, n = arr.length; i < n; i++) { + result = ((31 * result | 0) + Kotlin.hashCode(arr[i])) | 0; + } + return result; +}; + +Kotlin.arrayDeepHashCode = function (arr) { + var result = 1; + for (var i = 0, n = arr.length; i < n; i++) { + var e = arr[i]; + result = ((31 * result | 0) + (Array.isArray(e) ? Kotlin.arrayDeepHashCode(e) : Kotlin.hashCode(e))) | 0; + } + return result; +}; + +var BaseOutput = Kotlin.createClassNow(null, null, { + println: function (a) { + if (typeof a !== "undefined") this.print(a); + this.print("\n"); + }, + flush: function () { + } + } +); + + +Kotlin.NodeJsOutput = Kotlin.createClassNow(BaseOutput, + function(outputStream) { + this.outputStream = outputStream; + }, { + print: function (a) { + this.outputStream.write(a); + } + } +); + +Kotlin.OutputToConsoleLog = Kotlin.createClassNow(BaseOutput, null, { + print: function (a) { + console.log(a); + }, + println: function (a) { + this.print(typeof a !== "undefined" ? a : ""); + } + } +); + +Kotlin.BufferedOutput = Kotlin.createClassNow(BaseOutput, + function() { + this.buffer = "" + }, { + print: function (a) { + this.buffer += String(a); + }, + flush: function () { + this.buffer = ""; + } + } +); + +Kotlin.BufferedOutputToConsoleLog = Kotlin.createClassNow(Kotlin.BufferedOutput, + function() { + Kotlin.BufferedOutput.call(this); + }, { + print: function (a) { + var s = String(a); + + var i = s.lastIndexOf("\n"); + if (i != -1) { + this.buffer += s.substr(0, i); + + this.flush(); + + s = s.substr(i + 1); } + + this.buffer += s; + }, + flush: function () { + console.log(this.buffer); + this.buffer = ""; } - return true; - }; + } +); +Kotlin.out = function() { + var isNode = typeof process !== 'undefined' && process.versions && !!process.versions.node; - Kotlin.arrayHashCode = function (arr) { - var result = 1; - for (var i = 0, n = arr.length; i < n; i++) { - result = ((31 * result | 0) + Kotlin.hashCode(arr[i])) | 0; + if (isNode) return new Kotlin.NodeJsOutput(process.stdout); + + return new Kotlin.BufferedOutputToConsoleLog(); +}(); + +Kotlin.println = function (s) { + Kotlin.out.println(s); +}; + +Kotlin.print = function (s) { + Kotlin.out.print(s); +}; + +Kotlin.collectionsMax = function (c, comp) { + if (c.isEmpty()) { + //TODO: which exception? + throw new Error(); + } + var it = c.iterator(); + var max = it.next(); + while (it.hasNext()) { + var el = it.next(); + if (comp.compare(max, el) < 0) { + max = el; } - return result; - }; + } + return max; +}; - Kotlin.arrayDeepHashCode = function (arr) { - var result = 1; - for (var i = 0, n = arr.length; i < n; i++) { - var e = arr[i]; - result = ((31 * result | 0) + (Array.isArray(e) ? Kotlin.arrayDeepHashCode(e) : Kotlin.hashCode(e))) | 0; +Kotlin.collectionsSort = function (mutableList, comparator) { + var boundComparator = void 0; + if (comparator !== void 0) { + boundComparator = comparator.compare.bind(comparator); + } + + if (mutableList.size > 1) { + var array = Kotlin.copyToArray(mutableList); + + array.sort(boundComparator); + + for (var i = 0, n = array.length; i < n; i++) { + mutableList.set_vux3hl$(i, array[i]); } - return result; - }; + } +}; +Kotlin.primitiveArraySort = function(array) { + array.sort(Kotlin.primitiveCompareTo) +}; - var BaseOutput = Kotlin.createClassNow(null, null, { - println: function (a) { - if (typeof a !== "undefined") this.print(a); - this.print("\n"); - }, - flush: function () { - } +Kotlin.copyToArray = function (collection) { + if (typeof collection.toArray !== "undefined") return collection.toArray(); + return Kotlin.copyToArrayImpl(collection); +}; + +Kotlin.copyToArrayImpl = function (collection) { + var array = []; + var it = collection.iterator(); + while (it.hasNext()) { + array.push(it.next()); + } + + return array; +}; + +Kotlin.splitString = function (str, regex, limit) { + return str.split(new RegExp(regex), limit); +}; + +Kotlin.nullArray = function (size) { + var res = []; + var i = size; + while (i > 0) { + res[--i] = null; + } + return res; +}; + +Kotlin.numberArrayOfSize = function (size) { + return Kotlin.arrayFromFun(size, function () { + return 0; + }); +}; + +Kotlin.charArrayOfSize = function (size) { + return Kotlin.arrayFromFun(size, function () { + return '\0'; + }); +}; + +Kotlin.booleanArrayOfSize = function (size) { + return Kotlin.arrayFromFun(size, function () { + return false; + }); +}; + +Kotlin.longArrayOfSize = function (size) { + return Kotlin.arrayFromFun(size, function () { + return Kotlin.Long.ZERO; + }); +}; + +Kotlin.arrayFromFun = function (size, initFun) { + var result = new Array(size); + for (var i = 0; i < size; i++) { + result[i] = initFun(i); + } + return result; +}; + +Kotlin.deleteProperty = function (object, property) { + delete object[property]; +}; + +Kotlin.jsonAddProperties = function (obj1, obj2) { + for (var p in obj2) { + if (obj2.hasOwnProperty(p)) { + obj1[p] = obj2[p]; } - ); + } + return obj1; +}; - Kotlin.NodeJsOutput = Kotlin.createClassNow(BaseOutput, - function(outputStream) { - this.outputStream = outputStream; - }, { - print: function (a) { - this.outputStream.write(a); - } - } - ); - - Kotlin.OutputToConsoleLog = Kotlin.createClassNow(BaseOutput, null, { - print: function (a) { - console.log(a); - }, - println: function (a) { - this.print(typeof a !== "undefined" ? a : ""); - } - } - ); - - Kotlin.BufferedOutput = Kotlin.createClassNow(BaseOutput, - function() { - this.buffer = "" - }, { - print: function (a) { - this.buffer += String(a); - }, - flush: function () { - this.buffer = ""; - } - } - ); - - Kotlin.BufferedOutputToConsoleLog = Kotlin.createClassNow(Kotlin.BufferedOutput, - function() { - Kotlin.BufferedOutput.call(this); - }, { - print: function (a) { - var s = String(a); - - var i = s.lastIndexOf("\n"); - if (i != -1) { - this.buffer += s.substr(0, i); - - this.flush(); - - s = s.substr(i + 1); - } - - this.buffer += s; - }, - flush: function () { - console.log(this.buffer); - this.buffer = ""; - } - } - ); - Kotlin.out = function() { - var isNode = typeof process !== 'undefined' && process.versions && !!process.versions.node; - - if (isNode) return new Kotlin.NodeJsOutput(process.stdout); - - return new Kotlin.BufferedOutputToConsoleLog(); - }(); - - Kotlin.println = function (s) { - Kotlin.out.println(s); - }; - - Kotlin.print = function (s) { - Kotlin.out.print(s); - }; - - Kotlin.collectionsMax = function (c, comp) { - if (c.isEmpty()) { - //TODO: which exception? - throw new Error(); - } - var it = c.iterator(); - var max = it.next(); - while (it.hasNext()) { - var el = it.next(); - if (comp.compare(max, el) < 0) { - max = el; - } - } - return max; - }; - - Kotlin.collectionsSort = function (mutableList, comparator) { - var boundComparator = void 0; - if (comparator !== void 0) { - boundComparator = comparator.compare.bind(comparator); - } - - if (mutableList.size > 1) { - var array = Kotlin.copyToArray(mutableList); - - array.sort(boundComparator); - - for (var i = 0, n = array.length; i < n; i++) { - mutableList.set_vux3hl$(i, array[i]); - } - } - }; - - Kotlin.primitiveArraySort = function(array) { - array.sort(Kotlin.primitiveCompareTo) - }; - - Kotlin.copyToArray = function (collection) { - if (typeof collection.toArray !== "undefined") return collection.toArray(); - return Kotlin.copyToArrayImpl(collection); - }; - - Kotlin.copyToArrayImpl = function (collection) { - var array = []; - var it = collection.iterator(); - while (it.hasNext()) { - array.push(it.next()); - } - - return array; - }; - - Kotlin.splitString = function (str, regex, limit) { - return str.split(new RegExp(regex), limit); - }; - - Kotlin.nullArray = function (size) { - var res = []; - var i = size; - while (i > 0) { - res[--i] = null; - } - return res; - }; - - Kotlin.numberArrayOfSize = function (size) { - return Kotlin.arrayFromFun(size, function () { - return 0; - }); - }; - - Kotlin.charArrayOfSize = function (size) { - return Kotlin.arrayFromFun(size, function () { - return '\0'; - }); - }; - - Kotlin.booleanArrayOfSize = function (size) { - return Kotlin.arrayFromFun(size, function () { - return false; - }); - }; - - Kotlin.longArrayOfSize = function (size) { - return Kotlin.arrayFromFun(size, function () { - return Kotlin.Long.ZERO; - }); - }; - - Kotlin.arrayFromFun = function (size, initFun) { - var result = new Array(size); - for (var i = 0; i < size; i++) { - result[i] = initFun(i); - } - return result; - }; - - Kotlin.deleteProperty = function (object, property) { - delete object[property]; - }; - - Kotlin.jsonAddProperties = function (obj1, obj2) { - for (var p in obj2) { - if (obj2.hasOwnProperty(p)) { - obj1[p] = obj2[p]; - } - } - return obj1; - }; - - Kotlin.identityHashCode = getObjectHashCode; -})(Kotlin); +Kotlin.identityHashCode = getObjectHashCode; diff --git a/js/js.translator/testData/long.js b/js/js.translator/testData/long.js index 5baaacbac5f..cba92000547 100644 --- a/js/js.translator/testData/long.js +++ b/js/js.translator/testData/long.js @@ -26,819 +26,815 @@ // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -(function (Kotlin) { - "use strict"; +/** + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Longs. + * + * The internal representation of a long is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @param {number} low The low (signed) 32 bits of the long. + * @param {number} high The high (signed) 32 bits of the long. + * @constructor + * @final + */ +Kotlin.Long = function(low, high) { + /** + * @type {number} + * @private + */ + this.low_ = low | 0; // force into 32 signed bits. - /** - * Constructs a 64-bit two's-complement integer, given its low and high 32-bit - * values as *signed* integers. See the from* functions below for more - * convenient ways of constructing Longs. - * - * The internal representation of a long is the two given signed, 32-bit values. - * We use 32-bit pieces because these are the size of integers on which - * Javascript performs bit-operations. For operations like addition and - * multiplication, we split each number into 16-bit pieces, which can easily be - * multiplied within Javascript's floating-point representation without overflow - * or change in sign. - * - * In the algorithms below, we frequently reduce the negative case to the - * positive case by negating the input(s) and then post-processing the result. - * Note that we must ALWAYS check specially whether those values are MIN_VALUE - * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as - * a positive number, it overflows back into a negative). Not handling this - * case would often result in infinite recursion. - * - * @param {number} low The low (signed) 32 bits of the long. - * @param {number} high The high (signed) 32 bits of the long. - * @constructor - * @final - */ - Kotlin.Long = function(low, high) { - /** - * @type {number} - * @private - */ - this.low_ = low | 0; // force into 32 signed bits. - - /** - * @type {number} - * @private - */ - this.high_ = high | 0; // force into 32 signed bits. - }; + /** + * @type {number} + * @private + */ + this.high_ = high | 0; // force into 32 signed bits. +}; - // NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the - // from* methods on which they depend. +// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the +// from* methods on which they depend. - /** - * A cache of the Long representations of small integer values. - * @type {!Object} - * @private - */ - Kotlin.Long.IntCache_ = {}; +/** + * A cache of the Long representations of small integer values. + * @type {!Object} + * @private + */ +Kotlin.Long.IntCache_ = {}; - /** - * Returns a Long representing the given (32-bit) integer value. - * @param {number} value The 32-bit integer in question. - * @return {!Kotlin.Long} The corresponding Long value. - */ - Kotlin.Long.fromInt = function(value) { - if (-128 <= value && value < 128) { - var cachedObj = Kotlin.Long.IntCache_[value]; - if (cachedObj) { - return cachedObj; - } +/** + * Returns a Long representing the given (32-bit) integer value. + * @param {number} value The 32-bit integer in question. + * @return {!Kotlin.Long} The corresponding Long value. + */ +Kotlin.Long.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = Kotlin.Long.IntCache_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new Kotlin.Long(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + Kotlin.Long.IntCache_[value] = obj; + } + return obj; +}; + + +/** + * Returns a Long representing the given value, provided that it is a finite + * number. Otherwise, zero is returned. + * @param {number} value The number in question. + * @return {!Kotlin.Long} The corresponding Long value. + */ +Kotlin.Long.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return Kotlin.Long.ZERO; + } else if (value <= -Kotlin.Long.TWO_PWR_63_DBL_) { + return Kotlin.Long.MIN_VALUE; + } else if (value + 1 >= Kotlin.Long.TWO_PWR_63_DBL_) { + return Kotlin.Long.MAX_VALUE; + } else if (value < 0) { + return Kotlin.Long.fromNumber(-value).negate(); + } else { + return new Kotlin.Long( + (value % Kotlin.Long.TWO_PWR_32_DBL_) | 0, + (value / Kotlin.Long.TWO_PWR_32_DBL_) | 0); + } +}; + + +/** + * Returns a Long representing the 64-bit integer that comes by concatenating + * the given high and low bits. Each is assumed to use 32 bits. + * @param {number} lowBits The low 32-bits. + * @param {number} highBits The high 32-bits. + * @return {!Kotlin.Long} The corresponding Long value. + */ +Kotlin.Long.fromBits = function(lowBits, highBits) { + return new Kotlin.Long(lowBits, highBits); +}; + + +/** + * Returns a Long representation of the given string, written using the given + * radix. + * @param {string} str The textual representation of the Long. + * @param {number=} opt_radix The radix in which the text is written. + * @return {!Kotlin.Long} The corresponding Long value. + */ +Kotlin.Long.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return Kotlin.Long.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Kotlin.Long.fromNumber(Math.pow(radix, 8)); + + var result = Kotlin.Long.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = Kotlin.Long.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(Kotlin.Long.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(Kotlin.Long.fromNumber(value)); + } + } + return result; +}; + + +// NOTE: the compiler should inline these constant values below and then remove +// these variables, so there should be no runtime penalty for these. + + +/** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @private + */ +Kotlin.Long.TWO_PWR_16_DBL_ = 1 << 16; + + +/** + * @type {number} + * @private + */ +Kotlin.Long.TWO_PWR_24_DBL_ = 1 << 24; + + +/** + * @type {number} + * @private + */ +Kotlin.Long.TWO_PWR_32_DBL_ = + Kotlin.Long.TWO_PWR_16_DBL_ * Kotlin.Long.TWO_PWR_16_DBL_; + + +/** + * @type {number} + * @private + */ +Kotlin.Long.TWO_PWR_31_DBL_ = + Kotlin.Long.TWO_PWR_32_DBL_ / 2; + + +/** + * @type {number} + * @private + */ +Kotlin.Long.TWO_PWR_48_DBL_ = + Kotlin.Long.TWO_PWR_32_DBL_ * Kotlin.Long.TWO_PWR_16_DBL_; + + +/** + * @type {number} + * @private + */ +Kotlin.Long.TWO_PWR_64_DBL_ = + Kotlin.Long.TWO_PWR_32_DBL_ * Kotlin.Long.TWO_PWR_32_DBL_; + + +/** + * @type {number} + * @private + */ +Kotlin.Long.TWO_PWR_63_DBL_ = + Kotlin.Long.TWO_PWR_64_DBL_ / 2; + + +/** @type {!Kotlin.Long} */ +Kotlin.Long.ZERO = Kotlin.Long.fromInt(0); + + +/** @type {!Kotlin.Long} */ +Kotlin.Long.ONE = Kotlin.Long.fromInt(1); + + +/** @type {!Kotlin.Long} */ +Kotlin.Long.NEG_ONE = Kotlin.Long.fromInt(-1); + + +/** @type {!Kotlin.Long} */ +Kotlin.Long.MAX_VALUE = + Kotlin.Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + + +/** @type {!Kotlin.Long} */ +Kotlin.Long.MIN_VALUE = Kotlin.Long.fromBits(0, 0x80000000 | 0); + + +/** + * @type {!Kotlin.Long} + * @private + */ +Kotlin.Long.TWO_PWR_24_ = Kotlin.Long.fromInt(1 << 24); + + +/** @return {number} The value, assuming it is a 32-bit integer. */ +Kotlin.Long.prototype.toInt = function() { + return this.low_; +}; + + +/** @return {number} The closest floating-point representation to this value. */ +Kotlin.Long.prototype.toNumber = function() { + return this.high_ * Kotlin.Long.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); +}; + +/** @return {number} The 32-bit hashCode of this value. */ +Kotlin.Long.prototype.hashCode = function() { + return this.high_ ^ this.low_; +}; + +/** + * @param {number=} opt_radix The radix in which the text should be written. + * @return {string} The textual representation of this value. + * @override + */ +Kotlin.Long.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(Kotlin.Long.MIN_VALUE)) { + // We need to change the Long value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixLong = Kotlin.Long.fromNumber(radix); + var div = this.div(radixLong); + var rem = div.multiply(radixLong).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Kotlin.Long.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; } + result = '' + digits + result; + } + } +}; - var obj = new Kotlin.Long(value | 0, value < 0 ? -1 : 0); - if (-128 <= value && value < 128) { - Kotlin.Long.IntCache_[value] = obj; + +/** @return {number} The high 32-bits as a signed value. */ +Kotlin.Long.prototype.getHighBits = function() { + return this.high_; +}; + + +/** @return {number} The low 32-bits as a signed value. */ +Kotlin.Long.prototype.getLowBits = function() { + return this.low_; +}; + + +/** @return {number} The low 32-bits as an unsigned value. */ +Kotlin.Long.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : Kotlin.Long.TWO_PWR_32_DBL_ + this.low_; +}; + + +/** + * @return {number} Returns the number of bits needed to represent the absolute + * value of this Long. + */ +Kotlin.Long.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(Kotlin.Long.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; } - return obj; - }; + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } +}; - /** - * Returns a Long representing the given value, provided that it is a finite - * number. Otherwise, zero is returned. - * @param {number} value The number in question. - * @return {!Kotlin.Long} The corresponding Long value. - */ - Kotlin.Long.fromNumber = function(value) { - if (isNaN(value) || !isFinite(value)) { - return Kotlin.Long.ZERO; - } else if (value <= -Kotlin.Long.TWO_PWR_63_DBL_) { - return Kotlin.Long.MIN_VALUE; - } else if (value + 1 >= Kotlin.Long.TWO_PWR_63_DBL_) { - return Kotlin.Long.MAX_VALUE; - } else if (value < 0) { - return Kotlin.Long.fromNumber(-value).negate(); +/** @return {boolean} Whether this value is zero. */ +Kotlin.Long.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; +}; + + +/** @return {boolean} Whether this value is negative. */ +Kotlin.Long.prototype.isNegative = function() { + return this.high_ < 0; +}; + + +/** @return {boolean} Whether this value is odd. */ +Kotlin.Long.prototype.isOdd = function() { + return (this.low_ & 1) == 1; +}; + + +/** + * @param {Kotlin.Long} other Long to compare against. + * @return {boolean} Whether this Long equals the other. + */ +Kotlin.Long.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); +}; + + +/** + * @param {Kotlin.Long} other Long to compare against. + * @return {boolean} Whether this Long does not equal the other. + */ +Kotlin.Long.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); +}; + + +/** + * @param {Kotlin.Long} other Long to compare against. + * @return {boolean} Whether this Long is less than the other. + */ +Kotlin.Long.prototype.lessThan = function(other) { + return this.compare(other) < 0; +}; + + +/** + * @param {Kotlin.Long} other Long to compare against. + * @return {boolean} Whether this Long is less than or equal to the other. + */ +Kotlin.Long.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; +}; + + +/** + * @param {Kotlin.Long} other Long to compare against. + * @return {boolean} Whether this Long is greater than the other. + */ +Kotlin.Long.prototype.greaterThan = function(other) { + return this.compare(other) > 0; +}; + + +/** + * @param {Kotlin.Long} other Long to compare against. + * @return {boolean} Whether this Long is greater than or equal to the other. + */ +Kotlin.Long.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; +}; + + +/** + * Compares this Long with the given one. + * @param {Kotlin.Long} other Long to compare against. + * @return {number} 0 if they are the same, 1 if the this is greater, and -1 + * if the given one is greater. + */ +Kotlin.Long.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } +}; + + +/** @return {!Kotlin.Long} The negation of this value. */ +Kotlin.Long.prototype.negate = function() { + if (this.equals(Kotlin.Long.MIN_VALUE)) { + return Kotlin.Long.MIN_VALUE; + } else { + return this.not().add(Kotlin.Long.ONE); + } +}; + + +/** + * Returns the sum of this and the given Long. + * @param {Kotlin.Long} other Long to add to this one. + * @return {!Kotlin.Long} The sum of this and the given Long. + */ +Kotlin.Long.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return Kotlin.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + + +/** + * Returns the difference of this and the given Long. + * @param {Kotlin.Long} other Long to subtract from this. + * @return {!Kotlin.Long} The difference of this and the given Long. + */ +Kotlin.Long.prototype.subtract = function(other) { + return this.add(other.negate()); +}; + + +/** + * Returns the product of this and the given long. + * @param {Kotlin.Long} other Long to multiply with this. + * @return {!Kotlin.Long} The product of this and the other. + */ +Kotlin.Long.prototype.multiply = function(other) { + if (this.isZero()) { + return Kotlin.Long.ZERO; + } else if (other.isZero()) { + return Kotlin.Long.ZERO; + } + + if (this.equals(Kotlin.Long.MIN_VALUE)) { + return other.isOdd() ? Kotlin.Long.MIN_VALUE : Kotlin.Long.ZERO; + } else if (other.equals(Kotlin.Long.MIN_VALUE)) { + return this.isOdd() ? Kotlin.Long.MIN_VALUE : Kotlin.Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both longs are small, use float multiplication + if (this.lessThan(Kotlin.Long.TWO_PWR_24_) && + other.lessThan(Kotlin.Long.TWO_PWR_24_)) { + return Kotlin.Long.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return Kotlin.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + + +/** + * Returns this Long divided by the given one. + * @param {Kotlin.Long} other Long by which to divide. + * @return {!Kotlin.Long} This Long divided by the given one. + */ +Kotlin.Long.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return Kotlin.Long.ZERO; + } + + if (this.equals(Kotlin.Long.MIN_VALUE)) { + if (other.equals(Kotlin.Long.ONE) || + other.equals(Kotlin.Long.NEG_ONE)) { + return Kotlin.Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(Kotlin.Long.MIN_VALUE)) { + return Kotlin.Long.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(Kotlin.Long.ZERO)) { + return other.isNegative() ? Kotlin.Long.ONE : Kotlin.Long.NEG_ONE; } else { - return new Kotlin.Long( - (value % Kotlin.Long.TWO_PWR_32_DBL_) | 0, - (value / Kotlin.Long.TWO_PWR_32_DBL_) | 0); + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; } - }; - - - /** - * Returns a Long representing the 64-bit integer that comes by concatenating - * the given high and low bits. Each is assumed to use 32 bits. - * @param {number} lowBits The low 32-bits. - * @param {number} highBits The high 32-bits. - * @return {!Kotlin.Long} The corresponding Long value. - */ - Kotlin.Long.fromBits = function(lowBits, highBits) { - return new Kotlin.Long(lowBits, highBits); - }; - - - /** - * Returns a Long representation of the given string, written using the given - * radix. - * @param {string} str The textual representation of the Long. - * @param {number=} opt_radix The radix in which the text is written. - * @return {!Kotlin.Long} The corresponding Long value. - */ - Kotlin.Long.fromString = function(str, opt_radix) { - if (str.length == 0) { - throw Error('number format error: empty string'); - } - - var radix = opt_radix || 10; - if (radix < 2 || 36 < radix) { - throw Error('radix out of range: ' + radix); - } - - if (str.charAt(0) == '-') { - return Kotlin.Long.fromString(str.substring(1), radix).negate(); - } else if (str.indexOf('-') >= 0) { - throw Error('number format error: interior "-" character: ' + str); - } - - // Do several (8) digits each time through the loop, so as to - // minimize the calls to the very expensive emulated div. - var radixToPower = Kotlin.Long.fromNumber(Math.pow(radix, 8)); - - var result = Kotlin.Long.ZERO; - for (var i = 0; i < str.length; i += 8) { - var size = Math.min(8, str.length - i); - var value = parseInt(str.substring(i, i + size), radix); - if (size < 8) { - var power = Kotlin.Long.fromNumber(Math.pow(radix, size)); - result = result.multiply(power).add(Kotlin.Long.fromNumber(value)); - } else { - result = result.multiply(radixToPower); - result = result.add(Kotlin.Long.fromNumber(value)); - } - } - return result; - }; - - - // NOTE: the compiler should inline these constant values below and then remove - // these variables, so there should be no runtime penalty for these. - - - /** - * Number used repeated below in calculations. This must appear before the - * first call to any from* function below. - * @type {number} - * @private - */ - Kotlin.Long.TWO_PWR_16_DBL_ = 1 << 16; - - - /** - * @type {number} - * @private - */ - Kotlin.Long.TWO_PWR_24_DBL_ = 1 << 24; - - - /** - * @type {number} - * @private - */ - Kotlin.Long.TWO_PWR_32_DBL_ = - Kotlin.Long.TWO_PWR_16_DBL_ * Kotlin.Long.TWO_PWR_16_DBL_; - - - /** - * @type {number} - * @private - */ - Kotlin.Long.TWO_PWR_31_DBL_ = - Kotlin.Long.TWO_PWR_32_DBL_ / 2; - - - /** - * @type {number} - * @private - */ - Kotlin.Long.TWO_PWR_48_DBL_ = - Kotlin.Long.TWO_PWR_32_DBL_ * Kotlin.Long.TWO_PWR_16_DBL_; - - - /** - * @type {number} - * @private - */ - Kotlin.Long.TWO_PWR_64_DBL_ = - Kotlin.Long.TWO_PWR_32_DBL_ * Kotlin.Long.TWO_PWR_32_DBL_; - - - /** - * @type {number} - * @private - */ - Kotlin.Long.TWO_PWR_63_DBL_ = - Kotlin.Long.TWO_PWR_64_DBL_ / 2; - - - /** @type {!Kotlin.Long} */ - Kotlin.Long.ZERO = Kotlin.Long.fromInt(0); - - - /** @type {!Kotlin.Long} */ - Kotlin.Long.ONE = Kotlin.Long.fromInt(1); - - - /** @type {!Kotlin.Long} */ - Kotlin.Long.NEG_ONE = Kotlin.Long.fromInt(-1); - - - /** @type {!Kotlin.Long} */ - Kotlin.Long.MAX_VALUE = - Kotlin.Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); - - - /** @type {!Kotlin.Long} */ - Kotlin.Long.MIN_VALUE = Kotlin.Long.fromBits(0, 0x80000000 | 0); - - - /** - * @type {!Kotlin.Long} - * @private - */ - Kotlin.Long.TWO_PWR_24_ = Kotlin.Long.fromInt(1 << 24); - - - /** @return {number} The value, assuming it is a 32-bit integer. */ - Kotlin.Long.prototype.toInt = function() { - return this.low_; - }; - - - /** @return {number} The closest floating-point representation to this value. */ - Kotlin.Long.prototype.toNumber = function() { - return this.high_ * Kotlin.Long.TWO_PWR_32_DBL_ + - this.getLowBitsUnsigned(); - }; - - /** @return {number} The 32-bit hashCode of this value. */ - Kotlin.Long.prototype.hashCode = function() { - return this.high_ ^ this.low_; - }; - - /** - * @param {number=} opt_radix The radix in which the text should be written. - * @return {string} The textual representation of this value. - * @override - */ - Kotlin.Long.prototype.toString = function(opt_radix) { - var radix = opt_radix || 10; - if (radix < 2 || 36 < radix) { - throw Error('radix out of range: ' + radix); - } - - if (this.isZero()) { - return '0'; - } - - if (this.isNegative()) { - if (this.equals(Kotlin.Long.MIN_VALUE)) { - // We need to change the Long value before it can be negated, so we remove - // the bottom-most digit in this base and then recurse to do the rest. - var radixLong = Kotlin.Long.fromNumber(radix); - var div = this.div(radixLong); - var rem = div.multiply(radixLong).subtract(this); - return div.toString(radix) + rem.toInt().toString(radix); - } else { - return '-' + this.negate().toString(radix); - } - } - - // Do several (6) digits each time through the loop, so as to - // minimize the calls to the very expensive emulated div. - var radixToPower = Kotlin.Long.fromNumber(Math.pow(radix, 6)); - - var rem = this; - var result = ''; - while (true) { - var remDiv = rem.div(radixToPower); - var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); - var digits = intval.toString(radix); - - rem = remDiv; - if (rem.isZero()) { - return digits + result; - } else { - while (digits.length < 6) { - digits = '0' + digits; - } - result = '' + digits + result; - } - } - }; - - - /** @return {number} The high 32-bits as a signed value. */ - Kotlin.Long.prototype.getHighBits = function() { - return this.high_; - }; - - - /** @return {number} The low 32-bits as a signed value. */ - Kotlin.Long.prototype.getLowBits = function() { - return this.low_; - }; - - - /** @return {number} The low 32-bits as an unsigned value. */ - Kotlin.Long.prototype.getLowBitsUnsigned = function() { - return (this.low_ >= 0) ? - this.low_ : Kotlin.Long.TWO_PWR_32_DBL_ + this.low_; - }; - - - /** - * @return {number} Returns the number of bits needed to represent the absolute - * value of this Long. - */ - Kotlin.Long.prototype.getNumBitsAbs = function() { - if (this.isNegative()) { - if (this.equals(Kotlin.Long.MIN_VALUE)) { - return 64; - } else { - return this.negate().getNumBitsAbs(); - } - } else { - var val = this.high_ != 0 ? this.high_ : this.low_; - for (var bit = 31; bit > 0; bit--) { - if ((val & (1 << bit)) != 0) { - break; - } - } - return this.high_ != 0 ? bit + 33 : bit + 1; - } - }; - - - /** @return {boolean} Whether this value is zero. */ - Kotlin.Long.prototype.isZero = function() { - return this.high_ == 0 && this.low_ == 0; - }; - - - /** @return {boolean} Whether this value is negative. */ - Kotlin.Long.prototype.isNegative = function() { - return this.high_ < 0; - }; - - - /** @return {boolean} Whether this value is odd. */ - Kotlin.Long.prototype.isOdd = function() { - return (this.low_ & 1) == 1; - }; - - - /** - * @param {Kotlin.Long} other Long to compare against. - * @return {boolean} Whether this Long equals the other. - */ - Kotlin.Long.prototype.equals = function(other) { - return (this.high_ == other.high_) && (this.low_ == other.low_); - }; - - - /** - * @param {Kotlin.Long} other Long to compare against. - * @return {boolean} Whether this Long does not equal the other. - */ - Kotlin.Long.prototype.notEquals = function(other) { - return (this.high_ != other.high_) || (this.low_ != other.low_); - }; - - - /** - * @param {Kotlin.Long} other Long to compare against. - * @return {boolean} Whether this Long is less than the other. - */ - Kotlin.Long.prototype.lessThan = function(other) { - return this.compare(other) < 0; - }; - - - /** - * @param {Kotlin.Long} other Long to compare against. - * @return {boolean} Whether this Long is less than or equal to the other. - */ - Kotlin.Long.prototype.lessThanOrEqual = function(other) { - return this.compare(other) <= 0; - }; - - - /** - * @param {Kotlin.Long} other Long to compare against. - * @return {boolean} Whether this Long is greater than the other. - */ - Kotlin.Long.prototype.greaterThan = function(other) { - return this.compare(other) > 0; - }; - - - /** - * @param {Kotlin.Long} other Long to compare against. - * @return {boolean} Whether this Long is greater than or equal to the other. - */ - Kotlin.Long.prototype.greaterThanOrEqual = function(other) { - return this.compare(other) >= 0; - }; - - - /** - * Compares this Long with the given one. - * @param {Kotlin.Long} other Long to compare against. - * @return {number} 0 if they are the same, 1 if the this is greater, and -1 - * if the given one is greater. - */ - Kotlin.Long.prototype.compare = function(other) { - if (this.equals(other)) { - return 0; - } - - var thisNeg = this.isNegative(); - var otherNeg = other.isNegative(); - if (thisNeg && !otherNeg) { - return -1; - } - if (!thisNeg && otherNeg) { - return 1; - } - - // at this point, the signs are the same, so subtraction will not overflow - if (this.subtract(other).isNegative()) { - return -1; - } else { - return 1; - } - }; - - - /** @return {!Kotlin.Long} The negation of this value. */ - Kotlin.Long.prototype.negate = function() { - if (this.equals(Kotlin.Long.MIN_VALUE)) { - return Kotlin.Long.MIN_VALUE; - } else { - return this.not().add(Kotlin.Long.ONE); - } - }; - - - /** - * Returns the sum of this and the given Long. - * @param {Kotlin.Long} other Long to add to this one. - * @return {!Kotlin.Long} The sum of this and the given Long. - */ - Kotlin.Long.prototype.add = function(other) { - // Divide each number into 4 chunks of 16 bits, and then sum the chunks. - - var a48 = this.high_ >>> 16; - var a32 = this.high_ & 0xFFFF; - var a16 = this.low_ >>> 16; - var a00 = this.low_ & 0xFFFF; - - var b48 = other.high_ >>> 16; - var b32 = other.high_ & 0xFFFF; - var b16 = other.low_ >>> 16; - var b00 = other.low_ & 0xFFFF; - - var c48 = 0, c32 = 0, c16 = 0, c00 = 0; - c00 += a00 + b00; - c16 += c00 >>> 16; - c00 &= 0xFFFF; - c16 += a16 + b16; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c32 += a32 + b32; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c48 += a48 + b48; - c48 &= 0xFFFF; - return Kotlin.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); - }; - - - /** - * Returns the difference of this and the given Long. - * @param {Kotlin.Long} other Long to subtract from this. - * @return {!Kotlin.Long} The difference of this and the given Long. - */ - Kotlin.Long.prototype.subtract = function(other) { - return this.add(other.negate()); - }; - - - /** - * Returns the product of this and the given long. - * @param {Kotlin.Long} other Long to multiply with this. - * @return {!Kotlin.Long} The product of this and the other. - */ - Kotlin.Long.prototype.multiply = function(other) { - if (this.isZero()) { - return Kotlin.Long.ZERO; - } else if (other.isZero()) { - return Kotlin.Long.ZERO; - } - - if (this.equals(Kotlin.Long.MIN_VALUE)) { - return other.isOdd() ? Kotlin.Long.MIN_VALUE : Kotlin.Long.ZERO; - } else if (other.equals(Kotlin.Long.MIN_VALUE)) { - return this.isOdd() ? Kotlin.Long.MIN_VALUE : Kotlin.Long.ZERO; - } - - if (this.isNegative()) { - if (other.isNegative()) { - return this.negate().multiply(other.negate()); - } else { - return this.negate().multiply(other).negate(); - } - } else if (other.isNegative()) { - return this.multiply(other.negate()).negate(); - } - - // If both longs are small, use float multiplication - if (this.lessThan(Kotlin.Long.TWO_PWR_24_) && - other.lessThan(Kotlin.Long.TWO_PWR_24_)) { - return Kotlin.Long.fromNumber(this.toNumber() * other.toNumber()); - } - - // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products. - // We can skip products that would overflow. - - var a48 = this.high_ >>> 16; - var a32 = this.high_ & 0xFFFF; - var a16 = this.low_ >>> 16; - var a00 = this.low_ & 0xFFFF; - - var b48 = other.high_ >>> 16; - var b32 = other.high_ & 0xFFFF; - var b16 = other.low_ >>> 16; - var b00 = other.low_ & 0xFFFF; - - var c48 = 0, c32 = 0, c16 = 0, c00 = 0; - c00 += a00 * b00; - c16 += c00 >>> 16; - c00 &= 0xFFFF; - c16 += a16 * b00; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c16 += a00 * b16; - c32 += c16 >>> 16; - c16 &= 0xFFFF; - c32 += a32 * b00; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c32 += a16 * b16; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c32 += a00 * b32; - c48 += c32 >>> 16; - c32 &= 0xFFFF; - c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; - c48 &= 0xFFFF; - return Kotlin.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); - }; - - - /** - * Returns this Long divided by the given one. - * @param {Kotlin.Long} other Long by which to divide. - * @return {!Kotlin.Long} This Long divided by the given one. - */ - Kotlin.Long.prototype.div = function(other) { - if (other.isZero()) { - throw Error('division by zero'); - } else if (this.isZero()) { - return Kotlin.Long.ZERO; - } - - if (this.equals(Kotlin.Long.MIN_VALUE)) { - if (other.equals(Kotlin.Long.ONE) || - other.equals(Kotlin.Long.NEG_ONE)) { - return Kotlin.Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE - } else if (other.equals(Kotlin.Long.MIN_VALUE)) { - return Kotlin.Long.ONE; - } else { - // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. - var halfThis = this.shiftRight(1); - var approx = halfThis.div(other).shiftLeft(1); - if (approx.equals(Kotlin.Long.ZERO)) { - return other.isNegative() ? Kotlin.Long.ONE : Kotlin.Long.NEG_ONE; - } else { - var rem = this.subtract(other.multiply(approx)); - var result = approx.add(rem.div(other)); - return result; - } - } - } else if (other.equals(Kotlin.Long.MIN_VALUE)) { - return Kotlin.Long.ZERO; - } - - if (this.isNegative()) { - if (other.isNegative()) { - return this.negate().div(other.negate()); - } else { - return this.negate().div(other).negate(); - } - } else if (other.isNegative()) { - return this.div(other.negate()).negate(); - } - - // Repeat the following until the remainder is less than other: find a - // floating-point that approximates remainder / other *from below*, add this - // into the result, and subtract it from the remainder. It is critical that - // the approximate value is less than or equal to the real value so that the - // remainder never becomes negative. - var res = Kotlin.Long.ZERO; - var rem = this; - while (rem.greaterThanOrEqual(other)) { - // Approximate the result of division. This may be a little greater or - // smaller than the actual value. - var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); - - // We will tweak the approximate result by changing it in the 48-th digit or - // the smallest non-fractional digit, whichever is larger. - var log2 = Math.ceil(Math.log(approx) / Math.LN2); - var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); - - // Decrease the approximation until it is smaller than the remainder. Note - // that if it is too large, the product overflows and is negative. - var approxRes = Kotlin.Long.fromNumber(approx); - var approxRem = approxRes.multiply(other); - while (approxRem.isNegative() || approxRem.greaterThan(rem)) { - approx -= delta; - approxRes = Kotlin.Long.fromNumber(approx); - approxRem = approxRes.multiply(other); - } - - // We know the answer can't be zero... and actually, zero would cause - // infinite recursion since we would make no progress. - if (approxRes.isZero()) { - approxRes = Kotlin.Long.ONE; - } - - res = res.add(approxRes); - rem = rem.subtract(approxRem); - } - return res; - }; - - - /** - * Returns this Long modulo the given one. - * @param {Kotlin.Long} other Long by which to mod. - * @return {!Kotlin.Long} This Long modulo the given one. - */ - Kotlin.Long.prototype.modulo = function(other) { - return this.subtract(this.div(other).multiply(other)); - }; - - - /** @return {!Kotlin.Long} The bitwise-NOT of this value. */ - Kotlin.Long.prototype.not = function() { - return Kotlin.Long.fromBits(~this.low_, ~this.high_); - }; - - - /** - * Returns the bitwise-AND of this Long and the given one. - * @param {Kotlin.Long} other The Long with which to AND. - * @return {!Kotlin.Long} The bitwise-AND of this and the other. - */ - Kotlin.Long.prototype.and = function(other) { - return Kotlin.Long.fromBits(this.low_ & other.low_, - this.high_ & other.high_); - }; - - - /** - * Returns the bitwise-OR of this Long and the given one. - * @param {Kotlin.Long} other The Long with which to OR. - * @return {!Kotlin.Long} The bitwise-OR of this and the other. - */ - Kotlin.Long.prototype.or = function(other) { - return Kotlin.Long.fromBits(this.low_ | other.low_, - this.high_ | other.high_); - }; - - - /** - * Returns the bitwise-XOR of this Long and the given one. - * @param {Kotlin.Long} other The Long with which to XOR. - * @return {!Kotlin.Long} The bitwise-XOR of this and the other. - */ - Kotlin.Long.prototype.xor = function(other) { - return Kotlin.Long.fromBits(this.low_ ^ other.low_, - this.high_ ^ other.high_); - }; - - - /** - * Returns this Long with bits shifted to the left by the given amount. - * @param {number} numBits The number of bits by which to shift. - * @return {!Kotlin.Long} This shifted to the left by the given amount. - */ - Kotlin.Long.prototype.shiftLeft = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var low = this.low_; - if (numBits < 32) { - var high = this.high_; - return Kotlin.Long.fromBits( - low << numBits, - (high << numBits) | (low >>> (32 - numBits))); - } else { - return Kotlin.Long.fromBits(0, low << (numBits - 32)); - } - } - }; - - - /** - * Returns this Long with bits shifted to the right by the given amount. - * @param {number} numBits The number of bits by which to shift. - * @return {!Kotlin.Long} This shifted to the right by the given amount. - */ - Kotlin.Long.prototype.shiftRight = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var high = this.high_; - if (numBits < 32) { - var low = this.low_; - return Kotlin.Long.fromBits( - (low >>> numBits) | (high << (32 - numBits)), - high >> numBits); - } else { - return Kotlin.Long.fromBits( - high >> (numBits - 32), - high >= 0 ? 0 : -1); - } - } - }; - - - /** - * Returns this Long with bits shifted to the right by the given amount, with - * zeros placed into the new leading bits. - * @param {number} numBits The number of bits by which to shift. - * @return {!Kotlin.Long} This shifted to the right by the given amount, with - * zeros placed into the new leading bits. - */ - Kotlin.Long.prototype.shiftRightUnsigned = function(numBits) { - numBits &= 63; - if (numBits == 0) { - return this; - } else { - var high = this.high_; - if (numBits < 32) { - var low = this.low_; - return Kotlin.Long.fromBits( - (low >>> numBits) | (high << (32 - numBits)), - high >>> numBits); - } else if (numBits == 32) { - return Kotlin.Long.fromBits(high, 0); - } else { - return Kotlin.Long.fromBits(high >>> (numBits - 32), 0); - } - } - }; - - // Support for Kotlin - Kotlin.Long.prototype.equals_za3rmp$ = function (other) { - return other instanceof Kotlin.Long && this.equals(other); - }; - - Kotlin.Long.prototype.compareTo_za3rmp$ = Kotlin.Long.prototype.compare; - - Kotlin.Long.prototype.inc = function() { - return this.add(Kotlin.Long.ONE); - }; - - Kotlin.Long.prototype.dec = function() { - return this.add(Kotlin.Long.NEG_ONE); - }; - - Kotlin.Long.prototype.valueOf = function() { - return this.toNumber(); - }; - - Kotlin.Long.prototype.unaryPlus = function() { - return this; - }; - - Kotlin.Long.prototype.unaryMinus = Kotlin.Long.prototype.negate; - Kotlin.Long.prototype.inv = Kotlin.Long.prototype.not; - - Kotlin.Long.prototype.rangeTo = function (other) { - return new Kotlin.kotlin.ranges.LongRange(this, other); - }; -}(Kotlin)); \ No newline at end of file + } + } else if (other.equals(Kotlin.Long.MIN_VALUE)) { + return Kotlin.Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = Kotlin.Long.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = Kotlin.Long.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = Kotlin.Long.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = Kotlin.Long.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; +}; + + +/** + * Returns this Long modulo the given one. + * @param {Kotlin.Long} other Long by which to mod. + * @return {!Kotlin.Long} This Long modulo the given one. + */ +Kotlin.Long.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); +}; + + +/** @return {!Kotlin.Long} The bitwise-NOT of this value. */ +Kotlin.Long.prototype.not = function() { + return Kotlin.Long.fromBits(~this.low_, ~this.high_); +}; + + +/** + * Returns the bitwise-AND of this Long and the given one. + * @param {Kotlin.Long} other The Long with which to AND. + * @return {!Kotlin.Long} The bitwise-AND of this and the other. + */ +Kotlin.Long.prototype.and = function(other) { + return Kotlin.Long.fromBits(this.low_ & other.low_, + this.high_ & other.high_); +}; + + +/** + * Returns the bitwise-OR of this Long and the given one. + * @param {Kotlin.Long} other The Long with which to OR. + * @return {!Kotlin.Long} The bitwise-OR of this and the other. + */ +Kotlin.Long.prototype.or = function(other) { + return Kotlin.Long.fromBits(this.low_ | other.low_, + this.high_ | other.high_); +}; + + +/** + * Returns the bitwise-XOR of this Long and the given one. + * @param {Kotlin.Long} other The Long with which to XOR. + * @return {!Kotlin.Long} The bitwise-XOR of this and the other. + */ +Kotlin.Long.prototype.xor = function(other) { + return Kotlin.Long.fromBits(this.low_ ^ other.low_, + this.high_ ^ other.high_); +}; + + +/** + * Returns this Long with bits shifted to the left by the given amount. + * @param {number} numBits The number of bits by which to shift. + * @return {!Kotlin.Long} This shifted to the left by the given amount. + */ +Kotlin.Long.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return Kotlin.Long.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return Kotlin.Long.fromBits(0, low << (numBits - 32)); + } + } +}; + + +/** + * Returns this Long with bits shifted to the right by the given amount. + * @param {number} numBits The number of bits by which to shift. + * @return {!Kotlin.Long} This shifted to the right by the given amount. + */ +Kotlin.Long.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Kotlin.Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return Kotlin.Long.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } +}; + + +/** + * Returns this Long with bits shifted to the right by the given amount, with + * zeros placed into the new leading bits. + * @param {number} numBits The number of bits by which to shift. + * @return {!Kotlin.Long} This shifted to the right by the given amount, with + * zeros placed into the new leading bits. + */ +Kotlin.Long.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Kotlin.Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return Kotlin.Long.fromBits(high, 0); + } else { + return Kotlin.Long.fromBits(high >>> (numBits - 32), 0); + } + } +}; + +// Support for Kotlin +Kotlin.Long.prototype.equals_za3rmp$ = function (other) { + return other instanceof Kotlin.Long && this.equals(other); +}; + +Kotlin.Long.prototype.compareTo_za3rmp$ = Kotlin.Long.prototype.compare; + +Kotlin.Long.prototype.inc = function() { + return this.add(Kotlin.Long.ONE); +}; + +Kotlin.Long.prototype.dec = function() { + return this.add(Kotlin.Long.NEG_ONE); +}; + +Kotlin.Long.prototype.valueOf = function() { + return this.toNumber(); +}; + +Kotlin.Long.prototype.unaryPlus = function() { + return this; +}; + +Kotlin.Long.prototype.unaryMinus = Kotlin.Long.prototype.negate; +Kotlin.Long.prototype.inv = Kotlin.Long.prototype.not; + +Kotlin.Long.prototype.rangeTo = function (other) { + return new Kotlin.kotlin.ranges.LongRange(this, other); +}; \ No newline at end of file diff --git a/js/js.translator/testData/merge-builtins.js b/js/js.translator/testData/merge-builtins.js deleted file mode 100644 index 5e1428d8a65..00000000000 --- a/js/js.translator/testData/merge-builtins.js +++ /dev/null @@ -1,12 +0,0 @@ -var require = (function () { - var builtins = module.exports.kotlin; - var propertyNames = Object.getOwnPropertyNames(builtins); - Kotlin.kotlin = Kotlin.kotlin || {}; - for (var i = 0; i < propertyNames.length; ++i) { - var propertyName = propertyNames[i]; - Kotlin.kotlin[propertyName] = builtins[propertyName]; - } - return function() { - return Kotlin; - } -})(); \ No newline at end of file diff --git a/js/js.translator/testData/merge.js b/js/js.translator/testData/merge.js deleted file mode 100644 index d41e5821a92..00000000000 --- a/js/js.translator/testData/merge.js +++ /dev/null @@ -1,16 +0,0 @@ -(function () { - var stdlib = module.exports; - function copyProperties(from, to) { - var propertyNames = Object.getOwnPropertyNames(from); - for (var i = 0; i < propertyNames.length; ++i) { - var propertyName = propertyNames[i]; - if (propertyName in to) { - copyProperties(from[propertyName], to[propertyName]); - } - else { - to[propertyName] = from[propertyName]; - } - } - } - copyProperties(stdlib, Kotlin); -})(); diff --git a/js/js.translator/testData/moduleEmulation.js b/js/js.translator/testData/moduleEmulation.js index 7156925fef1..4c2c17f3a1b 100644 --- a/js/js.translator/testData/moduleEmulation.js +++ b/js/js.translator/testData/moduleEmulation.js @@ -1,24 +1,29 @@ - var emulatedModules = { kotlin: kotlin }; - var module = { exports: {} }; +var emulatedModules = { kotlin: kotlin }; +var module = { exports: {} }; - function require(moduleId) { - return emulatedModules[moduleId]; +function require(moduleId) { + return emulatedModules[moduleId]; +} + +function __beginModule__() { + module.exports = {}; +} + +function __endModule__(moduleId) { + emulatedModules[moduleId] = module.exports; +} + +function define(moduleId, dependencies, body) { + var resolvedDependencies = []; + emulatedModules[moduleId] = {}; + for (var i = 0; i < dependencies.length; ++i) { + var dependencyName = dependencies[i]; + resolvedDependencies.push(emulatedModules[dependencyName === 'exports' ? moduleId : dependencyName]); } - - function __beginModule__() { - module.exports = {}; + var result = body.apply(null, resolvedDependencies); + if (result != null) { + emulatedModules[moduleId] = result; } - - function __endModule__(moduleId) { - emulatedModules[moduleId] = module.exports; - } - - function define(moduleId, dependencies, body) { - var resolvedDependencies = []; - for (var i = 0; i < dependencies.length; ++i) { - resolvedDependencies.push(emulatedModules[dependencies[i]]); - } - emulatedModules[moduleId] = body.apply(null, resolvedDependencies); - } - define.amd = {}; +} +define.amd = {};